findContours函数

来源:互联网 发布:大专php电商网站教程 编辑:程序博客网 时间:2024/04/29 23:35

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 headervoid 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;  }  

0 0
原创粉丝点击