找封閉區域 ─ findContours 函式應用
void findContours(InputOutputArray image, OutputArrayOfArrays contours,
int mode, int method, Point offset=Point());
/*
mode:
CV_RETR_EXTERNAL:只取最外層的輪廓。
CV_RETR_LIST:取得所有輪廓,不建立階層(hierarchy)。
CV_RETR_CCOMP:取得所有輪廓,儲存成兩層的階層,首階層為物件外圍,
第二階層為內部空心部分的輪廓,如果更內部有其餘物件,包含於首階層。
//若要找封閉區域,需要用此mode來做contour間的階層
CV_RETR_TREE:取得所有輪廓,以全階層的方式儲存。
method:
CV_CHAIN_APPROX_NONE:儲存所有輪廓點。
CV_CHAIN_APPROX_SIMPLE:對水平、垂直、對角線留下頭尾點,所以假如輪廓為一
矩形,只儲存對角的四個頂點。
*/
使用範例:
//部分取自opencv doc 範例
stackoverflow Recognize open and closed shapes opencv
void contour( Mat image, Mat closeArea )
{
vector[int] contours;
vector[vec4i] hierarchy;
findContours( image, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE , Point(0, 0));
Mat drawing = Mat::zeros( image.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
}
for( int i = 0; i< contours.size(); i=hierarchy[i][0] ) // iterate through each contour.
{
Rect r= boundingRect(contours[i]);
if( hierarchy[i][2] >= 0)
{
rectangle( closeArea,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10),
Scalar(0,255,0),2,8,0); //closed contour
}
imshow( "Contours", closeArea );
imshow( "drawing", drawing );
}
int main( int argc, char** argv )
{
// Load source image and convert it to gray
Mat src = imread( argv[1], 0 );
Mat thr = imread( argv[1], 1 );
imshow("src", src);
threshold(src,src, 200, 255, THRESH_BINARY);
imshow("binary", src);
contour(src,thr);
cvWaitKey(0);
return(0);
}
原圖
找到封閉區域
畫出輪廓
心得:
雖然用在這個例子上很好用,
但用在複雜的圖上,結果就有點糟糕了
findContours在這張圖上,變得像是在找connected component的感覺了
思考了一陣子,發現其實是因為物件的邊緣並無完全封閉
所以造成無法用封閉區域來找到物件位置
原圖
找封閉區域
畫出輪廓