主要内容:对比新旧函数,用于过滤原始图像中轮廓分析后较小的区域,留下较大区域。
关键字:connectedComponentsWithStats
在以前,常用的方法是”是先调用 cv::findContours() 函数(传入cv::RETR_CCOMP 标志),随后在得到的连通区域上循环调用 cv::drawContours() “
比如,我在GOCVHelper中这样进行了实现
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
31
32
33
|
/ / 寻找最大的轮廓 VP FindBigestContour(Mat src){ int imax = 0 ; / / 代表最大轮廓的序号 int imaxcontour = - 1 ; / / 代表最大轮廓的大小 std::vector<std::vector<Point>>contours; findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE); for ( int i = 0 ;i<contours.size();i + + ){ int itmp = contourArea(contours[i]); / / 这里采用的是轮廓大小 if (imaxcontour < itmp ){ imax = i; imaxcontour = itmp; } } return contours[imax]; } / / 寻找并绘制出彩色联通区域 vector<VP> connection2(Mat src,Mat& draw){ draw = Mat::zeros(src.rows,src.cols,CV_8UC3); vector<VP>contours; findContours(src.clone(),contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE); / / 由于给大的区域着色会覆盖小的区域,所以首先进行排序操作 / / 冒泡排序,由小到大排序 VP vptmp; for ( int i = 1 ;i<contours.size();i + + ){ for ( int j = contours.size() - 1 ;j> = i;j - - ){ if (contourArea(contours[j]) < contourArea(contours[j - 1 ])) { vptmp = contours[j - 1 ]; contours[j - 1 ] = contours[j]; contours[j] = vptmp; } } } |
在OpenCV3中有了新的专门的函数 cv::connectedComponents() 和函数 cv::connectedComponentsWithStats()
定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
int cv::connectedComponents ( cv::InputArrayn image, / / input 8 - bit single - channel (binary) cv::OutputArray labels, / / output label map int connectivity = 8 , / / 4 - or 8 - connected components int ltype = CV_32S / / Output label type (CV_32S or CV_16U) ); int cv::connectedComponentsWithStats ( cv::InputArrayn image, / / input 8 - bit single - channel (binary) cv::OutputArray labels, / / output label map cv::OutputArray stats, / / Nx5 matrix (CV_32S) of statistics: / / [x0, y0, width0, height0, area0; / / ... ; x(N - 1 ), y(N - 1 ), width(N - 1 ), / / height(N - 1 ), area(N - 1 )] cv::OutputArray centroids, / / Nx2 CV_64F matrix of centroids: / / [ cx0, cy0; ... ; cx(N - 1 ), cy(N - 1 )] int connectivity = 8 , / / 4 - or 8 - connected components int ltype = CV_32S / / Output label type (CV_32S or CV_16U) ); |
其中,新出现的参数
stats:长这样
分别对应各个轮廓的x,y,width,height和面积。注意0的区域标识的是background
而centroids则对应的是中心点
而label则对应于表示是当前像素是第几个轮廓
例子:
对于图像
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
|
Mat img = cv::imread( "e:/sandbox/rect.png" , 0 ); cv::Mat img_edge, labels, img_color, stats,centroids; cv::threshold(img, img_edge, 128 , 255 , cv::THRESH_BINARY); bitwise_not(img_edge,img_edge); cv::imshow( "Image after threshold" , img_edge); int i, nccomps = cv::connectedComponentsWithStats ( img_edge, labels, stats, centroids ); cout << "Total Connected Components Detected: " << nccomps << endl; vector<cv::Vec3b> colors(nccomps + 1 ); colors[ 0 ] = Vec3b( 0 , 0 , 0 ); / / background pixels remain black. for ( i = 1 ; i < nccomps; i + + ) { colors[i] = Vec3b(rand() % 256 , rand() % 256 , rand() % 256 ); if ( stats.at< int >(i, cv::CC_STAT_AREA) < 200 ) colors[i] = Vec3b( 0 , 0 , 0 ); / / small regions are painted with black too. } img_color = Mat::zeros(img.size(), CV_8UC3); for ( int y = 0 ; y < img_color.rows; y + + ) for ( int x = 0 ; x < img_color.cols; x + + ) { int label = labels.at< int >(y, x); CV_Assert( 0 < = label && label < = nccomps); img_color.at<cv::Vec3b>(y, x) = colors[label]; } cv::imshow( "Labeled map" , img_color); cv::waitKey(); |
注意:
1、对于OpenCV来说,白色代表有数据,黑色代表没有数据,所以图像输入之前要转换成”黑底白图“
2、看labels 和 stats,其中第1 2 6 个的面积小于200
而labels中
完全对的上号,结果为
以上这篇浅谈OpenCV中的新函数connectedComponentsWithStats用法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/jsxyhelu/p/7439655.html