findContours函数
1、findContours函數
函數的作用:
查找圖像的輪廓
2、findContours函數,這個函數的原型為:
void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierar-
chy, int mode, int method, Point offset=Point())
參數說明
輸入圖像image必須為一個2值單通道圖像
contours參數為檢測的輪廓數組,每一個輪廓用一個point類型的vector表示
hiararchy參數和輪廓個數相同,每個輪廓contours[ i ]對應4個hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分別表示后一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號,如果沒有對應項,該值設置為負數。
mode表示輪廓的檢索模式
CV_RETR_EXTERNAL表示只檢測外輪廓
CV_RETR_LIST檢測的輪廓不建立等級關系
CV_RETR_CCOMP建立兩個等級的輪廓,上面的一層為外邊界,里面的一層為內孔的邊界信息。如果內孔內還有一個連通物體,這個物體的邊界也在頂層。
CV_RETR_TREE建立一個等級樹結構的輪廓。具體參考contours.c這個demo
method為輪廓的近似辦法
CV_CHAIN_APPROX_NONE存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1,即max(abs(x1-x2),abs(y2-y1))==1
CV_CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點坐標,例如一個矩形輪廓只需4個點來保存輪廓信息
CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
offset表示代表輪廓點的偏移量,可以設置為任意值。對ROI圖像中找出的輪廓,并要在整個圖像中進行分析時,這個參數還是很有用的。
3、
findContours后會對輸入的2值圖像改變,所以如果不想改變該2值圖像,需創建新mat來存放,findContours后的輪廓信息contours可能過于復雜不平滑,可以用approxPolyDP函數對該多邊形曲線做適當近似
contourArea函數可以得到當前輪廓包含區域的大小,方便輪廓的篩選
findContours經常與drawContours配合使用,用來將輪廓繪制出來。
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()?)
其中第一個參數image表示目標圖像,
第二個參數contours表示輸入的輪廓組,每一組輪廓由點vector構成,
第三個參數contourIdx指明畫第幾個輪廓,如果該參數為負值,則畫全部輪廓,
第四個參數color為輪廓的顏色,
第五個參數thickness為輪廓的線寬,如果為負值或CV_FILLED表示填充輪廓內部,
第六個參數lineType為線型,
第七個參數為輪廓結構信息,
第八個參數為maxLevel
得到了復雜輪廓往往不適合特征的檢測,這里再介紹一個點集凸包絡的提取函數convexHull,輸入參數就可以是contours組中的一個輪廓,返回外凸包絡的點集
還可以得到輪廓的外包絡矩形,使用函數boundingRect,如果想得到旋轉的外包絡矩形,使用函數minAreaRect,返回值為RotatedRect;也可以得到輪廓的外包絡圓,對應的函數為minEnclosingCircle;想得到輪廓的外包絡橢圓,對應的函數為fitEllipse,返回值也是RotatedRect,可以用ellipse函數畫出對應的橢圓
如果想根據多邊形的輪廓信息得到多邊形的多階矩,可以使用類moments,這個類可以得到多邊形和光柵形狀的3階以內的所有矩,類內有變量m00,m10,m01,m20,m11,m02,m30,m21,m12,m03,比如多邊形的質心為?x = m10 / m00,y = m01 / m00。
如果想獲得一點與多邊形封閉輪廓的信息,可以調用pointPolygonTest函數,這個函數返回值為該點距離輪廓最近邊界的距離,為正值為在輪廓內部,負值為在輪廓外部,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 );/// 轉成灰度并模糊化降噪cvtColor( src, src_gray, CV_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// 創建窗體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算子檢測邊緣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() );}/// 在窗體中顯示結果namedWindow( "Contours", CV_WINDOW_AUTOSIZE );imshow( "Contours", drawing ); }
或者: // test.cpp : 定義控制臺應用程序的入口點。 // #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; }
總結
以上是生活随笔為你收集整理的findContours函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HuMoments函数
- 下一篇: convexHull函数