OpenCV图像处理-区域分割-形态学操作应用
2016-11-24 14:38
561 查看
分割的结果中通常包含不想要的干扰,如我们感兴趣的物体被干扰了,如由于反射对分割结果造成的干扰,这时,形态学操作提供了特别有用的方法,让我们调整和描述物体的形状。
本文聚焦形态学操作的若干典型应用,不会对形态学操作的基本数学理论进行系统的阐述,也不会对OpenCV函数进行详细的介绍,因此需要您首先对形态学的基本理论有所了解。
【1】利用膨胀操作提取物体的边界
从一个彩色红苹果图像,经过色彩分割,得到如下二值化的图片
(图a)
然后对图(a)进行膨胀
(b)
(b)-(a)就得到图像的轮廓(c)
(c)
完整代码如下:
【2】利用腐蚀操作,分离相互连通的物体
(a)原始彩色图像
(b)经过色彩分割,二值化操作后图像
可以看到许多橘子是相互连通在一起的,这样在分割每个橘子时候,用findcounter就无法分出单个的橘子。
(c):对图(b)进行腐蚀操作,可以看到连在一起的橘子已经分开了
对(c)利用【1】中膨胀的方法轮廓(d)
在(d)上用findConters和minEnclosingCircle,查找轮廓,拟合圆,效果如下:
(e)基本上把前面的橘子都找出来了
对上面程序参数稍加修改,就可以对草莓进行定位:
(a)草莓色彩分割二值化图像,有许多干扰,不处理的话会影响轮廓的提取
(b)腐蚀后,干扰明显降低了很多
(c)提取边界
(d)草莓定位圆
【3】闭运算消除孔洞
腐蚀和膨胀,看上去好像是一对互逆的操作,实际上,这两种操作不具有互逆的关系。 开运算和闭运算正是依据腐蚀和膨胀的不可逆性,演变而来的。
先腐蚀后膨胀的过程就称为开运算。开操作可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。
闭运算是先膨胀后腐蚀的过程,其功能是用来填充物体内细小空洞、 闭操作可以消弭狭窄的间断,消除小的孔洞。 同时不明显改变不明显改变其面积。
还是以诱人的水果为例,比如说如下的两个橙子,
(a)两个诱人的橙子,恩,是随意拍的照片,没有使用研究过的机器视觉光照系统,所以橙子中间有强反射光(发白)
简单的进行颜色分割(提取橙色),二值化,如下图
(b)橙子中间有孔洞,反射强光造成的
(c)闭运算后的橙子,恩,效果好多了,有利于后面的分割
关键代码如下:
【4】开运算,检查零件的小突出物(缺陷)
先腐蚀后膨胀的过程就称为开运算。开操作可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。
(a)圆形带细小突出物的零件,假设圆的半径是R,突出物外接圆半径为r
(b)使用半径c,(c远大于r,但是略小于R)的圆,进行腐蚀操作的结果
(c)使用同样半径c的圆进行膨胀操作结果(b,c两步合在一块就是开操作)
图(c)-图(a)的结果,就检测出来了零件的突出缺陷
关键代码如下:
本文聚焦形态学操作的若干典型应用,不会对形态学操作的基本数学理论进行系统的阐述,也不会对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】闭运算消除孔洞
腐蚀和膨胀,看上去好像是一对互逆的操作,实际上,这两种操作不具有互逆的关系。 开运算和闭运算正是依据腐蚀和膨胀的不可逆性,演变而来的。
先腐蚀后膨胀的过程就称为开运算。开操作可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。
闭运算是先膨胀后腐蚀的过程,其功能是用来填充物体内细小空洞、 闭操作可以消弭狭窄的间断,消除小的孔洞。 同时不明显改变不明显改变其面积。
还是以诱人的水果为例,比如说如下的两个橙子,
(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--形态学图像处理--膨胀与腐蚀,开操作与闭操作
- opencv6.1-imgproc图像处理模块之平滑与形态学操作
- opencv6.1-imgproc图像处理模块之平滑与形态学操作
- OPENCV用户手册之图像处理部分(之三):形态学操作(中文翻译)
- opencv 图像处理 形态学操作 腐蚀 膨胀 开闭运算 阈值二值化 图像卷积 图像金字塔 Sobel算子 Laplacian 算子 candy边缘检测 霍夫变换 直方图
- OpenCV图像处理形态学操作腐蚀Erode与膨胀Dilate
- OpenCV1.0图像处理形态学操作腐蚀Erode与膨胀Dilate
- OpenCV之imgproc 模块. 图像处理(1)图像平滑处理 腐蚀与膨胀(Eroding and Dilating) 更多形态学变换 图像金字塔 基本的阈值操作
- OpenCV1.0图像处理形态学操作腐蚀Erode与膨胀Dilate
- OpenCV图像处理形态学操作腐蚀Erode与膨胀Dilate
- opencv6.1-imgproc图像处理模块之平滑与形态学操作
- OpenCV&图像处理_3:以腐蚀[eroding]和膨胀[dilating]为基础的形态学操作和图像金字塔[image pyramids]
- OPENCV用户手册之图像处理部分(之三):形态学操作(中文翻译)
- OpenCV入门(八)--形态学图像处理
- openCV 形态学图像处理
- 【OpenCV入门教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑
- 【OpenCV入门教程之十】 形态学图像处理(一):膨胀与腐蚀
- 【OpenCV入门教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑
- 使用OpenCV读、操作、写图像并与bash合作对某个目录下所有图像进行类似处理
- 【OpenCV入门教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑