提取元素的轮廓及形状描述子(以一种新的模式来做)(转载)

先看提取轮廓的代码:

 1     Mat image = imread("D:/picture/images/binaryGroup.bmp",0);
 2     if(!image.data)
 3         return -1;
 4     imshow("源图像",image);
 5 
 6     //获取轮廓
 7     std::vector<std::vector<Point>> contours;
 8     //获取轮廓:
 9     findContours(image,            //图像
10         contours,                //轮廓点
11                         //包含图像拓扑结构的信息(可选参数,这里没有选)
12         CV_RETR_EXTERNAL,            //获取轮廓的方法(这里获取外围轮廓)
13         CV_CHAIN_APPROX_NONE);        //轮廓近似的方法(这里不近似,获取全部轮廓)
14     //打印轮廓信息
15     std::cout<<"共有外围轮廓:"<<contours.size()<<""<<std::endl;
16     std::vector<std::vector<Point>>::const_iterator itContours = contours.begin();
17     for(;itContours != contours.end();++itContours)
18     {
19         std::cout<<"每个轮廓的长度: "<<itContours->size()<<std::endl;
20     }

注意到轮廓的存储格式为std::vector<std::vector<Point>>,他说明整个轮廓是若干条轮廓按一定顺序组成的,而每个轮廓中的点也是有顺序的。

画出轮廓就比较简单了:

1     //画出轮廓
2     Mat result(image.size(),CV_8U,Scalar(255));
3     //画出轮廓,参数为:画板,轮廓,轮廓指示(这里画出所有轮廓),颜色,线粗
4     drawContours(result,contours,-1,Scalar(0),2);
5     imshow("提取外围轮廓",result);

还要注意提取轮廓的方法还有很多种,比如CV_RETR_LIST代表所有轮廓

    findContours(image,            //图像
        contours,                //轮廓点
                        //包含图像拓扑结构的信息(可选参数,这里没有选)
        CV_RETR_LIST,            //获取轮廓的方法(这里获取所有轮廓)
        CV_CHAIN_APPROX_NONE);        //轮廓近似的方法(这里不近似,获取全部轮廓
    //画出轮廓
    drawContours(result,contours,-1,Scalar(0),2);
    imshow("提取所有轮廓",result);

通常,这样提取的轮廓包含一些我们不希望的轮廓(比如一些小洞),或者假如我们知道我们感兴趣的物体轮廓的大概范围时,我们就可以用下面的办法缩小目标范围:

 1     //除去太长或者太短的轮廓
 2     int cmin = 100;
 3     int cmax = 1000;
 4     std::vector<std::vector<Point>>::const_iterator itc = contours.begin();
 5     while(itc != contours.end())
 6     {
 7         if(itc->size() < cmin || itc->size() > cmax)
 8             itc = contours.erase(itc);
 9         else
10             ++itc;
11     }
12     
13     //把结果画在源图像上:
14     Mat original = imread("D:/picture/images/group.jpg");
15     if(!original.data)
16         return -1;
17     drawContours(original,contours,-1,Scalar(255,255,255),2);
18     imshow("动物的轮廓",original);
19 
20     //将轮廓重绘于白板上
21     result.setTo(Scalar(255));
22     drawContours(result,contours,-1,Scalar(0),1);

怎么提取轮廓的特征呢?OpenCV提供了很多函数,我们展示其中的几个:

 1     //轮廓的形状描述子
 2     //外接矩形
 3     Rect r0 = boundingRect(Mat(contours[0]));
 4     rectangle(result,r0,Scalar(0),2);
 5 
 6     //最小外接圆
 7     float radius;
 8     Point2f center;
 9     minEnclosingCircle(Mat(contours[1]),center,radius);
10     circle(result,Point(center),static_cast<int>(radius),Scalar(0),2);
11 
12     //多边形估计
13     std::vector<Point> poly;
14     //参数为:输入图像的2维点集,输出结果,估计精度,是否闭合
15     approxPolyDP(Mat(contours[2]),poly,5,true);
16     std::cout<<"多边形大小:"<<poly.size()<<std::endl;
17     //画出结果
18     std::vector<Point>::const_iterator itp = poly.begin();
19     while(itp != poly.end()-1)
20     {
21         line(result,*itp,*(itp+1),Scalar(0),2);
22         ++itp;
23     }
24     //将第一个点和最后一点连起来
25     line(result,*(poly.begin()),*(poly.end()-1),Scalar(128),2);
26 
27 
28     //计算凸包
29     std::vector<Point> hull;
30     convexHull(Mat(contours[3]),hull);
31     std::vector<cv::Point>::const_iterator it= hull.begin();
32     while(it != (hull.end()-1))
33     {
34         line(result,*it,*(it+1),Scalar(0),2);
35         ++it;
36     }
37     line(result,*(hull.begin()),*(hull.end()-1),Scalar(0),2);
38     
39 
40     //计算矩信息
41     itc = contours.begin();
42     while(itc != contours.end())
43     {
44         //计算所有的距
45         Moments mom = moments(Mat(*itc++));
46         //计算并画出质心
47         circle(result,Point(mom.m10/mom.m00,mom.m01/mom.m00),2,Scalar(2),2);
48     }
49     imshow("形状描述子",result);

我们再次看到,轮廓的确是有顺序的。值得注意的是矩信息:OpenCV提供了一个结构体Moments,它的元素就是计算好的矩信息,里面存放了常用的距。

其实,OpenCV还提供了许多其他的形状描述子,比如函数cv::minAreaRect计算了最小外界倾斜的矩形。函数cv::contourArea估计轮廓区域的面积(里面的像素数)。函数cv::pointPolygonTest计算一个点是否在轮廓内,cv::matchShapes测量了2两个轮廓的相似程度等等。这里就不一一介绍了。

转载于:https://www.cnblogs.com/gzy-zju-edu/articles/4167827.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值