分割的结果中通常包含不想要的干扰,如我们感兴趣的物体被干扰了,如由于反射对分割结果造成的干扰,这时,形态学操作提供了特别有用的方法,让我们调整和描述物体的形状。
      本文聚焦形态学操作的若干典型应用,不会对形态学操作的基本数学理论进行系统的阐述,也不会对OpenCV函数进行详细的介绍,因此需要您首先对形态学的基本理论有所了解。
【1】利用膨胀操作提取物体的边界
从一个彩色红苹果图像,经过色彩分割,得到如下二值化的图片

                  (图a)
然后对图(a)进行膨胀

                  (b)
(b)-(a)就得到图像的轮廓(c)

                  (c)

完整代码如下:

#include <opencv2\opencv.hpp>
#include<opencv2\imgproc\imgproc.hpp>using namespace cv;
using namespace std;void main(){//图片保存参数vector<int> compression_params;compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);compression_params.push_back(9);cv::Mat src = cv::imread("D:/test_pic/apple1.jpg",1);   Mat binary=Mat::zeros(src.size(),CV_8UC1);      //色彩分割得到二值图像for(int ii=0;ii<src.rows;ii++)for(int jj=0;jj<src.cols;jj++){int b=(int)(src.at<Vec3b>(ii,jj)[0]); int r=(int) (src.at<Vec3b>(ii,jj)[2]);                      if(r>150&b<100) {binary.at<uchar>(ii,jj)=255;                           }else binary.at<uchar>(ii,jj)=0;}   cv::imshow("binary",binary);cv::imwrite("binary.jpg",binary,compression_params);//对二值图像进行膨胀操作Mat element=cv::getStructuringElement(MORPH_ELLIPSE,Size(5,5));Mat dilate;cv::dilate(binary,dilate,element);imshow("dilate",dilate);cv::imwrite("dilate.jpg",dilate,compression_params);//膨胀之后的图像减去膨胀前的二值图像就是物体的轮廓Mat edge=dilate-binary;imshow("edge",edge);cv::imwrite("edge.jpg",edge,compression_params);cv::waitKey(0);
}   

【2】利用腐蚀操作,分离相互连通的物体


                  (a)原始彩色图像


                  (b)经过色彩分割,二值化操作后图像

可以看到许多橘子是相互连通在一起的,这样在分割每个橘子时候,用findcounter就无法分出单个的橘子。


(c):对图(b)进行腐蚀操作,可以看到连在一起的橘子已经分开了


                  对(c)利用【1】中膨胀的方法轮廓(d)

在(d)上用findConters和minEnclosingCircle,查找轮廓,拟合圆,效果如下:

                  (e)基本上把前面的橘子都找出来了

#include <opencv2\opencv.hpp>
#include<opencv2\imgproc\imgproc.hpp>using namespace cv;
using namespace std;void main(){    cv::Mat src = cv::imread("D:/test_pic/orange8.jpg",1);      cv::imshow("src",src);//--------------------------------------图像颜色分割得到二值图像------------------------------------------Mat binary=Mat::zeros(src.size(),CV_8UC1);  for(int ii=0;ii<src.rows;ii++)for(int jj=0;jj<src.cols;jj++){int b=(int)(src.at<Vec3b>(ii,jj)[0]); int r=(int) (src.at<Vec3b>(ii,jj)[2]);                      if(r>150&b<200) {binary.at<uchar>(ii,jj)=255;                           }else binary.at<uchar>(ii,jj)=0;} cv::imshow("binary",binary);cv::imwrite("binary.jpg",binary);//-------------------------对图像进行腐蚀,使得各个橘子不再连通--------------------------------------Mat element=cv::getStructuringElement(MORPH_RECT,Size(15,15));Mat erodeImg;cv::erode(binary,erodeImg,element);imshow("erod",erodeImg);    cv::imwrite("erod.jpg",erodeImg);//--------------------------对腐蚀后的图像膨胀,以便获得轮廓(和【1】中轮廓提取一样)--------------Mat element2=cv::getStructuringElement(MORPH_ELLIPSE,Size(3,3));    Mat Img2;cv::dilate(erodeImg,Img2,element2);Mat edge=Img2-erodeImg;imshow("edge",edge);cv::imwrite("edge.jpg",edge);//-------------------------------------------查找轮廓并拟合圆--------------------------------------------//定义轮廓和层次结构vector<vector<Point>> contours;vector<Vec4i> hierarchy;//查找轮廓int model=CV_RETR_CCOMP;//针对不同的情况,几种方法应该都试一下,效果还是不一样的int method=CV_CHAIN_APPROX_NONE;cv::findContours(edge,contours,hierarchy,model,method);//遍历轮廓,绘拟合圆 for(int index=0;index>=0;index=hierarchy[index][0]){        float radius;cv::Point2f center;cv::minEnclosingCircle(contours[index],center,radius);  RotatedRect rect=cv::minAreaRect(contours[index]);double ratio=double(rect.size.height)/double (rect.size.width+0.01);if(radius>5&&ratio>0.5&&ratio<5.0){ //对橘子的半径,长短轴比进行一定的限定        //drawContours(src,contours,index,Scalar(255,255,0),CV_FILLED,8,hierarchy);         cv::circle(src,center,radius+6.0,Scalar(255,0,0),1,8);  //radius+6.0将之前腐蚀时减小量补回来        }}   cv::imshow("src with fitting-circles",src); cv::imwrite("fitting-circles.jpg",src);cv::waitKey(0);
}

对上面程序参数稍加修改,就可以对草莓进行定位:


(a)草莓色彩分割二值化图像,有许多干扰,不处理的话会影响轮廓的提取

(b)腐蚀后,干扰明显降低了很多

(c)提取边界

(d)草莓定位圆

【3】闭运算消除孔洞

  1. 腐蚀和膨胀,看上去好像是一对互逆的操作,实际上,这两种操作不具有互逆的关系。 开运算和闭运算正是依据腐蚀和膨胀的不可逆性,演变而来的。
  2. 先腐蚀后膨胀的过程就称为开运算。开操作可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。
  3. 闭运算是先膨胀后腐蚀的过程,其功能是用来填充物体内细小空洞、 闭操作可以消弭狭窄的间断,消除小的孔洞。 同时不明显改变不明显改变其面积。

    还是以诱人的水果为例,比如说如下的两个橙子,

    (a)两个诱人的橙子,恩,是随意拍的照片,没有使用研究过的机器视觉光照系统,所以橙子中间有强反射光(发白)

    简单的进行颜色分割(提取橙色),二值化,如下图

    (b)橙子中间有孔洞,反射强光造成的


    (c)闭运算后的橙子,恩,效果好多了,有利于后面的分割

关键代码如下:

    //闭运算Mat closedImg;Mat element=cv::getStructuringElement(MORPH_CROSS,Size(15,15)); cv::morphologyEx(binary,closedImg,CV_MOP_CLOSE,element);imshow("closeImg",closedImg);cv::imwrite("closeImg.jpg",closedImg);

【4】开运算,检查零件的小突出物(缺陷)
先腐蚀后膨胀的过程就称为开运算。开操作可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。

(a)圆形带细小突出物的零件,假设圆的半径是R,突出物外接圆半径为r


(b)使用半径c,(c远大于r,但是略小于R)的圆,进行腐蚀操作的结果


(c)使用同样半径c的圆进行膨胀操作结果(b,c两步合在一块就是开操作)


图(c)-图(a)的结果,就检测出来了零件的突出缺陷

关键代码如下:

//开运算Mat openImg;Mat element=cv::getStructuringElement(MORPH_ELLIPSE,Size(131,131)); cv::erode(binary,openImg,element);cv::dilate(openImg,openImg,element);//或者直接使用下面的操作,和上面两步结果是一样的//cv::morphologyEx(binary,openImg,CV_MOP_OPEN,element);imshow("openImg",openImg);cv::imwrite("openImg.jpg",openImg);Mat burrImg=binary-openImg;Mat element2=cv::getStructuringElement(MORPH_ELLIPSE,Size(3,3));    cv::morphologyEx(burrImg,burrImg,CV_MOP_OPEN,element2);//消除由于计算中小误差带来的圆形边界imshow("burrImg",burrImg);cv::imwrite("burrImg.jpg",burrImg);

OpenCV图像处理-区域分割-形态学操作应用相关推荐

  1. OpenCV中图像形态学操作

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:视学算法 图像形态学是图像处理的分支学科,在二值图像处理 ...

  2. opencv常用的形态学操作

    导读 在使用opencv做图像处理的时候,我们经常会需要用到一些基础的图像形态学操作腐蚀.膨胀.通过这些基本的形态学操作我们可以实现去噪以及图像的切割等. 形态学变换是基于图像形状的基础变换,它只能在 ...

  3. opencv c++ 图像形态学操作

    1.图像的形态学操作 包括图像的腐蚀.膨胀.开.闭.形态学梯度.顶帽.黑帽.分支主题.结构元素等操作. 具体概念参考:(41条消息) 图像处理-形态学处理_Good@dz的博客-CSDN博客_图像处理 ...

  4. opencv 实现图像形态学操作 膨胀和腐蚀 开闭运算 形态学梯度 顶帽和黑帽

    图像膨胀和腐蚀 图解 原理及python实现 更多内容:图像膨胀和腐蚀原理及python实现 opencv中膨胀和腐蚀函数 dilation = cv.dilate(img, kernel) # 膨胀 ...

  5. 2020.11.01 使用OpenCV进行图像形态学操作(开、闭、梯度)【OpenCV C++】

    进行基础的图像形态学操作练习 (开操作.闭操作.梯度.顶帽.黑帽操作) 源代码: // #include <opencv2/opencv.hpp> #include <iostrea ...

  6. opencv中的形态学操作

    形态学操作 1 连通性 在图像中,最小的单位是像素,每个像素周围有8各邻接像素,常见的邻接关系有3种:4邻接.8邻接和D邻接.分别如下图所示: 4邻接:像素p(x,y)的4邻域是:(x+1,y).(x ...

  7. Python图像处理:形态学操作

    来源:DeepHub IMBA本文约1400字,建议阅读5分钟 形态学的操作主要是去除影响图像形状和信息的噪声.形态学运算在图像分割中非常有用,可以得到无噪声的二值图像. 形态学方法 当图像经过预处理 ...

  8. opencv python 图像形态学操作/图像腐蚀/图像膨胀/开运算/闭运算/顶帽/黑帽

    Morphological Transformations 1图像腐蚀 腐蚀的基本思想:侵蚀前景物体的边界(总是试图保持前景为白色):内核在图像中滑动(如在2D卷积中).只有当内核下的所有像素都是1时 ...

  9. python图像处理模糊_Python+OpenCV图像处理之模糊操作

    模糊操作是图像处理中最简单和常用的操作之一,该使用的操作之一原因就为了给图像预处理时减低噪声,基于数学的卷积操作 均值模糊,函数 cv2.blur(image,(5,5)),这是一个平滑图片的函数,它 ...

最新文章

  1. 7纳米duv和euv_要超车台积电 三星宣布采用EUV技术7纳米制程完成验证
  2. c语言循环练习[xcode]
  3. pxe和kickstart无人值守安装
  4. Javah 常见错误记录
  5. 关于ax+by+cz的最大不可表数
  6. 《天天数学》连载48:二月十七日
  7. Django之ORM字段和参数
  8. Android CircleImageView圆形ImageView
  9. logo qt添加_Qt官方示例-窗口标志
  10. %3c %3e 转换html,防止基本的XSS攻击 滤掉HTML标签
  11. 数据集:102 flower、Cratech256、ImageNet数据集下载
  12. 个人博客图片管理(方便管理,大家忽略)
  13. 程序员求职之道(《程序员面试笔试宝典》)之看着别人手拿大把的offer,不淡定了怎么办?
  14. 轻量级的双向绑定工具 —— ukulelejs
  15. 在计算机中安装Manjaro
  16. 省市区三级联动(带经纬度、离线地图)
  17. 风电的Weibull分布及光电的Beta分布组合研究(Matlab代码实现)
  18. 一篇文章让你全面了解TDengine
  19. 作为喜爱3D游戏动漫建模的你,如果还不知道次世代游戏贴图的这些技巧,真是太可惜了
  20. 0x30数学知识(0x38 概率与数学期望)例题3:扑克牌(题解)

热门文章

  1. 如何利用计算机处理,旧电脑如何处理?去卖回收教你几招!榨干闲置电脑最后一丝价值!...
  2. JetBrains各版本全家桶工具 编程开发全套永久软件!IDE也能免费用
  3. 怎么开启windows hypervisor platform,解决hypervisor platform消失无法安装的问题
  4. 永磁同步直线电机仿真实例,仿真教学 maxwell16.0版本 12槽11极
  5. 关于SMTP邮件无法发送到 SMTP服务器,传输错误代码为 0x80040217
  6. 安装使用python-pcl调用ICP算法|debug
  7. 图形学数学基础之1D采样分布计算方法Inverse Method
  8. 瑞幸创造VC圈神话,风暴中的OYO回应,企鹅杏仁集团完成2.5亿美元融资...
  9. Protractor版本大事记
  10. 学网络安全到什么程度才能找到工作?