形态学操作-腐蚀与膨胀

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了形态学操作-腐蚀与膨胀相关的知识,希望对你有一定的参考价值。

参考技术A 1.形态学操作
形态学操作就是基于形状的一系列图像处理操作。一般情况下对二值化的图像进行操作。腐蚀与膨胀是最基本的形态学操作
应用:
(1)消除噪声
(2)分割(isolate)独立的图像元素,以及连接(join)相邻的元素
(3)寻找图像中的明显的极大值区域或者极小值区域
2.膨胀(最大值dilate)
此操作是将图像A与任意形状(通常为正方形或圆形)的内核B,,进行卷积。
内核B有一个可定义的 锚点, 通常定义为内核中心点。
进行膨胀操作时,将内核B划过图像,将内核B覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展” (因此有了术语膨胀 dilation )

src——输入图像.
dst——输出图像.
element——用于膨胀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
iterations——膨胀的次数
3.腐蚀(erode)
腐蚀提取的是内核覆盖下的相素最小值。进行腐蚀操作时,将内核B划过图像,将内核B覆盖区域的最小相素值提取,并代替锚点位置的相素。

src——输入图像.
dst——输出图像.
element——用于腐蚀的结构元素。若为 NULL, 则使用 3×3 长方形的结构元素
iterations——腐蚀的次数
4.结构元素
我们一般使用函数 getStructuringElement配合膨胀或腐蚀算法使用
Mat strElement = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3), new Point(-1, -1));
其中有三种内核形状可以选择:
矩形: MORPH_RECT
交叉形: MORPH_CROSS
椭圆形: MORPH_ELLIPSE
再指定内核大小,以及锚点位置。不指定锚点位置,则默认锚点在内核中心位置。
5.图像的开运算
开运算:先腐蚀后膨胀,移除小的对象时候很有用
6.图像的闭运算
闭运算:先膨胀后腐蚀,被用来填充前景物体中的小洞,或者抹去前景物体上的小黑点

7.梯度:膨胀与腐蚀图之差
可以用来突出边缘,可以保留物体的边缘轮廓
8.顶帽:原图与开运算结果之差
开运算放大了裂缝或者局部低亮度的区域,所以,从原图中减去开运算后的图,得到的结果突出了比原图轮廓周围的区域更明亮的区域,这个操作与选择的核的大小有关。TopHat运算一般用来分离比邻近点亮一些的斑块,可以使用这个运算提取背景
9.黑帽运算:闭运算的结果与原图之差
黑帽运算的结果突出了比原图轮廓周围区域更暗的区域,所以黑帽运算用来分离比邻近点暗一些的斑块。

参考: https://www.jianshu.com/p/6147d69c879f

OpenCV 形态学操作:膨胀与腐蚀

前导知识

图像形态学操作:基于形状的一系列图像处理操作的合集,主要是基于集合论基础上的形态学数学

形态学有四个基本操作:腐蚀、膨胀、开、闭

膨胀与腐蚀是图像处理中最常用的形态学操作手段

定义

膨胀

跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状。

这种操作会造成图像中像素值高的区域变大,而像素值小的区域变小。(亮区变粗,暗区变细)

腐蚀

腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值

这种操作会造成图像中像素值高的区域变小,而像素值小的区域变大。(亮区变细,暗区变粗)

API

结构元形状构造函数

函数原型:

getStructuringElement( 
	int shape, 
	Size ksize, 
	Point anchor
)

参数:

  • shape:结构元类型:
    1)MORPH_RECT 表示产生矩形的结构元
    2)MORPH_ELLIPSEM 表示产生椭圆形的结构元
    3)MORPH_CROSS 表示产生十字交叉形的结构元
  • ksize:表示结构元的尺寸,即(宽,高),必须是奇数
  • anchor:表示结构元的锚点,即参考点。默认值Point(-1, -1)代表中心像素为锚点

膨胀

函数原型:

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

参数:

  • src:表示输入矩阵
  • element:表示结构元,即 函数getStructuringElement( )的返回值
  • anchor:结构元的锚点,即参考点
  • iterations:膨胀操作的次数,默认为一次
  • borderType:边界扩充类型
  • borderValue:边界扩充值

腐蚀

函数原型:

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

参数:

  • src:表示输入矩阵
  • dst:表示输出矩阵
  • element:表示结构元,即 函数getStructuringElement( )的返回值
  • anchor:结构元的锚点,即参考点
  • iterations:腐蚀操作的次数,默认为一次
  • borderType:边界扩充类型
  • borderValue:边界扩充值

案例

案例中用到了 Trackbar 函数,可以参考我的另一篇博文学习 Trackbar:https://blog.csdn.net/weixin_45525272/article/details/121265662

膨胀

效果展示:

代码如下:

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>  

using namespace cv;
using namespace std;

Mat src, dst;                   // 全局变量
int element_size = 3;			// 全局变量
int max_size = 21;				// 全局变量

void CallBack_func(int, void*);
int main()
{
	src = imread("test2.jpg");
	if (src.empty())
	{
		printf("could not load the  image...\\n");
		return -1;
	}
	namedWindow("原图:", CV_WINDOW_AUTOSIZE);
	imshow("原图:", src);
	namedWindow("膨胀操作后:", CV_WINDOW_AUTOSIZE);
	createTrackbar("结构元尺寸 :", "膨胀操作后:", &element_size, max_size, CallBack_func);
	CallBack_func(element_size, 0);

	waitKey(0);
	return 0;
}

// 膨胀操作 Trackbar 回调函数
void CallBack_func(int, void*)
{
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));		// 创建结构元
	dilate(src, dst, structureElement, Point(-1, -1), 1);										// 调用膨胀API
	imshow("膨胀操作后:", dst);
}

腐蚀

效果展示:

代码如下:

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>  

using namespace cv;
using namespace std;

Mat src, dst;                   // 全局变量
int element_size = 3;			// 全局变量
int max_size = 21;				// 全局变量

void CallBack_func(int, void*);
int main()
{
	src = imread("test2.jpg");
	if (src.empty())
	{
		printf("could not load the  image...\\n");
		return -1;
	}
	namedWindow("原图:", CV_WINDOW_AUTOSIZE);
	imshow("原图:", src);
	namedWindow("腐蚀操作后:", CV_WINDOW_AUTOSIZE);
	createTrackbar("结构元尺寸 :", "腐蚀操作后:", &element_size, max_size, CallBack_func);
	CallBack_func(element_size, 0);

	waitKey(0);
	return 0;
}

// 腐蚀操作 Trackbar 回调函数
void CallBack_func(int, void*)
{
	int s = element_size * 2 + 1;
	Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));		// 创建结构元
	erode(src, dst, structureElement, Point(-1, -1), 1);										// 调用腐蚀API
	imshow("腐蚀操作后:", dst);
}

以上是关于形态学操作-腐蚀与膨胀的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 形态学操作:膨胀与腐蚀

OpenCV2:大学篇 形态学技术-腐蚀与膨胀操作

opencv:形态学操作-腐蚀与膨胀

形态学滤波:腐蚀与膨胀 开运算,闭运算,形态学梯度,顶帽,黑帽

08 OpenCV腐蚀膨胀与形态学运算

数字图像处理:形态学操作腐蚀膨胀开运算闭运算