//---------------------------------------------------------------------
//概要		: 画像中の物体の輪郭を抽出する
//File Name	: findcontours.cpp
//Library	: OpenCV for MS-Windows 1.0
//---------------------------------------------------------------------

#include <stdio.h>
#include <cv.h>
#include <highgui.h>

#define THRESHOLD	10			//	2値化の際の閾値
#define THRESHOLD_MAX_VALUE	255	//	2値化の際に使用する最大値

#define CONTOUR_MAX_LEVEL	1	//	描画される輪郭の最大レベル
#define LINE_THICKNESS	2		//	線の太さ
#define LINE_TYPE	8			//	線の種類

int main( int argc, char** argv ) {
	char windowNameSource[] = "Source";		//	読み込んだ画像を表示するウィンドウの名前
	char windowNameContour[] = "Contour";	//	輪郭画像を表示するウィンドウの名前

	//	画像を読み込む
	IplImage *sourceImage = cvLoadImage( "image/source.bmp", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR );

	if ( sourceImage == NULL ) {
		//	画像が見つからなかった場合
		printf( "画像が見つかりません\n" );
		return -1;
	}
	//	画像を生成する
	IplImage *grayImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 );		//	グレースケール画像用IplImage
	IplImage *binaryImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 );	//	2値画像用IplImage
	IplImage *contourImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 3 );	//	輪郭画像用IplImage

	//	BGRからグレースケールに変換する
	cvCvtColor( sourceImage, grayImage, CV_BGR2GRAY );

	//	グレースケールから2値に変換する
	cvThreshold( grayImage, binaryImage, THRESHOLD, THRESHOLD_MAX_VALUE, CV_THRESH_BINARY );

	//	画像をコピーする
	contourImage = cvCloneImage( sourceImage );

	//	輪郭抽出用のメモリを確保する
	CvMemStorage* storage = cvCreateMemStorage( 0 );	//	抽出された輪郭を保存する領域
	CvSeq* find_contour = NULL;		//	輪郭へのポインタ           

	//	2値画像中の輪郭を見つけ、その数を返す
	int find_contour_num = cvFindContours( 
		binaryImage,			//	入力画像(８ビットシングルチャンネル）
		storage,				//	抽出された輪郭を保存する領域
		&find_contour,			//	一番外側の輪郭へのポインタへのポインタ
		sizeof( CvContour ),	//	シーケンスヘッダのサイズ
		CV_RETR_LIST,			//	抽出モード 
		CV_CHAIN_APPROX_NONE,	//	推定手法
		cvPoint( 0, 0 )			//	オフセット
	);

	//	物体の輪郭を赤色で描画する
	CvScalar red = CV_RGB( 255, 0, 0 );
	cvDrawContours( 
		contourImage,			//	輪郭を描画する画像
		find_contour,			//	最初の輪郭へのポインタ
		red,					//	外側輪郭線の色
		red,					//	内側輪郭線（穴）の色
		CONTOUR_MAX_LEVEL,		//	描画される輪郭の最大レベル
		LINE_THICKNESS,			//	描画される輪郭線の太さ
		LINE_TYPE,				//	線の種類
		cvPoint( 0, 0 )			//	オフセット
	);   

	//	ウィンドウを生成する
	cvNamedWindow( windowNameSource, CV_WINDOW_AUTOSIZE );
	cvNamedWindow( windowNameContour, CV_WINDOW_AUTOSIZE );

	//	画像を表示する
	cvShowImage( windowNameSource, sourceImage );
	cvShowImage( windowNameContour, contourImage );

	//	キー入力を待つ
	cvWaitKey( 0 );

	//	画像を保存する
	cvSaveImage( "image/contour.bmp", contourImage );

	//	メモリを解放する
	cvReleaseImage( &sourceImage );
	cvReleaseImage( &binaryImage );
	cvReleaseImage( &grayImage );
	cvReleaseImage( &contourImage );
	//	ウィンドウを破棄する
	cvDestroyWindow( windowNameSource );
	cvDestroyWindow( windowNameContour );

	return 0;
}