OpenCVで色認識

OpenCVのサンプルをいじって簡単な色認識を作ってみた。
大まかな処理の流れ。


1.Webカメラの映像を画像として取り込む。
2.取り込んだ画像をRGBからHSVに変換する。
3.HSV色空間内の特定の範囲だけマスキングして表示する。


HSVの方が特定の色を抜き取りやすいらしい。
http://render.s73.xrea.com/pipe_render/2008/06/artoolkit-hsv.html

こんな感じに一定の範囲の色を認識させる。

実行結果はこんな感じ。

ソースコード

#include 
#include 


void GetMaskHSV(IplImage* src, IplImage* mask,int erosions, int dilations)
{
	int x = 0, y = 0;
	uchar H, S, V;
	uchar minH, minS, minV, maxH, maxS, maxV;

	CvPixelPosition8u pos_src, pos_dst;
	uchar* p_src;
	uchar* p_dst;
	IplImage* tmp;


	tmp = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);

	//HSVに変換
	cvCvtColor(src, tmp, CV_RGB2HSV);

	CV_INIT_PIXEL_POS(pos_src, (unsigned char*) tmp->imageData,
					   tmp->widthStep,cvGetSize(tmp), x, y, tmp->origin);

	CV_INIT_PIXEL_POS(pos_dst, (unsigned char*) mask->imageData,
					   mask->widthStep, cvGetSize(mask), x, y, mask->origin);

	minH = 100;	maxH = 115;
	minS = 80;	maxS = 255;
	minV = 120;	maxV = 255;
	for(y = 0; y < tmp->height; y++) {
		for(x = 0; x < tmp->width; x++) {
			p_src = CV_MOVE_TO(pos_src, x, y, 3);
			p_dst = CV_MOVE_TO(pos_dst, x, y, 3);

			H = p_src[0];	//0から180
			S = p_src[1];
			V = p_src[2];

			if( minH <= H && H <= maxH &&
				minS <= S && S <= maxS &&
				minV <= V && V <= maxV
			) {
				p_dst[0] = 255;
				p_dst[1] = 255;
				p_dst[2] = 255;
			} else {
				p_dst[0] = 0;
				p_dst[1] = 0;
				p_dst[2] = 0;
			}
		}
	}

	if(erosions > 0)  cvErode(mask, mask, 0, erosions);
	if(dilations > 0) cvDilate(mask, mask, 0, dilations);

	cvReleaseImage(&tmp);
}


int main(int argc, char **argv)
{
	int c;
	CvCapture* capture = 0;
	IplImage* frame = 0;
	IplImage* mask = 0;
	IplImage* dst = 0;

	if(argc == 1 || (argc == 2 && strlen (argv[1]) == 1 && isdigit(argv[1][0])))
		capture = cvCreateCameraCapture(argc == 2 ? argv[1][0] - '0' : 0);

	frame = cvQueryFrame(capture);
	mask = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
	dst = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);

	cvNamedWindow("src", CV_WINDOW_AUTOSIZE);
	cvNamedWindow("dst", CV_WINDOW_AUTOSIZE);

	while(1) {
		frame = cvQueryFrame(capture);
		GetMaskHSV(frame, mask, 1, 1);
		cvAnd(frame, mask, dst);

		cvShowImage("src", frame);
		cvShowImage("dst", dst);
		c = cvWaitKey(10);
		if(c == 'q') break;
	}

	cvDestroyWindow("src");
	cvDestroyWindow("dst");

	cvReleaseImage(&frame);
	cvReleaseImage(&dst);
	cvReleaseImage(&mask);
	cvReleaseCapture(&capture);

	return(0);
}

参考にしたサンプルはこちら。
http://opencv.jp/sample/accumulation_of_background.html
http://chihara.naist.jp/opencv/?%BF%A7%BE%F0%CA%F3%A4%CB%A4%E8%A4%EB%CE%CE%B0%E8%C3%EA%BD%D0