1、drawContours函数的作用
主要用于画出图像的轮廓
2、函数的调用形式
void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )
函数参数详解:
其中第一个参数image表示目标图像,
第二个参数contours表示输入的轮廓组,每一组轮廓由点vector构成,
第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓,
第四个参数color为轮廓的颜色,
第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,
第六个参数lineType为线型,
第七个参数为轮廓结构信息,
第八个参数为maxLevel
opencv代码:
#include "cv.h" #include "highgui.h" using namespace cv; int main( int argc, char** argv ) { Mat src; // the first command-line parameter must be a filename of the binary // (black-n-white) image if( argc != 2 || !(src=imread(argv[1], 0)).data) return -1; Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3); src = src > 1; namedWindow( "Source", 1 ); imshow( "Source", src ); vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours( src, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); // iterate through all the top-level contours, // draw each connected component with its own random color int idx = 0; for( ; idx >= 0; idx = hierarchy[idx][0] ) { Scalar color( rand()&255, rand()&255, rand()&255 ); drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy ); } namedWindow( "Components", 1 ); imshow( "Components", dst ); waitKey(0); }
提取到轮廓后,其实我们更关心的是如果把这些轮廓转换为可以利用的特征,也就是涉及到轮廓的描述问题,这时就有多种方法可以选择,比如矢量化为多边形、矩形、椭圆等。OpenCV里提供了一些这样的函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
// 轮廓表示为一个矩形
Rect r = boundingRect(Mat(contours[0]));
rectangle(result, r, Scalar(255), 2);
// 轮廓表示为一个圆
float
radius;
Point2f center;
minEnclosingCircle(Mat(contours[1]), center, radius);
circle(result, Point(center),
static_cast
<
int
>(radius), Scalar(255), 2);
// 轮廓表示为一个多边形
vector
approxPolyDP(Mat(contours[2]), poly, 5,
true
);
vector
while
(itp != (poly.end() - 1))
{
line(result, *itp, *(itp + 1), Scalar(255), 2);
++itp;
}
line(result, *itp, *(poly.begin()), Scalar(255), 2);
// 轮廓表示为凸多边形
vector
convexHull(Mat(contours[3]), hull);
vector
while
(ith != (hull.end() - 1))
{
line(result, *ith, *(ith + 1), Scalar(255), 2);
++ith;
}
line(result, *ith, *(hull.begin()), Scalar(255), 2);
|
对连通区域的分析到此远远没有结束,我们可以进一步计算每一个连通区域的其他属性,比如:重心、中心矩等特征,这些内容以后有机会展开来写。
以下几个函数可以尝试:minAreaRect:计算一个最小面积的外接矩形,contourArea可以计算轮廓内连通区域的面积;pointPolygenTest可以用来判断一个点是否在一个多边形内。mathShapes可以比较两个形状的相似性,相当有用的一个函数。