形态学操作
形态学操作就是基于形状的一系列图像处理操作。
OpenCV 为进行图像的形态学变换提供了快捷、方便的函数。
最基本的形态学操作有二种,他们是:膨胀与腐蚀 (Dilation 与 Erosion)。
膨胀与腐蚀能实现多种多样的功能,主要如下:
- 消除噪声
- 分割 (isolate) 出独立的图像元素,在图像中连接 (join) 相邻的元素。
- 寻找图像中的明显的极大值区域或极小值区域
- 求出图像的梯度
腐蚀和膨胀是针对白色部分(高亮部分)而言的。
- 膨胀就是对图像高亮部分进行 “领域扩张”,效果图拥有比原图更大的高亮区域;
- 腐蚀是原图中的高亮区域被蚕食,效果图拥有比原图更小的高亮区域。
膨胀用来处理缺陷问题; 腐蚀用来处理毛刺问题。
膨胀 dilate
膨胀就是求局部最大值的操作,从图像直观看来,就是将图像光亮部分放大,黑暗部分缩小。
按数学方面来说,膨胀或者腐蚀操作就是将图像(或图像的一部分区域,我们称之为 A)与核(我们称之为 B)进行卷积。假设有图像 A 和结构元素 B,结构元素 B 在 A 上面移动,其中 B 定义其中心为锚点,
以 B 覆盖下 A 的最大像素值(偏白)替换锚点的像素,其中 B 作为结构体可以是任意形状(与卷积不同之处,可以是线、矩阵、圆、十字等形状)。
二值图像与灰度图像上的膨胀操作:
- B 覆盖下的三个像素点是 1,0,0,然后最大值就是 1,然后中间的那个 0,就是替换成了 1,1,0
腐蚀 erode
腐蚀操作和膨胀操作相反,也就是将毛刺消除,腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值(偏黑)替换锚点重叠下图像的像素值。
形态学膨胀——dilate 函数
函数原型:
void dilate( InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() );
参数详解:
- 第一个参数,InputArray 类型的 src,输入图像,即源图像,填 Mat 类的对象即可。图像通道的数量可以是任意的,但图像深度应为 CV_8U,CV_16U,CV_16S,CV_32F 或 CV_64F 其中之一。
- 第二个参数,OutputArray 类型的 dst,即目标图像,需要和源图片有一样的尺寸和类型。
- 第三个参数,InputArray 类型的 kernel,膨胀操作的核。若为 NULL 时,表示的是使用参考点位于中心 3x3 的核。
我们一般使用函数 getStructuringElement 配合这个参数的使用。getStructuringElement 函数会返回指定形状和尺寸的结构元素(内核矩阵)。其中,getStructuringElement 函数的第一个参数表示内核的形状,我们可以选择如下三种形状之一:
- 矩形: MORPH_RECT
- 交叉形: MORPH_CROSS
- 椭圆形: MORPH_ELLIPSE
调用范例:
//载入原图 Mat image = imread("1.jpg"); //获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); Mat out; //进行膨胀操作 dilate(image, out, element);
//-----------------------------------【头文件包含部分】--------------------------------------- // 描述:包含程序所依赖的头文件 //---------------------------------------------------------------------------------------------- #include <opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include <iostream> //-----------------------------------【命名空间声明部分】--------------------------------------- // 描述:包含程序所使用的命名空间 //----------------------------------------------------------------------------------------------- using namespace std; using namespace cv; //-----------------------------------【main( )函数】-------------------------------------------- // 描述:控制台应用程序的入口函数,我们的程序从这里开始 //----------------------------------------------------------------------------------------------- int main() { //载入原图 Mat image = imread("5.jpg"); //显示原图 imshow("【原图】膨胀操作", image); //获取自定义核 Mat element1 = getStructuringElement(MORPH_RECT, Size(7, 7)); Mat element2 = getStructuringElement(MORPH_RECT, Size(15, 15)); Mat out1; Mat out2; //进行膨胀操作 dilate(image, out1, element1); dilate(image, out2, element2); //显示效果图 imshow("【效果图】膨胀操作(ksize=5)", out1); imshow("【效果图】膨胀操作(ksize=15)", out2); waitKey(0); return 0; }
可以看到白色的像素点(像素值高的像素点)越来越多,黑色的部分(像素值低的像素点)越来越少。
形态学腐蚀——erode 函数
C++: void erode( InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() );
参数详解:
- 第一个参数,InputArray 类型的 src,输入图像,即源图像,填 Mat 类的对象即可。图像通道的数量可以是任意的,但图像深度应为 CV_8U,CV_16U,CV_16S,CV_32F 或 CV_64F 其中之一。
- 第二个参数,OutputArray 类型的 dst,即目标图像,需要和源图片有一样的尺寸和类型。
- 第三个参数,InputArray 类型的 kernel,腐蚀操作的内核。若为 NULL 时,表示的是使用参考点位于中心 3x3 的核。我们一般使用函数 getStructuringElement 配合这个参数的使用。getStructuringElement 函数会返回指定形状和尺寸的结构元素(内核矩阵)。
//载入原图 Mat image = imread("1.jpg"); //获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); Mat out; //进行腐蚀操作 erode(image,out, element);
//-----------------------------------【头文件包含部分】--------------------------------------- // 描述:包含程序所依赖的头文件 //---------------------------------------------------------------------------------------------- #include <opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include <iostream> //-----------------------------------【命名空间声明部分】--------------------------------------- // 描述:包含程序所使用的命名空间 //----------------------------------------------------------------------------------------------- using namespace std; using namespace cv; //-----------------------------------【main( )函数】-------------------------------------------- // 描述:控制台应用程序的入口函数,我们的程序从这里开始 //----------------------------------------------------------------------------------------------- int main( ) { //载入原图 Matimage = imread("1.jpg"); //创建窗口 namedWindow("【原图】腐蚀操作"); namedWindow("【效果图】腐蚀操作"); //显示原图 imshow("【原图】腐蚀操作", image); //获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); Mat out; //进行腐蚀操作 erode(image,out, element); //显示效果图 imshow("【效果图】腐蚀操作", out); waitKey(0); return 0; }
与膨胀相反,可以看到白色的像素点(像素值高的像素点)越来越少,黑色的部分(像素值低的像素点)越来越多。
参考文章:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验