輪郭の情報を抽出する
2013年1月13日:OpenCV
前に輪郭を抽出するプログラムを作成しました。 今回は、抽出した輪郭の情報を取り出す方法を紹介します。 画像としては以下の画像を使います。
まず、前回のプログラムを以下のように改造します。
プログラム
#import "AppDelegate.h" @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Insert code here to initialize your application cvNamedWindow("window",1); } -(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app{ cvReleaseImage(&image); cvDestroyWindow("window"); return NSTerminateNow; } - (IBAction)Button:(NSButton *)sender { NSOpenPanel *openPanel=[NSOpenPanel openPanel]; NSArray *allowedFileTypes=[NSArray arrayWithObjects:@"png",@"PNG",nil]; [openPanel setAllowedFileTypes:allowedFileTypes]; NSInteger pressButton=[openPanel runModal]; if(pressButton==NSOKButton){ NSURL * filePath=[openPanel URL]; NSString* fileName=[filePath path]; const char* path=[fileName UTF8String]; image=cvLoadImage(path,CV_LOAD_IMAGE_ANYCOLOR); if(image==NULL){ NSLog(@"Not Read"); }else{ //ここからが本題です。 //グレースケール用のIplImageを用意する IplImage *img_gray; img_gray=cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1); //青色だけを取り出す for(int j=0;jheight;j++){ for(int i=0;iwidth;i++){ //青色の画素をグレースケールへ移す img_gray->imageData[img_gray->widthStep*j+i]=image->imageData[image->widthStep*j+i*3]; } } //二値化する(大津の方法) cvThreshold(img_gray, img_gray, 0, 255, CV_THRESH_BINARY|CV_THRESH_OTSU); //輪郭を抽出する //メモリストレージの確保 CvMemStorage* storage=cvCreateMemStorage(0); CvSeq* contours; int nCont=cvFindContours(img_gray,storage,&contours,sizeof(CvContour),CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0)); NSLog(@"輪郭数=%d",nCont); //ここから追加************* CvRect rect; rect=cvBoundingRect(contours,0); cvRectangle(image,cvPoint(rect.x,rect.y),cvPoint(rect.x+rect.width,rect.y+rect.height),CV_RGB(0,255,0),1,CV_AA,0); double length; length=cvArcLength(contours,CV_WHOLE_SEQ,1); NSLog(@"周長=%f",length); double area; area=cvContourArea(contours, CV_WHOLE_SEQ, 0); NSLog(@"面積=%f",area); //*********************** cvDrawContours(image,contours,CV_RGB(255,0,0),CV_RGB(0,255,0),1,2,CV_AA,cvPoint(0,0)); cvShowImage("window",image); } } } @end
解説
以下の命令で輪郭を囲む四角形の情報を得ることができます。
CvRect cvBoundingRect( CvArr* points, //点列データ int update //更新フラグ );
このプログラムで得られた情報から、実際に四角形を描写しています。 輪郭の周長は以下の命令で得ることができます。
double cvArcLength( const void* curve, //輪郭データ CvSlice slice, //曲線の始点と終点 int is_closed //曲線が閉じているかどうかのフラグ );
最後に面積は以下の命令から得ることができます。
double cvContourArea( const CvArr* contour, //輪郭データ CvSlice slice, //輪郭の始点と終点 int oriented );
輪郭の周長と面積がわかれば、これらを利用することで形を分類できます。 例えば、円なら 面積/周の自乗= となります。 いろいろ活用してみてください。
著者:安井 真人(やすい まさと)
@yasui_masatoさんをフォロー