2010/06/03

画像の輪郭抽出

おひさしぶりです。

Lost Planet2が発売されてたのでそっちをずっとやってました。
ひとまずHardもクリアしたのでOpenCVに戻ります。


今日はオライリーのOpenCV本を読みつつ、輪郭抽出で遊んでみました。

輪郭抽出にかける画像は下記のようなものを用意しました。
マーカーはARToolKitで使われている形式のモノです。
それを部屋の画像(画像検索で適当に探しました)に貼り付けてます。



これに輪郭抽出をかけると、10msぐらいで輪郭の抽出が出来ました。
輪郭だけを描画したものが下の画像になります。


この画像のうち、青が外側の輪郭で、緑が内側の輪郭となります。

以前やっていたチェスボード検出で使ったFindChessboardCornersの場合は、場所と傾きを正確に計算してくれるのですが、1フレーム処理するのに100ms~200msかかるので動画をリアルタイムで処理するには向いてなさそうです。(速いマシンを使えば別でしょうけども。。)


輪郭検出の場合は、10msぐらいで処理できるようなので、この輪郭抽出を応用できないかな~と考えてます。

今日のコードは以下のような感じです。


//////////////////////////////////////
// 
// OpenCVで遊ぼう!
// http://playwithopencv.blogspot.com/
//
//rinkaku.cpp
//画像から輪郭を抽出します。
//
//処理の概要
//1.画像を読み込み、グレイスケールに変換して輪郭を抽出します。
//2.その後、輪郭を1つずつ表示していきます。
//
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"

using namespace System;

int main(array<System::String ^> ^args)
{
    IplImage * image;
 IplImage* gsImage;
 IplImage* colorImage;

 double process_time;
 image=cvLoadImage("c:\\rinkaku.png",1);

 gsImage=cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
 colorImage=cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,3);

 cvNamedWindow("window",1);

 //輪郭保存用のストレージを確保
 CvMemStorage *storage = cvCreateMemStorage (0);
 CvSeq *firstcontour=NULL; 
 
 cvCvtColor(image,gsImage,CV_BGR2GRAY);
 process_time = (double)cvGetTickCount();
 
 //輪郭を探します。Ncには探した輪郭の数が入ります。
 //CV_RETR_LISTに設定すると、見つけた輪郭がすべて同じレベルに入ります。。
 //first=輪郭1⇔輪郭2⇔輪郭3⇔輪郭4
 //これだと内側と外側の両方の輪郭が同じレベルに入るので、外側だけほしい場合はCV_LETR_CCOMPに設定します。
 
 int Nc=cvFindContours (gsImage, storage, &firstcontour, sizeof (CvContour), CV_RETR_LIST);
 process_time = (double)cvGetTickCount()-process_time;
 printf("process_time %gms\n", process_time/(cvGetTickFrequency()*1000.)); 
 printf("MODE:CV_RETR_LIST ",Nc);
 printf("Total Contour %d\n",Nc);
 
 int n=0;
 
 //輪郭を1つずつ取り出して描画します。
 for(CvSeq * seq=firstcontour;seq!=NULL;seq=seq->h_next)
 {
  colorImage=cvCloneImage(image);
  cvDrawContours(colorImage,seq,cvScalar(255,0,0),cvScalar(0,255,0),0,2,8);
 
  printf("Contour no:%d\n",n);
  cvShowImage("window",colorImage);

  for(int i=0;i<seq->total;i++)
  {
   CvPoint* p=CV_GET_SEQ_ELEM(CvPoint,seq,i);
   printf(" (%d %d)\n",p->x,p->y);

  }
  cvWaitKey(0);
  n++;
 }
 cvReleaseImage(&image);
 cvReleaseImage(&gsImage);
 cvDestroyWindow("window");
 return 0;
}

ではまた。

0 件のコメント:

コメントを投稿