2010/06/20

OpenCV 色相情報の抽出

マーカー認識の次は物体認識と物体追跡を試してみることに。

物体認識には、形状の特徴をベースにしたものと、色情報をベースにしたものがあるようで、今回は色情報のものからやってみることにしました。

下準備として、特定の色を抽出するプログラムを作ってみました。

色情報で判断する場合、通常使用しているRGBだとどの色かがわかりにくいため、HSVに変換して処理しています。
HSVは色相、彩度、明度からなっているので、色相(H)だけ調査すればどの色かがわかります。(細かくはWikipediaを参照ください)

下記の動画は、表示する色相を0度から360度まで変化させたものです。
(OpenCVでは0~180で色相が一周していました)




家の中をWebカメラで色々写したところ、我が家では黄色か黄緑成分が少ないので
対象物の色は黄色か黄緑にすることにしました。
逆に、赤と青はそこらじゅうにあったため、このあたりの色は適さない模様です。
(壁、肌は赤成分に反応し、髪の毛や黒は青成分で反応してました)


今回のコードは短いのでこちらに掲載します。

//////////////////////////////////////
// 
// OpenCVで遊ぼう!
// http://playwithopencv.blogspot.com/
//
//hsv.cpp

//カラー画像を読み込み、BGR画像からHSV画像に変換し、
//特定の色相だけ抽出したものを表示します。

//色による物体追跡用のマスクとして使用する予定です。

#include "cv.h"
#include "highgui.h"
#include 

int main(int argc, char** argv)
{
 IplImage * source;
 source=cvLoadImage("HSV.png",1);
 if(source==NULL) return -1;

 IplImage * hsvimage;
 IplImage * bgrimage;
 IplImage * hueimage;
 IplImage * simage;
 IplImage * vimage;
 
 hsvimage=cvCreateImage(cvGetSize(source),IPL_DEPTH_8U,3);
 bgrimage=cvCreateImage(cvGetSize(source),IPL_DEPTH_8U,3);
 //H S Vの3つに分けるためのスペースを確保
 hueimage=cvCreateImage(cvGetSize(source),IPL_DEPTH_8U,1);
 simage=cvCreateImage(cvGetSize(source),IPL_DEPTH_8U,1);
 vimage=cvCreateImage(cvGetSize(source),IPL_DEPTH_8U,1);

 cvNamedWindow("orig");
 cvNamedWindow("result");
 
 int hue=0;   //0から180まで
 int huestep=1; //hueの増加・減少単位。
 int huerange=1; //許容する範囲。1以上にしてください。
 
 
 char pressd;

 //フォントの設定
 CvFont dfont;
 float hscale      = 0.5f;
 float vscale      = 0.5f;
 float italicscale = 0.0f;
 int  thickness    = 1;
 char text[255] = "";
 cvInitFont (&dfont, CV_FONT_HERSHEY_SIMPLEX , hscale, vscale, italicscale, thickness, CV_AA); 

 while(1)
 {
  
   cvCvtColor(source,hsvimage,CV_BGR2HSV);
 
   //Hue成分のみ抽出。
   cvSplit(hsvimage,hueimage,NULL,NULL,NULL);

   //現在のHue+許容範囲以上を切り捨てる
   //CV_THRESH_TOZERO_INVは、閾値以上の値を0にするフラグ。
   cvThreshold(hueimage,hueimage,hue+huerange,hue,CV_THRESH_TOZERO_INV);
 
   //現在のHue-許容範囲以下を0にする
   cvThreshold(hueimage,hueimage,hue-huerange,hue,CV_THRESH_BINARY);
   
   cvZero(simage);
   cvZero(vimage);
      
   cvOrS(simage,cvScalarAll(255),simage,hueimage);
   cvOrS(vimage,cvScalarAll(255),vimage,hueimage);

  
   //H S Vを合体させる
   cvMerge(hueimage,simage,vimage,NULL,hsvimage);
   cvCvtColor(hsvimage,bgrimage,CV_HSV2BGR);
 
   
   //OpenCVは0-180°でHueを扱っているが、本来は0-360°なので2倍しておく
   sprintf(text,"hue %d",hue*2);
   cvPutText(bgrimage,text,cvPoint(bgrimage->width/2,bgrimage->height-30),&dfont,CV_RGB(255,255,255));

   cvShowImage("orig",source);
   cvShowImage("result",bgrimage);

   pressd=cvWaitKey(100);
   if(pressd==27) break;

   if(hue>180) hue=0;
   hue++;
  
 }

 cvReleaseImage (&hsvimage);
 cvReleaseImage (&bgrimage);
 cvReleaseImage (&hueimage);
 cvReleaseImage (&simage);
 cvReleaseImage (&vimage);
 cvDestroyWindow("orig");
 cvDestroyWindow("result");
}

物体追跡のよい参考書がなかなか見つかりません。。。
Webで調べるしかないのかな~


ではまた。

0 件のコメント:

コメントを投稿