OpenCV中形态学操作:膨胀、腐蚀、开闭运算
1、基本概念
图像形态学即数学形态学(Mathematical morphology)是一门建立在格伦和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论;常见图像形态学运算:腐蚀,膨胀,开运算,闭运算,骨架抽取,极线腐蚀,击中击不中变换,顶帽变换,颗粒分析,流域变换,形态学梯度等。
腐蚀和膨胀是最基本的形态学运算。
腐蚀和膨胀是针对白色部分(高亮部分)而言的。
膨胀(dilate)是对图像高亮部分进行“领域扩张”,领域扩张,效果图拥有比原图更大的高亮区域;
腐蚀(erode)是原图中的高亮区域被蚕食,领域缩减,效果图拥有比原图更小的高亮区域。
开运算:先腐蚀再膨胀,用来消除小物体
闭运算:先膨胀再腐蚀,用于排除小型黑洞
形态学梯度:就是膨胀图与俯视图之差,用于保留物体的边缘轮廓。
顶帽:原图像与开运算图之差,用于分离比邻近点亮一些的斑块。
黑帽:闭运算与原图像之差,用于分离比邻近点暗一些的斑块。
opencv里有一个很好的函数getStructuringElement,我们只要往这个函数传相应的处理参数,就可以进行相应的操作了,使用起来非常方便。
getStructuringElement():返回指定形状和尺寸的结构元素;
格式:
getStructuringElement(int shape,Size ksize,Point anchor = Point(-1,-1));
参数:
shape:表核的形状,矩形MORPH_RECT;交叉形MORPH_CROSS;椭圆形MORPH_ELLIPSE;
ksize:核尺寸大小;
anchor:锚点的位置,锚点只影响形态学运算结果的偏移;
下面列举一下相应的操作宏定义。
2、膨胀(dilate)
膨胀就是求局部最大值的操作,从图像直观看来,就是将图像光亮部分放大,黑暗部分缩小。
OpenCV的中膨胀函数为dilate()。
dilate(
InputArray src,//输入
OutputArray dst,//输出
InputArray kernel,//核大小
Point anchor = Point(-1,-1),//锚位置,( - 1,-1)为中心
int iterations = 1,//迭代次数
int borderType = BORDER_CONSTANT,//图像边界像素模式
const Scalar&borderValue = morphologyDefaultBorderValue()//边界值
)
实现方法:
1、定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);
通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
2、将核乙与图像甲进行卷积,计算核乙覆盖区域的像素点最大值;
3、将这个最大值赋值给参考点指定的像素;
因此,图像中的高亮区域逐渐增长。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
cout << img.size() << endl;
imshow("原图",img);
Mat dst;
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
dilate(img, dst, element);
imshow("膨胀操作", dst);
waitKey();
return 0;
}
3、腐蚀(erode)
腐蚀就是与膨胀相反,求局部最小值,从图像直观看来,就是将图像光亮部分缩小,黑暗部分放大。
OpenCV的中腐蚀函数为erode()。
erode(
InputArray src,//输入
OutputArray dst,//输出
InputArray kernel,//核大小
Point anchor = Point(-1,-1),//锚位置,( - 1,-1)为中心
int iterations = 1,//迭代次数
int borderType = BORDER_CONSTANT,//图像边界像素模式
const Scalar&borderValue = morphologyDefaultBorderValue()//边界值
)
实现方法:
1、定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);
通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
2、将核乙与图像甲进行卷积,计算核乙覆盖区域的像素点最小值;
3、将这个最小值赋值给参考点指定的像素;
因此,图像中的高亮区域逐渐减小。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
cout << img.size() << endl;
imshow("原图",img);
Mat dst;
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
//腐蚀操作
erode(img, dst, element);
imshow("腐蚀操作", dst);
waitKey();
return 0;
}
4、形态学开运算
开操作(先腐蚀后膨胀)可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。
它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
cout << img.size() << endl;
imshow("原图",img);
Mat dst;
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
//形态学开操作
#if 1
morphologyEx(img, dst, MORPH_OPEN, element);
#else
erode(img, dst, element);
dilate(dst, dst, element);
#endif
imshow("形态学开操作", dst);
waitKey();
return 0;
}
注:形态学操作可使用高级函数morphologyEx。
//形态学操作(开、闭、形态学梯度、顶帽、黑帽)
morphologyEx(src, dst, MORPH_BLACKHAT, kernel);
//第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
//第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
//第三个参数,int类型的op,表示形态学运算的类型,可以是如下之一的标识符:
//MORPH_OPEN – 开运算(Opening operation):先腐蚀后膨胀,去掉小对象
//MORPH_CLOSE – 闭运算(Closing operation):先膨胀后腐蚀,可以填充一些小的空洞(fill hole)
//MORPH_GRADIENT - 形态学梯度(Morphological gradient):膨胀后的图减去腐蚀后的图(设置恰当的参数可以得到目标的大致边缘)
//MORPH_TOPHAT - “顶帽”(“Top hat”):原图像与开操作之间的差值图像(可以用来观察开运算除去了哪些小目标)
//MORPH_BLACKHAT - “黑帽”(“Black hat“):闭操作图像与源图像的差值图像(可以观察闭运算的效果)
//第四个参数:结构元素即形态学运算的内核
//第五个参数,Point类型的anchor,锚的位置,其有默认值( - 1, - 1),表示锚位于中心。
//第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
//第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
//第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档
5、形态学闭运算
闭操作(先膨胀后腐蚀)可以消弭狭窄的间断,消除小的孔洞。先膨胀后腐蚀的操作称之为闭操作。
它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
cout << img.size() << endl;
imshow("原图",img);
Mat dst;
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
//形态学闭操作
#if 1
morphologyEx(img, dst, MORPH_CLOSE, element);
#else
dilate(dst, dst, element);
erode(img, dst, element);
#endif
imshow("形态学闭操作", dst);
waitKey();
return 0;
}
上一篇: 自定义VS Code界面背景图片