膨胀、腐蚀、开、闭运算——数字图像处理中的形态学

膨胀、腐蚀、开、闭运算是数学形态学最基本的变换

  • 膨胀:把二值图像各1像素连接成分的边界扩大一层(填充边缘或0像素内部的孔);

  • 腐蚀:把二值图像各1像素连接成分的边界点去掉从而缩小一层(可提取骨干信息,去掉毛刺,去掉孤立的0像素);

  • 先腐蚀再膨胀,可以去掉目标外的孤立点

  • 先膨胀再腐蚀,可以去掉目标内的孔。

在这里插入图片描述

二值形态学概念

数学形态学中二值图像的形态变换是一种针对集合的处理过程。

其形态算子的实质是表达物体或形状的集合与结构元素间的相互作用,结构元素的形状就决定了这种运算所提取的信号的形状信息。形态学图像处理是在图像中移动一个结构元素,然后将结构元素与下面的二值图像进行交、并等集合运算。

基本的形态运算是腐蚀和膨胀
在形态学中,结构元素是最重要最基本的概念。

结构元素在形态变换中的作用相当于信号处理中的“滤波窗口”。用B(x)——代表结构元素,对工作空间E中的每一点x,腐蚀和膨胀的定义为:
在这里插入图片描述

  • 用B(x)对E进行腐蚀的结果就是把结构元素B平移后使B包含于E的所有点构成的集合。
  • 用B(x)对E进行膨胀的结果就是把结构元素B平移后使B与E的交集非空的点构成的集合。
  • 先腐蚀后膨胀的过程称为开运算。它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。
  • 先膨胀后腐蚀的过程称为闭运算。它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。

在这里插入图片描述

形态学操作

1、图像腐蚀

卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都为1,那么中心元素就保持原来的像素值,否则为0。

根据卷积核的大小靠近前景的所有像素都会被腐蚀掉(变为0),所以前景物体会变小,整幅图像的白色区域会减少。这对于去除白噪声很有用。

  • 说明
    通过特定的结构元素腐蚀图像。

    该函数使用指定的结构元素腐蚀源图像,该结构化元素确定在其上采用最小值的像素邻域的形状:
    在这里插入图片描述
    可以进行多次(迭代)腐蚀。在多通道图像的情况下,每个通道都是独立处理的。

  • 声明

    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输入图像,通道数可以是任意的,但深度应该为CV_8U,CV_16U,CV_16S,CV_32F或者CV_64F之一。
    dst输出与src大小和类型相同的图像。
    kernel用于侵蚀的结构元素;如果为element=Mat(),3 x 3则使用矩形结构元素。可以使用getStructuringElement创建内核
    anchor锚在元素内的位置;默认值(-1,-1)表示锚点位于元素中心。
    iterations施加腐蚀的次数。
    borderType
    borderValue边界不变时候的边界值。
  • 应用

    void erodeMethod(Mat &src) {
    	imshow("src", src);
    	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
    	erode(src, src, kernel, Point(-1, -1));
    	imshow("erode", src);
    }
    

    在这里插入图片描述
    在这里插入图片描述

2、图像膨胀

与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是 1,中心元 素的像素值就是 1。所以这个操作会增加图像中的白色区域(前景)。一般在去噪声时先用腐蚀再用膨胀

  • 说明
    通过使用特定的结构元素来扩展运行长度编码的二进制图像。

    该函数使用指定的结构元素对源图像进行扩展,该结构元素确定在其上取最大值的像素邻域的形状:
    dst ( x , y ) = max ⁡ ( x ′ , y ′ ) :   element ( x ′ , y ′ ) ≠ 0 src ( x + x ′ , y + y ′ ) \texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y') dst(x,y)=(x,y):element(x,y)=0maxsrc(x+x,y+y)
    可以进行几次(迭代)扩张。在多通道图像的情况下,每个通道都是独立处理的。

  • 声明

    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输入图像,通道可以任意,但深度应该为CV_8U,CV_16U,CV_16S,CV_32F或者CV_64F之一。
    dst输出与src大小和类型相同的图像。
    kernel用于扩张的结构元素;如果elemenat = Mat(),则使用3 x 3的矩形结构元素。可以使用getStructuringElement创建内核。
    anchor锚在元素内的位置;默认值(-1,-1)表示锚点位于元素中心。
    iteration扩张的次数。
    borderType参见BorderType。
    borderValue边界不变时的边界值。
  • 应用

    void dilateMethod(Mat &src) {
    	imshow("src", src);
    	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
    	dilate(src, src, kernel, Point(-1, -1));
    	imshow("dilate", src);
    }
    

    在这里插入图片描述 在这里插入图片描述

3、形态学操作

利用morphologyEx这个函数可以方便的对图像进行一系列的膨胀腐蚀组合。

3.1 函数说明
  • 说明
    执行高级形态转换。

    函数cv :: morphologyEx可以使用侵蚀和膨胀作为基本操作来执行高级形态转换。

    在多通道图像的情况下,每个通道都是独立处理的。

  • 声明

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

    src源图像。通道数可以是任意的。深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。
    dst与源图像大小和类型相同的目标图像。
    p形态学操作的类型,请参见MorphTypes
    kernel结构元素。可以使用getStructuringElement创建它。
    anchor内核的锚位置。负值表示锚点位于内核中心。
    iterations施加腐蚀和膨胀的次数。
    borderType边缘类型,默认为BORDER_CONSTANT。请参见BorderTypes。
    borderValue边界不变时的边界值。默认值具有特殊含义。
    参数op:操作的类型。
    enum MorphTypes{
     MORPH_ERODE    = 0, //腐蚀
     MORPH_DILATE   = 1, //膨胀
     MORPH_OPEN     = 2, //开操作
     MORPH_CLOSE    = 3, //闭操作
     MORPH_GRADIENT = 4, //梯度操作
     MORPH_TOPHAT   = 5, //顶帽操作
     MORPH_BLACKHAT = 6, //黑帽操作
     MORPH_HITMISS  = 7  
    };
    

    迭代次数是将应用腐蚀或膨胀操作的次数。例如,具有两个迭代的打开操作(MORPH_OPEN)等效于依次应用:腐蚀->腐蚀->膨胀->膨胀(而不是腐蚀->膨胀->腐蚀->膨胀)

3.2、操作类型

①MORPH_ERODE(腐蚀)
与erode函数的腐蚀效果相同。
②MORPH_DILATE(膨胀)
与dilate函数的膨胀效果相同。
③MORPH_OPEN(开)

  • 功能
    △消除小物体;
    △在纤细处分离物体;
    △平滑较大的边界并不明显改变其面积;

    数学公式:
    d s t = o p e n ( s r c , e l e m e m t ) = d i l a t e ( e r o d e ( s r c , e l e m e n t ) ) dst=open(src,elememt)=dilate(erode(src,element)) dst=open(src,elememt)=dilate(erode(src,element))
    在这里插入图片描述

  • 说明
    void openMethod(Mat &src) {
    	Mat dst;
    	Mat kernel = getStructuringElement(MORPH_RECT,Size(5,5));
    	morphologyEx(src,dst,MORPH_OPEN , kernel);
    	imshow("dst", dst);
    
    }
    int main() {
    	Mat src = imread("D:/test/weixin.jpg");
    	if (src.empty()) {
    		cout << "图片打开失败!" << endl;
    	}
    	imshow("src", src);
    	
    	openMethod(src);
    
    	waitKey(0);
    	return 0;
    }
    
    
    在这里插入图片描述
    在这里插入图片描述

④ MORPH_CLOSE(闭)

  • 功能
    消除小型黑洞(黑斑)。

    数学公式
    d s t = c l o s e ( s r c , e l e m e n t ) = e r o d e ( d i l a t e ( s r c , e l e m e n t ) ) dst=close(src,element)=erode(dilate(src,element)) dst=close(src,element)=erode(dilate(src,element))在这里插入图片描述

  • 应用
    void closeMethod(Mat& src) {
       Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
       morphologyEx(src, src, MORPH_CLOSE, kernel);
       imshow("close", src);
    
    在这里插入图片描述
    在这里插入图片描述

⑤ MORPH_GRADIENT(梯度)

  • 功能
    对二值图像进行这一操作可以将团块(blob)的边缘突出来。我们可以用形态学梯度来保留物体的边缘轮廓

    数学公式
    d s t = m o r p h _ g r a d i e n t ( s r c , e l e m e n t ) = d i l a t e ( s r c , e l e m e m t ) − e r o d e ( s r c , e l e m e n t ) dst=morph\_gradient(src,element)=dilate(src,elememt)-erode(src,element) dst=morph_gradient(src,element)=dilate(src,elememt)erode(src,element)
    在这里插入图片描述

    • 应用
      void gradientMethod(Mat& src) {
      	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
      	morphologyEx(src, src, MORPH_GRADIENT, kernel);
      	imshow("gradient", src);
      }
      
      在这里插入图片描述
      在这里插入图片描述

⑥MPRPH_TOPHAT(顶帽)

  • 功能
    因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原型轮廓周围的区域更明亮的区域。且这一操作和选择的核的大小有关。

    顶帽运算往往用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候,而微小物品比较有规律的时候,可以用顶帽运算进行背景提取。

    数学公式
    为原图像与上文刚介绍的“开运算”的结果图之差,表达式如下:
    d s t = t o p h a t ( s r c , e l e m e n t ) = s r c − o p e n ( s r c , e l e m e n t ) dst=tophat(src,element)=src-open(src,element) dst=tophat(src,element)=srcopen(src,element)
    在这里插入图片描述

  • 应用

    void tophatMethod(Mat& src) {
      Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
      morphologyEx(src, src, MORPH_TOPHAT, kernel);
      imshow("gradient", src);
    }
    

    在这里插入图片描述
    在这里插入图片描述

⑦MORPH_BLACKHAT(黑帽)

  • 功能
    黑帽(Black Hat)运算为”闭运算“的结果图与原图像之差。

    黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。
    所以,黑帽运算用来分离比邻近点暗一些的斑块

    数学表达式:
    d s t = b l a c k h a t ( s r c , e l e m e n t ) = c l o s e ( s r c , e l e m e n t ) − s r c dst=blackhat(src,element)=close(src,element)-src dst=blackhat(src,element)=close(src,element)src
    在这里插入图片描述

  • 应用

    void blackhatMethod(Mat& src) {
      Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
      morphologyEx(src, src, MORPH_BLACKHAT, kernel);
      imshow("gradient", src);
    }
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

举例应用

Mat src,dst1, dst2,dst3,dst4,dst5,dst6,dst7;
int step_size = 3;
int max_size = 21;
void my_dilate(int ,void*) {
	int s = step_size * 2 + 1;
	Mat structingElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
	dilate(src, dst1, structingElement);
	imshow("dilate", dst1);
	return;
}

void my_erode(int, void*) {
	int s = step_size * 2 + 1;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s));
	erode(src, dst2, kernel);
	imshow("erode", dst2);
	return;
}
void my_open(int, void*) {
	int s = step_size * 2 + 1;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s));
	morphologyEx(src, dst3, MORPH_OPEN, kernel);
	imshow("open", dst3);
}
void my_close(int, void*) {
	int s = step_size * 2 + 1;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s));
	morphologyEx(src, dst4, MORPH_CLOSE, kernel);
	imshow("close", dst4);
}
void my_gradient(int, void*) {
	int s = step_size * 2 + 1;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s));
	morphologyEx(src, dst5, MORPH_GRADIENT, kernel);
	imshow("gradient", dst5);
}
void my_tophat(int, void*) {
	int s = step_size * 2 + 1;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s));
	morphologyEx(src, dst6, MORPH_TOPHAT, kernel);
	imshow("tophat", dst6);
}
void my_blackhat(int, void*) {
	int s = step_size * 2 + 1;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(s, s));
	morphologyEx(src, dst7, MORPH_BLACKHAT, kernel);
	imshow("blackhat", dst7);
}

int main() {
    src = imread("D:\\jing.png");
	if (src.empty()) {
		cerr << "open error" << endl;
		return -1;
	}
	imshow("cat", src);
	my_dilate(0, 0);
	my_erode(0, 0);
	my_open(0, 0);
	my_close(0, 0);
	my_gradient(0, 0);
	my_tophat(0, 0);
	my_blackhat(0, 0);
	createTrackbar("erode_size", "erode", &step_size, max_size, my_erode);
	createTrackbar("erode_size", "dilate", &step_size, max_size,my_dilate);
	createTrackbar("erode_size", "open", &step_size, max_size, my_open);
	createTrackbar("erode_size", "close", &step_size, max_size, my_close);
	createTrackbar("erode_size", "gradient", &step_size, max_size, my_gradient);
	createTrackbar("erode_size", "tophat", &step_size, max_size, my_tophat);
	createTrackbar("erode_size", "blackhat", &step_size, max_size, my_blackhat);
	waitKey(0);
}

原图:
在这里插入图片描述

  • dilate
    白点不断变大
    在这里插入图片描述
    在这里插入图片描述

  • erode
    白点逐渐变小
    在这里插入图片描述
    在这里插入图片描述

  • open
    消除小物体;
    在纤细处分离物体;
    平滑较大的边界并不明显改变其面积
    在这里插入图片描述
    在这里插入图片描述

  • close
    祛除小黑点
    在这里插入图片描述
    在这里插入图片描述

  • gradient
    使轮廓更加清晰
    在这里插入图片描述
    在这里插入图片描述

  • 顶帽

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

  • 黑帽
    在这里插入图片描述
    在这里插入图片描述

好文章分享:
膨胀与腐蚀的彻底击破:https://www.cnblogs.com/daxiongblog/p/6289551.html
学习 opencv—(10)形态学图像处理(2):开运算,闭运算,形态学梯度,顶帽,黒帽合辑 https://www.cnblogs.com/wyuzl/p/6266498.html(NICE)

在这里插入图片描述

应用

二值形态膨胀与腐蚀可转化为集合的逻辑运算,算法简单,适于并行处理,且易于硬件实现,适于对二值图像进行图像分割、细化、抽取骨架、边缘提取、形状分析。但是,在不同的应用场合,结构元素的选择及其相应的处理算法是不一样的,对不同的目标图像需设计不同的结构元素和不同的处理算法。结构元素的大小、形状选择合适与否,将直接影响图像的形态运算结果

  • 数学形态学在图像处理中的主要应用包括:边缘检测、图像分割、形态骨架提取、噪声滤除。
  • 选取结构元素的方法:多结构元素、遗传算法。
膨胀腐蚀是图像处理常用的操作,可以通过OpenCV的相关API来实现。膨胀操作可以将图像的亮区域扩张,而腐蚀操作可以将图像的暗区域缩小。 在OpenCV,可以使用函数cv::dilate来实现膨胀操作。该函数的参数包括输入图像、输出图像、膨胀的结构单元、锚点位置、膨胀的次数等。其,结构单元可以是一个自定义的矩形,也可以使用函数getStructuringElement创建。 以下是一个实现膨胀腐蚀的代码示例: ```cpp #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { Mat image1 = imread("F:/photo/qx.jpg", 1); namedWindow("input_picture1"); imshow("input_picture1", image1); Mat image2; Mat image3; cvtColor(image1, image2, COLOR_RGB2GRAY); namedWindow("input_picture2"); imshow("input_picture2", image2); threshold(image2, image3, 65, 255, THRESH_BINARY); namedWindow("input_picture3"); imshow("input_picture3", image3); Mat eroded; erode(image3, eroded, Mat()); namedWindow("erode"); imshow("erode", eroded); Mat dilated; dilate(image3, dilated, Mat()); namedWindow("dilate"); imshow("dilate", dilated); waitKey(0); return 0; } ``` 上述代码,首读取一张图像,并将其转换为灰度图像。然后通过阈值处理得到二值图像。接下来,分别对二值图像进行腐蚀膨胀操作,并显示处理结果。可以根据实际需要调整参数和操作顺序。 希望对你有帮助!如果有更多问题,请随时提问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [13、OpenCV形态学操作——膨胀腐蚀](https://blog.csdn.net/phinoo/article/details/113105119)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [OpenCV图像处理学习十,图像的形态学操作——膨胀腐蚀](https://blog.csdn.net/weixin_44651073/article/details/126321876)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值