当前位置: 首页 > article >正文

OpenCV_图像膨胀腐蚀与形态学操作及具体应用详解

在本教程中,您将学习如何:

  • 应用两个非常常见的形态运算符:腐蚀和膨胀:
    • cv::erode
    • cv::dilate
  • 使用OpenCV函数cv :: morphologyEx应用形态转换,如:
  1. 开运算
  2. 闭运算
  3. 形态学梯度
  4. 顶帽运算
  5. 黑帽运算

形态作业

  • 简而言之:一组基于形状处理图像的操作。形态操作将结构元素应用于输入图像并生成输出图像。
  • 最基本的形态作用是:腐蚀和膨胀。它们有广泛的用途,即:
  1. 消除噪音
  2. 隔离单个元素并连接图像中的不同元素。
  3. 查找图像中的强度凸点或孔

1.腐蚀操作(erode)


腐蚀操作可以将图像中的边缘“腐蚀”掉,使其变得更加平滑。它的原理是使用一个称为结构元素(Structuring Element)的小型矩阵,在图像上滑动并检查像素与结构元素的对应位置是否满足某种条件(通常是“与”操作)。如果像素值全部满足条件,则中心像素值保持不变,否则被腐蚀为0。这一过程可以用来消除小型噪声、分离接触对象、以及缩小物体等。
在 OpenCV 中,腐蚀操作的函数是 erode()。下面是它的语法格式和含义:

函数:

erode( src, dst, kernel);

src:表示输入图像,即待腐蚀的图像,应为灰度图像或者单通道二值图像。

dst:表示输出图像

kernel:表示结构元素,这是我们将用来执行操作的内核。如果我们不指定,
默认是一个简单的3x3矩阵。否则,我们可以指定它的形状。为此,我们需要使用
函数cv :: getStructuringElement:

腐蚀操作的基本思想是,对于给定的结构元素,在图像上滑动并检查像素与结构元素的对应位置是否满足某种条件。如果像素值全部满足条件,则中心像素值保持不变,否则被腐蚀为0。

  • 这个操作是扩张的姊妹。它计算给定内核区域的局部最小值。
  • 当内核在图像上扫描时,我们计算由重叠的最小像素值,并用该最小值替换锚点下的图像像素。BB
  • 对于扩张的例子,我们可以将侵蚀算子应用于原始图像(如上所示)。您可以在下面的结果中看到,图像的明亮区域(背景,显然)变得更薄,而黑暗区域(“写作”)变得更大。

OpenCV侵蚀

以相似的方式,通过对反转的原始图像(具有尺寸的矩形结构元素的两次侵蚀)施加腐蚀操作来产生相应的图像3x3:

OpenCV侵蚀

左图:原图反转,右图:造成腐蚀

代码如下:

void callback_Demo(int, void* userdata) {
	Mat dst;
	Mat image = *((Mat*)userdata);
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(
        MORPH_RECT, 
        Size(s, s), 
        Point(-1, -1));
	erode(image, dst, structureElement, Point(-1, -1), 1);
	imshow(OUTPUT_WINDOW, dst);
	return;
}

2.膨胀操作(dilate)


膨胀操作是图像形态学处理中的一种基本操作,通常用于增加或扩展图像中的白色区域(前景对象)。它的原理是在图像上滑动一个结构元素(通常是一个小的矩形或圆形内核),将内核下方的像素值替换为内核下方区域内的最大像素值。因此,它会使图像中的白色区域变得更大。膨胀操作常用于填充图像中的空洞、连接相邻的对象以及消除图像中的噪声。

在OpenCV中,膨胀操作可以通过dilate()函数实现。该函数需要传入待处理的图像、结构元素(通常是一个矩形或圆形内核)以及迭代次数作为参数。迭代次数表示膨胀操作的次数,通常设置为1即可。

函数:

dilate( src, dst, kernel);

src:表示输入图像,即待膨胀的图像,应为灰度图像或者单通道二值图像。

dst:表示输出图像

kernel:表示结构元素,这是我们将用来执行操作的内核。如果我们不指定,
默认是一个简单的3x3矩阵。否则,我们可以指定它的形状。为此,我们需要使用
函数cv :: getStructuringElement:
  • 该操作包括将图像与某些内核(B)进行卷积,其可以具有任何形状或尺寸,通常为正方形或圆形。AB
  • 内核具有定义的锚点,通常是内核的中心。B
  • 当内核在图像上扫描时,我们计算由B重叠的最大像素值,并用该最大值替换锚点位置中的图像像素。您可以推断,这种最大化的操作会使图像中的亮区“增长”(因此称为扩张)。以上图为例。应用扩张我们可以得到:BB

OpenCV扩张

背景(明亮)扩大了字母的黑色地区。

为了更好地把握想法并避免可能的混乱,在另一个例子中,我们已经将原始图像倒过来,如白色的对象现在是这个字母。我们已经执行了两个具有大小的矩形结构元素的扩张3x3。

OpenCV扩张

左图:原图反转,右图:产生扩张

代码如下:

void callback_Demo(int, void* userdata) {
	Mat dst;
	Mat image = *((Mat*)userdata);
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));	
	dilate(image,dst,structureElement,Point(-1,-1),1);	
	imshow(OUTPUT_WINDOW, dst);
	return;
}

全部代码如下:

char OUTPUT_WINDOW[] = "output image";
int element_size = 3;
int max_size = 21;
void callback_Demo(int, void* userdata);
void callback_Demo(int, void* userdata) {
	Mat dst;
	Mat image = *((Mat*)userdata);
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));	
	dilate(image,dst,structureElement,Point(-1,-1),1);
	//erode(image, dst, structureElement, Point(-1, -1), 1);	
	//threshold(image,dst, element_size, max_size, THRESH_OTSU);
	imshow(OUTPUT_WINDOW, dst);
	return;
}
void QuickDemo::eleven(Mat& image) {
	Mat gray;
	cvtColor(image, gray, COLOR_BGR2GRAY);
	namedWindow(OUTPUT_WINDOW, WINDOW_AUTOSIZE);
	createTrackbar("element size :", OUTPUT_WINDOW, &element_size, max_size, callback_Demo, &image);
	callback_Demo(10, &image);
}

在前面的教程中,我们介绍了两种基本的形态学操作:

  • 腐蚀
  • 膨胀

基于这两个,我们可以对我们的图像进行更复杂的转换。在这里,我们简要讨论OpenCV提供的5个操作:

3.开运算—先腐蚀后膨胀

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

函数:

morphologyEx(mask_image, opening_image, MORPH_OPEN, element);

示例代码:

void QuickDemo::twelve(Mat& image) {
	Mat dst;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
	morphologyEx(image, dst, MORPH_OPEN, kernel);
	namedWindow("形态学操作", WINDOW_AUTOSIZE);
	imshow("形态学操作", dst);
}

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

4.闭运算—先膨胀后腐蚀 

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

void QuickDemo::twelve(Mat& image) {
	Mat dst;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(10, 10), Point(-1, -1));
	morphologyEx(image, dst, MORPH_CLOSE, kernel);
	namedWindow("形态学操作", WINDOW_AUTOSIZE);
	imshow("形态学操作", dst);
}

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

5.形态学梯度(膨胀-腐蚀)

形态学梯度运算是用图像的膨胀图像减腐蚀图像的操作,该操作可以获取原始图像中前景图像的边缘。

  • 这是图像的扩张和侵蚀的区别。

OpenCV更多形态转化

  • 找到对象的轮廓是有用的,如下所示:

OpenCV更多形态转化

代码如下:

void QuickDemo::twelve(Mat& image) {
	Mat dst;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
	morphologyEx(image, dst, MORPH_GRADIENT, kernel);
	namedWindow("形态学操作", WINDOW_AUTOSIZE);
	imshow("形态学操作", dst);
}

 

6. 顶帽运算(src-开运算)

顶帽运算是用原始图像减去其开运算图像的操作。顶帽运算能够获取图像的噪声信息,或者得到比原始图像的边缘更亮的边缘信息。

代码如下:

void QuickDemo::twelve(Mat& image) {
	Mat dst;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
	morphologyEx(image, dst, MORPH_TOPHAT, kernel);
	namedWindow("形态学操作", WINDOW_AUTOSIZE);
	imshow("形态学操作", dst);
}

7.黑帽运算(闭运算-src)

黑帽运算是用闭运算图像减去原始图像的操作。黑帽运算能够获取图像内部的小孔,或前景色中的小黑点,或者得到比原始图像的边缘更暗的边缘部分。

void QuickDemo::twelve(Mat& image) {
	Mat dst;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
	morphologyEx(image, dst, MORPH_BLACKHAT, kernel);
	namedWindow("形态学操作", WINDOW_AUTOSIZE);
	imshow("形态学操作", dst);
}

原图像:


http://www.kler.cn/a/315632.html

相关文章:

  • SQL 中 BETWEEN AND 用于字符串的理解
  • 分布式锁实践方案
  • OpenGL ES 共享上下文实现多线程渲染
  • 深入解析 OpenHarmony 构建系统-4-OHOSLoader类
  • [代码随想录Day10打卡] 理论基础 232.用栈实现队列 225. 用队列实现栈 20. 有效的括号 1047. 删除字符串中的所有相邻重复项
  • GaussDB部署架构
  • 分布式安装LNMP
  • [OpenCV] 数字图像处理 C++ 学习——16直方图均衡化、直方图比较 详细讲解+附完整代码
  • 超详细的XML介绍【附带dom4j操作XML】
  • 口腔检测系统源码分享
  • php怎么连接使用kafka
  • 【AI算法岗面试八股面经【超全整理】——NLP】
  • 学生管理系统1.0版本
  • Kotlin 基本介绍(一)
  • 如何确保消息只被消费一次:Java实现详解
  • Python 中的 HTTP 编程入门,如何使用 Requests 请求网络
  • 实现人体模型可点击
  • Kotlin 枚举和 when 表达式(六)
  • 关于Python sklearn CountVectorizer使用详解
  • 多模态论文串讲-学习笔记(上)
  • docker配置镜像加速器
  • 亚马逊IP关联揭秘:发生ip关联如何处理
  • 【BEV 视图变换】Ray-based(2): 代码复现+画图解释 基于深度估计、bev_pool
  • MoveIt控制机械臂的运动实现——机器人抓取系统基础系列(二)
  • 带你0到1之QT编程:十七、Http协议实战,实现一个简单服务器和一个客户端进行http协议通信
  • 校园美食发现:Spring Boot技术的美食社交平台