OpenCV-Python图像处理:腐蚀和膨胀原理及erode、dilate函数介绍

☞ ░ 前往老猿Python博客 https://blog.csdn.net/LaoYuanPython

在这里插入图片描述

一、引言

关于图像的腐蚀和膨胀,网上介绍的资料非常多,老猿也看了很多,总体来说主要偏向于就使用OpenCV腐蚀和膨胀函数的应用,另外原理介绍的有一小部分,对于初学者有很多的帮助,但如果想知其所以然则总体来说是不够的。

从《OpenCV-Python常用图像运算:加减乘除幂开方对数及位运算:https://blog.csdn.net/LaoYuanPython/article/details/108879397》这篇博文发布到现在,老猿花了较多的时间针对腐蚀和膨胀的原理以及一些比较偏门的问题进行了比较深入的研究,这半个月每晚都花近三个小时在与此相关的研究上。研究期间查阅了大量资料、做了大量测试,还咨询了一个做这方面的老同学,到今天基本上自认为弄清楚了,因此准备就这个方面写3-5篇与网上已有资料有些差异的博文,通过不同角度来阐述相关内容,希望于对这方面细节感兴趣的同仁有所裨益。

本文是老猿关于图像腐蚀与膨胀系列博文之一,该系列包括如下博文:

  1. OpenCV-Python图像处理:腐蚀和膨胀原理及erode、dilate函数介绍:https://blog.csdn.net/LaoYuanPython/article/details/109441709
  2. OpenCV-Python腐蚀膨胀函数erode、dilate使用详解:https://blog.csdn.net/LaoYuanPython/article/details/109477130
  3. OpenCV-Python图像矩阵不扩充边界腐蚀膨胀函数处理算法探究:https://blog.csdn.net/LaoYuanPython/article/details/109283825
  4. OpenCV图像腐蚀膨胀算法的Python模拟实现:
    https://blog.csdn.net/LaoYuanPython/article/details/109407091

本文作为老猿介绍图像腐蚀和膨胀处理的首篇文章,主要介绍腐蚀和膨胀的基础概念、腐蚀和膨胀的基本运算过程、OpenCV腐蚀和膨胀函数erode、dilate语法以及简单应用,并提供了老猿觉得有参考价值的一些博文参考。
在这里插入图片描述

二、基础概念

图像的膨胀(Dilation)和腐蚀(Erosion)是两种基本的形态学运算,主要用来寻找图像中的极大区域和极小区域。其中膨胀类似于“领域扩张”,将图像中的高亮区域或白色部分进行扩张,其运行结果图比原图的高亮区域更大;腐蚀类似于“领域被蚕食”,将图像中的高亮区域或白色部分进行缩减细化,其运行结果图比原图的高亮区域更小。

具体处理时,腐蚀和膨胀都类似于在在《数字图像处理:理解什么是卷积(滤波)、卷积核以及相关参考资料(博文地址:https://blog.csdn.net/LaoYuanPython/article/details/108841819))》介绍的卷积处理。

卷积处理是针对图像对应的矩阵使用一个参考矩阵(卷积核)在图像矩阵中从左到右、从上到下的进行移动,移动到指定位置时,卷积核矩阵与图像矩阵重合范围内的对应元素相乘后得到积矩阵,卷积就是将积矩阵各元素和相加得到的值作为结果图像矩阵锚点对应位置元素的值。

腐蚀则是将对应核矩阵元素不为0位置的图像矩阵中所有元素的最小值作为结果图像矩阵锚点位置的对应元素值,膨胀则是将对应核矩阵元素不为0位置的图像矩阵中所有元素的最大值作为结果图像矩阵锚点位置的对应元素值。
在这里插入图片描述

三、OpenCV函数

3.1、腐蚀和膨胀函数
erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)#腐蚀函数

dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)#膨胀函数
3.2、函数语法说明

腐蚀和膨胀函数的参数相同,返回值都是结果矩阵,相关参数含义如下:

  • src:需要腐蚀和膨胀的图像源矩阵
  • kernel:核矩阵
  • dst:返回结果矩阵,如果传值,可以不用将返回值赋值给单独的结果变量,直接使用dst即可,但dst必须先定义,老猿不推荐传该参数,因为使用没有直接返回结果赋值给结果变量方便
  • anchor:核矩阵锚点,不传值或传值为(-1,-1)则取核矩阵的中心位置作为锚点
  • iterations:迭代次数,每多迭代一次相当于以该值为1返回的结果作为src、以iterations为1、其他参数保持不变再次调用腐蚀或膨胀函数一次
  • borderType:扩充边界的模式,缺省值None表示不进行边界扩充
  • borderValue:当borderType=cv2.BORDER_CONSTANT时,扩充边界的元素以borderValue填充
3.3、关于kernel核矩阵

kernel核矩阵可以通过getStructuringElement函数构建,也可以自己单独构建。通过getStructuringElement构建时,可以传入两个参数,对应语法如下:
getStructuringElement(shape, ksize, anchor=None)

  • 参数shape表示核的形状,有如下三个取值:
  1. cv2.MORPH_RECT:长方形或正方形矩阵,矩阵中每个元素都为1。如图为一个5*5的正方形矩阵:
    在这里插入图片描述

  2. cv2.MORPH_CROSS:内置十字形矩阵,矩阵中和锚点同一列或同一行的每个元素都为1,其他元素都为0。下图为一个锚点为(2,3)的5*5内置十字形矩阵:
    在这里插入图片描述

  3. cv2.MORPH_ELLIPSE:内接椭圆形矩阵,矩阵中为1的元素构成一个椭圆,为该矩阵对应长方形的内接椭圆。下图为一个5*5内接椭圆矩阵:
    在这里插入图片描述

  • 参数ksize:矩阵的大小,表示宽和高的二元组,(3,3)表示3行3列矩阵,(6,4)表示4行6列的核矩阵

  • anchor:矩阵锚点,当shape为MORPH_CROSS时需要使用锚点的坐标

  • 返回值:构造的矩阵

3.4、关于borderType

在此直接以官网的表格来说明bordType取值的含义:
在这里插入图片描述
由于borderType不只是腐蚀和膨胀函数使用,在其他函数中也会使用,所以上述列表中的值并不能都在腐蚀和膨胀函数中使用:

  1. cv2.BORDER_WRAP:不能在腐蚀和膨胀函数中使用,官方文档有明确说明
  2. cv2.BORDER_TRANSPARENT:该值官网上没有说明,但老猿测试时发现报错:cv2.error: OpenCV(4.3.0) C:\projects\opencv-python\opencv\modules\core\src\copy.cpp:1179: error: (-5:Bad argument) Unknown/unsupported border type in function 'cv::borderInterpolate',老猿没有找到c++源代码进行核实,但测试来看应该也是不支持的。

另外缺省值为None时,老猿进行验证发现与cv2.BORDER_ISOLATED 值含义值相同,与列表中的说明可以相互印证。
在这里插入图片描述

四、腐蚀和膨胀对矩阵的影响图解

在《数字图像处理:理解什么是卷积(滤波)、卷积核以及相关参考资料》介绍了卷积核对图像处理过程,腐蚀和膨胀时核矩阵在图像矩阵中的移动过程与卷积是一样的,在此不重复介绍。下面通过案例来介绍腐蚀和膨胀结果矩阵的图像元素的生成过程。

4.1、案例1
图像源矩阵和核矩阵

在这里插入图片描述

锚点为红色标记的缺省中心位置,则针对源矩阵的S11和S88两个位置腐蚀和膨胀计算过程如下:

  1. 以核矩阵锚点位置与S11、S88对齐,形成核矩阵和源矩阵的重叠,对源矩阵来说,重叠区域请见上面两个颜色标记区域,其中深蓝色标记位置为核矩阵锚点对齐位置

  2. 由于核矩阵全为1,则腐蚀后结果矩阵ED的两个对应位置元素值为:
    ED11 = min(S00,S01,S02,S01,S11,S12,S20,S21,S22) = 0
    ED88 = min(S77,S78,S79,S87,S88,S89,S97,S98,S99) = 49

  3. 膨胀后结果矩阵DD的两个对应位置元素值为:
    DD11 = max(S00,S01,S02,S01,S11,S12,S20,S21,S22) = 4
    DD88 = max(S77,S78,S79,S87,S88,S89,S97,S98,S99) = 81

完整腐蚀和膨胀后的结果矩阵

在这里插入图片描述

上述案例的实现代码如下:
    import cv2,sys
    import numpy as np
    img = np.zeros((10, 10),np.uint8)
    for row in range(10):
        for col in range(10):
            img[row,col] = row*col


    kernalInt = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    imgErode = cv2.erode(img, kernalInt, borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgDilate = cv2.dilate(img, kernalInt, borderType=cv2.BORDER_CONSTANT, borderValue=0)
4.2、案例2
图像源矩阵和核矩阵

本案例和案例1的区别主要体现在两方面:

  1. 核矩阵非全0,锚点非中心位置,核矩阵锚点元素值为0
  2. 由于锚点位置的变化,导致计算S88的腐蚀和膨胀值时核矩阵覆盖范围超出了源矩阵

图像源矩阵案例1相同,核矩阵调整为了十字形,锚点为(0,0),还是以源矩阵的S11和S88为例,由于核的锚点与S88对齐时,核矩阵范围超出了源矩阵范围,在此采用扩充边界模式(扩充边界值固定为0),此时两个位置与核矩阵的重叠范围为下图浅蓝色标记区域:
在这里插入图片描述
针对源矩阵的S11和S88两个位置腐蚀和膨胀计算过程如下:

  1. 以核矩阵锚点位置与S11、S88对齐,形成核矩阵和源矩阵的重叠,对源矩阵来说,重叠区域请见上面两个颜色标记区域,其中深蓝色标记位置为核矩阵锚点对齐位置

  2. 取重叠区域核矩阵为1的源矩阵元素的最小值,则腐蚀后结果矩阵ED的两个对应位置元素值为:
    ED11 = min(S12,S22,S32,S21,S23) = 2
    ED88 = min(S89,S99,Sa9,S98,S9a) = 0

  3. 膨胀后结果矩阵DD的两个对应位置元素值为:
    DD11 = max(S12,S22,S32,S21,S23) = 6
    DD88 = max(S89,S99,Sa9,S98,S9a) = 81

完整腐蚀和膨胀后的结果矩阵

在这里插入图片描述

上述案例的实现代码如下:
    img = np.zeros((10, 10),np.uint8)
    for row in range(10):
        for col in range(10):
            img[row,col] = row*col

   
    kernalInt = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))

    imgErode = cv2.erode(img, kernalInt, anchor=(0,0),borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgDilate = cv2.dilate(img, kernalInt, anchor=(0,0), borderType=cv2.BORDER_CONSTANT, borderValue=0)

五、形态变换博文传送门

下面是老猿博文中与形态变换相关的博文列表:

  1. https://blog.csdn.net/LaoYuanPython/article/details/109441709 OpenCV-Python图像处理:腐蚀和膨胀原理及erode、dilate函数介绍
  2. https://blog.csdn.net/LaoYuanPython/article/details/109984045 OpenCV-Python图像运算变换处理:开运算和闭运算以及不同核矩阵的影响分析
  3. https://blog.csdn.net/LaoYuanPython/article/details/109556425 OpenCV-Python图像形态变换概述及morphologyEx函数介绍
  4. https://blog.csdn.net/LaoYuanPython/article/details/109768675 OpenCV-Python图像运算变换处理:形态学梯度运算及分类
  5. https://blog.csdn.net/LaoYuanPython/article/details/110195287 OpenCV-Python中预览超大图的程序实现方法
  6. https://blog.csdn.net/LaoYuanPython/article/details/110223709 OpenCV-Python图形图像处理:利用TopHat顶帽获取背景色中的噪点
  7. https://blog.csdn.net/LaoYuanPython/article/details/110294445 OpenCV-Python图形图像处理:利用黑帽去除图像浅色水印
  8. https://blog.csdn.net/LaoYuanPython/article/details/110676764 OpenCV-Python击中击不中HITMISS形态变换详解

附:一些参考资料

写作不易,敬请支持:

如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

小技巧: 可以通过点击博文下面的一键三连按钮实现对相关文章的点赞、收藏和对博客的关注,谢谢!

更多OpenCV-Python的介绍请参考专栏《OpenCV-Python图形图像处理 》
专栏网址https://blog.csdn.net/laoyuanpython/category_9979286.html

关于老猿的付费专栏

老猿的付费专栏《使用PyQt开发图形界面Python应用 》(https://blog.csdn.net/laoyuanpython/category_9607725.html)专门介绍基于Python的PyQt图形界面开发基础教程,付费专栏《moviepy音视频开发专栏》 (https://blog.csdn.net/laoyuanpython/category_10232926.html)详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,两个专栏都适合有一定Python基础但无相关知识的小白读者学习。

付费专栏文章目录:《moviepy音视频开发专栏文章目录》(https://blog.csdn.net/LaoYuanPython/article/details/107574583)、《使用PyQt开发图形界面Python应用专栏目录 》(https://blog.csdn.net/LaoYuanPython/article/details/107580932)。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《专栏:Python基础教程目录》(https://blog.csdn.net/laoyuanpython/category_9831699.html)从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

跟老猿学Python、学OpenCV!

☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython
  • 56
    点赞
  • 176
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LaoYuanPython

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值