# OpenCV 图像预处理—形态学:膨胀、腐蚀、开运算、闭运算 原理详解

news/2024/9/8 12:58:23

文章目录

  • 形态学概念
  • 膨胀
    • 使用膨胀操作来修复裂痕
      • 示例代码
      • 关键解析:
  • 腐蚀
    • 使用腐蚀操作消除噪点
      • 示例代码:
  • 开运算—先腐蚀后膨胀
  • 闭运算—先膨胀后腐蚀

形态学概念

首先看这两张图片

在这里插入图片描述

一张图周围有大大小小的噪音和彩点,另一张图片中字母有间隙,这种效果影响了图片的质量,该如何处理图片,提高质量?

这就是形态学操作发挥作用的地方,形态学(Morphology)是图像处理中的一种技术,主要用于分析和处理图像中的结构和形状。形态学操作基于图像的形状和结构,而不是像素的具体值。它通常应用于二值图像(黑白图像),但也可以用于灰度图像。形态学操作在许多图像处理任务中发挥着重要作用,如去噪声、分割、边缘检测等。

膨胀

膨胀操作可以理解为将图像中的前景对象扩展。其基本原理是用一个结构元素扫描图像,如果结构元素至少有一个与前景(白色)部分重叠,则图像中的中心元素被设置为前景。

与卷积类似,也有一个矩阵来扫描整张图片,比如下方这个3*3矩阵,
$$
1 & 1 & 1
1 & 1 & 1
1 & 1 & 1

$$
当这个矩阵在图片扫描的时候,如果矩阵的任何元素遇到图像的像素值“1”。则与内核中心元素重叠的像素将转换为“1”。如下图所示

在这里插入图片描述

整个扫描的过程动态如下:会将橙色部分进行扩张,这就是膨胀的过程。

在这里插入图片描述

使用膨胀操作来修复裂痕

示例代码

//形态学操作 膨胀 腐蚀 ,开操作, 闭操作
void morphology_op_demo(Mat &image){Mat mask_image;threshold(image,mask_image,150,255,THRESH_BINARY_INV);  //图像进行二值化// 创建结构元素 扫描核int kernel_size =3;cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * kernel_size + 1, 2 * kernel_size + 1),cv::Point(-1, -1));// 执行膨胀操作cv::Mat eroded_image;cv::dilate(mask_image, eroded_image, element,Point(-1,-1),1);// 显示结果图像cv::imshow("Original Image", mask_image);cv::imshow("Eroded Image", eroded_image);waitKey();
}

关键解析:

threshold(image,mask_image,150,255,THRESH_BINARY);  //图像进行二值化

对图像进行二值化,让图像非黑即白,当然膨胀操作也可以用于彩色图像,但是会有一个问题,中心点像素会累加,会提高原来图片的亮度,扫描核越大,会导致图片越亮,直到白色看不见为止。

   cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1),cv::Point(-1, -1));

创建扫描矩阵,矩阵可以任意大小,这里使用奇数n*n的矩阵 Point 取(-1,-1)代表使用中心点像素,扫描矩阵的size越大,膨胀效果越强。

  cv::dilate(mask_image, eroded_image, element,Point(-1,-1),1);

膨胀操作API ,函数原型

CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );

一般只关心前三个参数即可,输入,输出,扫描核(扫描的矩阵),Point 取(-1,-1)代表使用中心点像素,这里迭代次数为1次,同理 迭代次数越多,膨胀效果越强

效果如图:

扫描核size为 3:有效果,但仍然有裂痕

在这里插入图片描述

扫描核 size 为 5:效果增强,边缘变粗,基本上添上空隙

在这里插入图片描述

腐蚀

与膨胀相反,删除元素,它腐蚀图像的方式就像水侵蚀河岸一样。在腐蚀操作中,它将结构元素从输入图像的左向右和从上到下滑动。如果结构元素内的所有像素都大于 0,则保留原始像素值。否则,像素设置为 0。腐蚀用于去除被视为噪声的小斑点。

同样的使用膨胀操作的扫描核 3*3 全为1 的矩阵
$$
1 & 1 & 1
1 & 1 & 1
1 & 1 & 1

$$
此内核遍历图像的每个像素。如果与内核重叠的所有像素恰好是“1”,则不会发生任何更改。但是,如果任何重叠的像素恰好为“0”,则与内核的 中心 元素重叠的像素将设置为“0”。

在这里插入图片描述

腐蚀操作可视化图:

在这里插入图片描述

随着迭代次数的增加,图像像素点慢慢被腐蚀。因此,如果您需要提取粗体且周围有很多噪点的时候,可以通过侵蚀图像来消除噪点。

使用腐蚀操作消除噪点

示例代码:

//形态学操作 膨胀 腐蚀 ,开操作, 闭操作
void morphology_op_demo(Mat &image){Mat mask_image;threshold(image,mask_image,150,255,THRESH_BINARY_INV);  //图像进行二值化// 创建结构元素 扫描核int kernel_size =1;cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * kernel_size + 1, 2 * kernel_size + 1),cv::Point(-1, -1));// 执行腐蚀操作cv::Mat eroded_image;cv::erode(mask_image, eroded_image, element,Point(-1,-1),1);// 显示结果图像cv::imshow("Original Image", mask_image);cv::imshow("Eroded Image", eroded_image);waitKey();
}
int main()
{string imagePath = "C:\\Users\\Marxist\\Pictures\\coco\\eroding_test.jpg";string mix_image_path = "C:\\Users\\Marxist\\Pictures\\coco\\Linux.jpg";Mat image = imread(imagePath,IMREAD_GRAYSCALE);//读取灰度图像morphology_op_demo(image);return 0;
}

关键解析:

cv::erode(mask_image, eroded_image, element,Point(-1,-1),1);

函数原型:

CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );

与膨胀API参数一致,但效果相反

腐蚀操作—内核大小3*3 迭代1次,噪点明显消除

在这里插入图片描述

腐蚀操作—内核大小5*5 迭代1次,噪点完全消除,但是图像细节也跟着丢失了

在这里插入图片描述

面对图像丢失的情况,可以进行开闭运算了

开运算—先腐蚀后膨胀

开运算是先进行腐蚀操作,再进行膨胀操作。它主要用于去除小的噪点,并保持前景物体的整体形状。

关键函数:

  morphologyEx(mask_image, opening_image, MORPH_OPEN, element);

本质上就是调用了腐蚀API和膨胀API,OpenCV为了代码简洁,将二个API 合成了一个

示例代码

//形态学操作 膨胀 腐蚀 ,开操作, 闭操作
void morphology_op_demo(Mat &image){Mat mask_image;threshold(image,mask_image,150,255,THRESH_BINARY_INV);  //图像进行二值化// 创建结构元素 扫描核int kernel_size =2;cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * kernel_size + 1, 2 * kernel_size + 1),cv::Point(-1, -1));// 执行腐蚀操作cv::Mat eroded_image;cv::erode(mask_image, eroded_image, element,Point(-1,-1),1);Mat final;// 先执行 腐蚀 然后执行膨胀morphologyEx(mask_image, final, MORPH_OPEN, element);cv::imshow("Original Image", mask_image);cv::imshow("Eroded Image", eroded_image);cv::imshow("final Image", final);waitKey();
}
int main()
{string imagePath = "C:\\Users\\Marxist\\Pictures\\coco\\eroding_test.jpg";string mix_image_path = "C:\\Users\\Marxist\\Pictures\\coco\\Linux.jpg";Mat image = imread(imagePath,IMREAD_GRAYSCALE);//读取灰度图像morphology_op_demo(image);return 0;
}

开运算效果:对比腐蚀过后的图像,进行稍微膨胀 补充连接细节

在这里插入图片描述

闭运算—先膨胀后腐蚀

//形态学操作 膨胀 腐蚀 ,开操作, 闭操作
void morphology_op_demo(Mat &image){Mat mask_image;threshold(image,mask_image,150,255,THRESH_BINARY_INV);  //图像进行二值化// 创建结构元素 扫描核int kernel_size =2;cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * kernel_size + 1, 2 * kernel_size + 1),cv::Point(-1, -1));// 执行膨胀操作cv::Mat eroded_image;cv::dilate(mask_image, eroded_image, element,Point(-1,-1),1);Mat final;// 先执行 腐蚀 然后执行膨胀morphologyEx(mask_image, final, MORPH_CLOSE, element);cv::imshow("Original Image", mask_image);cv::imshow("Eroded Image", eroded_image);cv::imshow("final Image", final);waitKey();
}
int main()
{string imagePath = "C:\\Users\\Marxist\\Pictures\\coco\\dilation_test.jpg";string mix_image_path = "C:\\Users\\Marxist\\Pictures\\coco\\Linux.jpg";Mat image = imread(imagePath,IMREAD_GRAYSCALE);//读取灰度图像morphology_op_demo(image);return 0;
}

闭运算与开运算相反,先膨胀后腐蚀,它主要用于填补前景物体中的小孔和连接断开的物体。

闭运算效果:对比膨胀后的图像,边缘稍微细了些

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.cpky.cn/p/14952.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Radon(拉当) 变换:超详细讲解(附MATLAB,Python 代码)

Radon 变换 Radon 变换是数学上用于函数或图像的一种积分变换,广泛应用于图像处理领域,尤其是在计算机断层成像 (CT) 中。本文档将详细介绍 Radon 变换的数学含义及其在图像处理中的应用。 数学定义 Radon 变换的数学定义是将二维函数 f ( x , y ) f…

硅纪元视角 | 类器官智能OI技术实现将人脑植入机器人

在数字化浪潮的推动下,人工智能(AI)正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展,捕捉行业动态;提供深入的新闻解读,助您洞悉技术背后的逻辑;汇聚行业专家的见解,…

基于微信小程序+SpringBoot+Vue的校园自助打印系统(带1w+文档)

基于微信小程序SpringBootVue的校园自助打印系统(带1w文档) 基于微信小程序SpringBootVue的校园自助打印系统(带1w文档) 管理信息可以处理复杂的信息从而提高用户的工作效率,减少失误。所以本基于Vue和微信小程序的校园自助打印系统的开发非常有意义,本系…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第三十八章 驱动模块编译进内核

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

el-menu根据多层树形结构递归遍历展示菜单栏

文章目录 前提条件假设菜单等级只有两个等级结果如下所示 但是如果菜单等级超过两个等级或者多个等级的话App.vueMenuItems.vue结果如下所示 关于遍历时图标前的展示后续完善关于点击路由跳转参考element plus的官网即可 前提条件 package.json如下所示,这是一个Vi…

【Linux】条件变量及生产者消费者模型

为什么要将这两者放在一起进行呢? 主要是因为生产消费与条件变量关系密切,正好相辅相成。 目录 条件变量:条件变量的引出:条件变量的解释与接口:测试代码: 生产者消费者模型:概念:代…