動く物を肌色限定で検出

動く物を肌色限定で検出


参照先
元コード:動的背景更新による物体検出
一部OpenCVプログラミングブックのコードを参考にしました

一番下にファイルをアップロードしました

include <cv.h>
include <highgui.h>
include <ctype.h>
include <stdio.h>
include "hadah.h"


void extractSkinColor( IplImage *frame, IplImage *hsv_img, IplImage *skin_img ) {
CvScalar color;		//	HSV表色系で表した色
unsigned char h;	//	H成分
unsigned char s;	//	S成分
unsigned char v;	//	V成分

//	BGRからHSVに変換する
cvCvtColor( frame, hsv_img, CV_BGR2HSV );

//肌色抽出
for( int x = 0; x < skin_img->width; x++ ) {
	for( int y = 0 ; y < skin_img->height; y++ ) {

		color = cvGet2D( hsv_img, y, x );
		h = color.val[0];
		s = color.val[1];
		v = color.val[2];

		if( h <= HMAX && h >= HMIN &&
			s <= SMAX && s >= SMIN &&
				v <= VMAX && v >= VMIN ) {
			//	肌色の場合
			cvSetReal2D( skin_img, y, x, 255 );
		} else {
			cvSetReal2D( skin_img, y, x, 0 );
		}
	}
}
}



int
main (int argc, char **argv)
{
 int i, c, counter;
 int INIT_TIME = 100;
 int w = 0, h = 0;
 double B_PARAM = 1.0 / 50.0;
 double T_PARAM = 1.0 / 200.0;
 double Zeta = 10.0;
 CvCapture *capture = 0;
 IplImage *frame = 0;
 IplImage *av_img, *sgm_img;
 IplImage *lower_img, *upper_img, *tmp_img;
 IplImage *dst_img, *msk_img;
 IplImage *hsv_img;
 IplImage *skin_img;


 CvFont font;
 char str[64];

 // (1)コマンド引数によって指定された番号のカメラに対するキャプチャ構造体を作成する
 if (argc == 1 || (argc == 2 && strlen (argv[1]) == 1 && isdigit (argv[1][0])))
   capture = cvCreateCameraCapture (argc == 2 ? argv[1][0] - '0' : 0);

 // (2)1フレームキャプチャし,キャプチャサイズを取得する.
 frame = cvQueryFrame (capture);
 w = frame->width;
 h = frame->height;

 // (3)作業用の領域を生成する
 av_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
 sgm_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
 tmp_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
 lower_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
 upper_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3);
 hsv_img=cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);
 skin_img=cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
 dst_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_8U, 3);
 msk_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_8U, 1);

 // (4)背景の輝度平均の初期値を計算する
 printf ("Background statistics initialization start\n");

 cvSetZero (av_img);
 for (i = 0; i < INIT_TIME; i++) {
   frame = cvQueryFrame (capture);
   cvAcc (frame, av_img);
 }
 cvConvertScale (av_img, av_img, 1.0 / INIT_TIME);

 // (5)背景の輝度振幅の初期値を計算する
 cvSetZero (sgm_img);
 for (i = 0; i < INIT_TIME; i++) {
   frame = cvQueryFrame (capture);
   cvConvert (frame, tmp_img);
   cvSub (tmp_img, av_img, tmp_img);
   cvPow (tmp_img, tmp_img, 2.0);
   cvConvertScale (tmp_img, tmp_img, 2.0);
   cvPow (tmp_img, tmp_img, 0.5);
   cvAcc (tmp_img, sgm_img);
 }
 cvConvertScale (sgm_img, sgm_img, 1.0 / INIT_TIME);

 printf ("Background statistics initialization finish\n");

 // (6)表示用ウィンドウを生成する
 cvInitFont (&font, CV_FONT_HERSHEY_COMPLEX, 0.7, 0.7);
 cvNamedWindow ("Input", CV_WINDOW_AUTOSIZE);
 cvNamedWindow("sub",CV_WINDOW_AUTOSIZE);
 cvNamedWindow ("Substraction", CV_WINDOW_AUTOSIZE);

 // (7)取得画像から背景を分離するループ
 counter = 0;
 while (1) {
   frame = cvQueryFrame (capture);
   cvConvert (frame, tmp_img);

   // (8)背景となりうる画素の輝度値の範囲をチェックする
   cvSub (av_img, sgm_img, lower_img);
   cvSubS (lower_img, cvScalarAll (Zeta), lower_img);
   cvAdd (av_img, sgm_img, upper_img);
   cvAddS (upper_img, cvScalarAll (Zeta), upper_img);
   cvInRange (tmp_img, lower_img, upper_img, msk_img);

   // (9)輝度振幅を再計算する
   cvSub (tmp_img, av_img, tmp_img);
   cvPow (tmp_img, tmp_img, 2.0);
   cvConvertScale (tmp_img, tmp_img, 2.0);
   cvPow (tmp_img, tmp_img, 0.5);

   // (10)背景と判断された領域の背景の輝度平均と輝度振幅を更新する
   cvRunningAvg (frame, av_img, B_PARAM, msk_img);
   cvRunningAvg (tmp_img, sgm_img, B_PARAM, msk_img);

   // (11)物体領域と判断された領域では輝度振幅のみを(背景領域よりも遅い速度で)更新する
   cvNot (msk_img, msk_img);
   cvRunningAvg (tmp_img, sgm_img, T_PARAM, msk_img);

   // (12)物体領域のみを出力画像にコピーする(背景領域は黒)
   cvSetZero (dst_img);
   cvCopy (frame, dst_img, msk_img);

   // (13)処理結果を表示する
   //sprintf (str, 64, "%03d[frame]", counter);
   cvPutText (dst_img, str, cvPoint (10, 20), &font, CV_RGB (0, 255, 100));
  
   
   extractSkinColor(dst_img,hsv_img,skin_img);

   cvShowImage ("Input", frame);
   cvShowImage("sub",dst_img);
   cvShowImage ("Substraction",skin_img);

   counter++;

   c = cvWaitKey (10);
   if (c == '\x1b')
     break;
 }

 cvDestroyWindow ("Input");
 cvDestroyWindow ("Substraction");
 cvReleaseImage (&frame);
 cvReleaseImage (&dst_img);
 cvReleaseImage (&av_img);
 cvReleaseImage (&sgm_img);
 cvReleaseImage (&lower_img);
 cvReleaseImage (&upper_img);
 cvReleaseImage (&tmp_img);
 cvReleaseImage (&msk_img);

 return 0;
}

  • cvShowImage ("Substraction",skin_img);を追加して、肌色検出コードの内容を追加する -- (↑) 2009-09-28 14:15:05
  • extractSkinColor関数にskin_imgの内容がはいっている -- (maou様) 2009-09-28 14:18:59
名前:
コメント:

すべてのコメントを見る
最終更新:2009年09月28日 14:07
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。
添付ファイル