findContours函数
1、findContours函數(shù)
函數(shù)的作用:
查找圖像的輪廓
2、findContours函數(shù),這個(gè)函數(shù)的原型為:
void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierar-
chy, int mode, int method, Point offset=Point())
參數(shù)說(shuō)明
輸入圖像image必須為一個(gè)2值單通道圖像
contours參數(shù)為檢測(cè)的輪廓數(shù)組,每一個(gè)輪廓用一個(gè)point類型的vector表示
hiararchy參數(shù)和輪廓個(gè)數(shù)相同,每個(gè)輪廓contours[ i ]對(duì)應(yīng)4個(gè)hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分別表示后一個(gè)輪廓、前一個(gè)輪廓、父輪廓、內(nèi)嵌輪廓的索引編號(hào),如果沒有對(duì)應(yīng)項(xiàng),該值設(shè)置為負(fù)數(shù)。
mode表示輪廓的檢索模式
CV_RETR_EXTERNAL表示只檢測(cè)外輪廓
CV_RETR_LIST檢測(cè)的輪廓不建立等級(jí)關(guān)系
CV_RETR_CCOMP建立兩個(gè)等級(jí)的輪廓,上面的一層為外邊界,里面的一層為內(nèi)孔的邊界信息。如果內(nèi)孔內(nèi)還有一個(gè)連通物體,這個(gè)物體的邊界也在頂層。
CV_RETR_TREE建立一個(gè)等級(jí)樹結(jié)構(gòu)的輪廓。具體參考contours.c這個(gè)demo
method為輪廓的近似辦法
CV_CHAIN_APPROX_NONE存儲(chǔ)所有的輪廓點(diǎn),相鄰的兩個(gè)點(diǎn)的像素位置差不超過(guò)1,即max(abs(x1-x2),abs(y2-y1))==1
CV_CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對(duì)角線方向的元素,只保留該方向的終點(diǎn)坐標(biāo),例如一個(gè)矩形輪廓只需4個(gè)點(diǎn)來(lái)保存輪廓信息
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
offset表示代表輪廓點(diǎn)的偏移量,可以設(shè)置為任意值。對(duì)ROI圖像中找出的輪廓,并要在整個(gè)圖像中進(jìn)行分析時(shí),這個(gè)參數(shù)還是很有用的。
3、
findContours后會(huì)對(duì)輸入的2值圖像改變,所以如果不想改變?cè)?值圖像,需創(chuàng)建新mat來(lái)存放,findContours后的輪廓信息contours可能過(guò)于復(fù)雜不平滑,可以用approxPolyDP函數(shù)對(duì)該多邊形曲線做適當(dāng)近似
contourArea函數(shù)可以得到當(dāng)前輪廓包含區(qū)域的大小,方便輪廓的篩選
findContours經(jīng)常與drawContours配合使用,用來(lái)將輪廓繪制出來(lái)。
void?drawContours(InputOutputArray?image, InputArrayOfArrays?contours, int?contourIdx, const Scalar&?color, intthickness=1, int?lineType=8, InputArray?hierarchy=noArray(), int?maxLevel=INT_MAX, Point?offset=Point()?)
其中第一個(gè)參數(shù)image表示目標(biāo)圖像,
第二個(gè)參數(shù)contours表示輸入的輪廓組,每一組輪廓由點(diǎn)vector構(gòu)成,
第三個(gè)參數(shù)contourIdx指明畫第幾個(gè)輪廓,如果該參數(shù)為負(fù)值,則畫全部輪廓,
第四個(gè)參數(shù)color為輪廓的顏色,
第五個(gè)參數(shù)thickness為輪廓的線寬,如果為負(fù)值或CV_FILLED表示填充輪廓內(nèi)部,
第六個(gè)參數(shù)lineType為線型,
第七個(gè)參數(shù)為輪廓結(jié)構(gòu)信息,
第八個(gè)參數(shù)為maxLevel
得到了復(fù)雜輪廓往往不適合特征的檢測(cè),這里再介紹一個(gè)點(diǎn)集凸包絡(luò)的提取函數(shù)convexHull,輸入?yún)?shù)就可以是contours組中的一個(gè)輪廓,返回外凸包絡(luò)的點(diǎn)集
還可以得到輪廓的外包絡(luò)矩形,使用函數(shù)boundingRect,如果想得到旋轉(zhuǎn)的外包絡(luò)矩形,使用函數(shù)minAreaRect,返回值為RotatedRect;也可以得到輪廓的外包絡(luò)圓,對(duì)應(yīng)的函數(shù)為minEnclosingCircle;想得到輪廓的外包絡(luò)橢圓,對(duì)應(yīng)的函數(shù)為fitEllipse,返回值也是RotatedRect,可以用ellipse函數(shù)畫出對(duì)應(yīng)的橢圓
如果想根據(jù)多邊形的輪廓信息得到多邊形的多階矩,可以使用類moments,這個(gè)類可以得到多邊形和光柵形狀的3階以內(nèi)的所有矩,類內(nèi)有變量m00,m10,m01,m20,m11,m02,m30,m21,m12,m03,比如多邊形的質(zhì)心為?x = m10 / m00,y = m01 / m00。
如果想獲得一點(diǎn)與多邊形封閉輪廓的信息,可以調(diào)用pointPolygonTest函數(shù),這個(gè)函數(shù)返回值為該點(diǎn)距離輪廓最近邊界的距離,為正值為在輪廓內(nèi)部,負(fù)值為在輪廓外部,0表示在邊界上。
opencv代碼:
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h>using namespace cv; using namespace std;Mat src; Mat src_gray; int thresh = 100; int max_thresh = 255; RNG rng(12345);/// Function header void thresh_callback(int, void* );/** @function main */ int main( int argc, char** argv ) {/// 加載源圖像src = imread( argv[1], 1 );/// 轉(zhuǎn)成灰度并模糊化降噪cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// 創(chuàng)建窗體char* source_window = "Source";namedWindow( source_window, CV_WINDOW_AUTOSIZE );imshow( source_window, src );createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey(0);return(0); }/** @function thresh_callback */ void thresh_callback(int, void* ) {Mat canny_output;vector<vector<Point> > contours;vector<Vec4i> hierarchy;/// 用Canny算子檢測(cè)邊緣Canny( src_gray, canny_output, thresh, thresh*2, 3 );/// 尋找輪廓findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );/// 繪出輪廓Mat drawing = Mat::zeros( canny_output.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() );}/// 在窗體中顯示結(jié)果namedWindow( "Contours", CV_WINDOW_AUTOSIZE );imshow( "Contours", drawing ); }
或者: // test.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。 // #include "stdafx.h" #include "stdio.h" #include "cv.h" #include "highgui.h" #include "Math.h" int _tmain(int argc, _TCHAR* argv[]) { IplImage *src = cvLoadImage("c:\\temp.jpg", 0); IplImage *dsw = cvCreateImage(cvGetSize(src), 8, 1); IplImage *dst = cvCreateImage(cvGetSize(src), 8, 3); CvMemStorage *storage = cvCreateMemStorage(0); CvSeq *first_contour = NULL; //turn the src image to a binary image //cvThreshold(src, dsw, 125, 255, CV_THRESH_BINARY_INV); cvThreshold(src, dsw, 100, 255, CV_THRESH_BINARY); cvFindContours(dsw, storage, &first_contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); cvZero(dst); int cnt = 0; for(; first_contour != 0; first_contour = first_contour->h_next) { cnt++; CvScalar color = CV_RGB(rand()&255, rand()&255, rand()&255); cvDrawContours(dst, first_contour, color, color, 0, 2, CV_FILLED, cvPoint(0, 0)); CvRect rect = cvBoundingRect(first_contour,0);cvRectangle(dst, cvPoint(rect.x, rect.y), cvPoint(rect.x + rect.width, rect.y + rect.height),CV_RGB(255, 0, 0), 1, 8, 0);} printf("the num of contours : %d\n", cnt); cvNamedWindow( "Source", 1 ); cvShowImage( "Source", src ); cvNamedWindow( "dsw", 1 ); cvShowImage( "dsw", dsw ); cvNamedWindow( "Components", 1 ); cvShowImage( "Components", dst ); cvReleaseMemStorage(&storage); cvWaitKey(-1); return 0; }
總結(jié)
以上是生活随笔為你收集整理的findContours函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: HuMoments函数
- 下一篇: convexHull函数