簡易認識
出典: Wikimura
ポリライン近似から、校正パターンのフレーム(四角形)と方向マーカ(三角形)を探し出すためには、角と曲線を区別できなくてはならない。
レンズにより、フレームもマーカも歪んでしまう。単にポリラインの頂点数が4つだから四角、3つだから三角と判定できるか不安だった。 しかし、試してみたところ意外とうまくいった。 実際のカメラ校正では広角レンズも扱うかもしれないが、まずは簡易版を作ってみる。 インターフェースさえ決めておけば、後で広角にも対応させることができるはず。
パターンの黒丸や、パターン外部に四角・三角が見つかっているが、これは別途除外する。
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#define BOX_HOLE_COLOR CV_RGB( 255, 125, 0)
#define BOX_OUTLINE_COLOR CV_RGB( 255, 0, 0)
#define TRI_HOLE_COLOR CV_RGB( 0, 125, 255)
#define TRI_OUTLINE_COLOR CV_RGB( 0, 0, 255)
int main( void)
{
IplImage *src, *dst, *tmp;
IplImage *gray;
int found ;
int i;
char key;
// 輪郭・ポリライン近似
CvMemStorage *contStorage = cvCreateMemStorage(0);
CvSeq *contours;
CvMemStorage *polyStorage = cvCreateMemStorage(0);
CvSeq *polys, *poly;
CvTreeNodeIterator polyIterator;
cvNamedWindow( "Poly", CV_WINDOW_AUTOSIZE);
// 画像入力
CvCapture *capture = cvCreateCameraCapture( 0);
if( capture == 0) return -1;
src = cvQueryFrame( capture);
gray = cvCreateImage( cvGetSize( src), IPL_DEPTH_8U, 1);
tmp = cvCreateImage( cvGetSize( src), IPL_DEPTH_8U, 1);
dst = cvCreateImage( cvGetSize( src), IPL_DEPTH_8U, 3);
while( key != 'q')
{
cvQueryFrame( capture);
cvCopy( src, dst);
cvCvtColor( dst, gray, CV_BGR2GRAY);
// 二値化
cvThreshold( gray, tmp , 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
// 輪郭抽出
found = cvFindContours( tmp, contStorage, &contours, sizeof( CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
// ポリライン近似
// 許容誤差距離は適当、階層も適当
polys = cvApproxPoly( contours, sizeof( CvContour), polyStorage, CV_POLY_APPROX_DP, 10, 10);
// 表示
cvInitTreeNodeIterator( &polyIterator, ( void*)polys, 10);
while( (poly = (CvSeq *)cvNextTreeNode( &polyIterator)) != NULL)
{
switch( poly->total)
{
case 3:
cvDrawContours( dst, poly, TRI_OUTLINE_COLOR, TRI_HOLE_COLOR, 0, 3);
break;
case 4:
cvDrawContours( dst, poly, BOX_OUTLINE_COLOR, BOX_HOLE_COLOR, 0, 3);
break;
default:
break;
}
}
cvShowImage( "Poly", dst);
key = cvWaitKey( 10);
}
cvDestroyAllWindows();
cvReleaseImage( &dst);
cvReleaseImage( &gray);
cvReleaseImage( &tmp);
cvReleaseCapture( &capture);
cvReleaseMemStorage( &polyStorage);
cvReleaseMemStorage( &contStorage);
return 0;
}
パターン外形のみ抽出
ロバスト性は低いが、環境を整えれば十分使える程度の認識率なら良いと考え、難しい計算が不要な方法を考えた。
外形線は四角形であること、内側に四角形が1つだけあることを条件とした。
ポリライン近似と、その元となった輪郭の階層構造は一致している。 片方の構造を用いて走査しつつ、もう片方も追従させる。 発見てループを抜け、次の処理に移る際に、対応する輪郭が分かっている必要があるためこうした。
実行したところ、照明条件が悪く二値化に失敗したと思われる場合を除き、人の目で見えていると思える状態ならば、確実に認識できた。
cvInitTreeNodeIterator( &polyIterator, ( void*)polys, 10);
cvInitTreeNodeIterator( &contIterator, ( void*)contours, 10);
while( (poly = (CvSeq *)cvNextTreeNode( &polyIterator)) != NULL)
{
contour = (CvSeq *)cvNextTreeNode( &contIterator);
if( poly->total == 4 && poly->v_next != 0 && poly->v_next->h_next == 0 && poly->v_next->total == 4)
{
cvDrawContours( dst, poly, VIRTEX_COLOR, VIRTEX_COLOR, 0, 3);
}
}

