OpenCV-Python腐蚀膨胀函数erode、dilate使用详解

OPenCV膨胀函数dilate()的使用 OPenCV版本:4.4 IDE:VS2007 功能描述 简述:使用一个指定的核元素去膨胀一个图像,图像膨胀的过程类似于一个卷积的过程,源图像矩阵A以及结构元素B,B在A矩阵上依次移动,每个位置上B所覆盖元素的最大值替换B的中心位置值(即锚点处),完成整个膨胀的过程。 函数使用一个指定的核元素去膨胀源图像,内核有一个可定义的 锚点,我们叫他内核中心点,膨胀操作时,获取内核覆盖区域最大像素值,并代替锚点的像素,最大值通过以下公式获取: dst(x,y)=max⁡(x′,y′): element(x′,y′. 阅读详情
☞ ░ 前往老猿Python博客 https://blog.youkuaiyun.com/LaoYuanPython ░

一、引言

在《OpenCV-Python图像处理:腐蚀和膨胀原理及erode、dilate函数介绍:https://blog.youkuaiyun.com/LaoYuanPython/article/details/109441709》介绍了图像腐蚀和膨胀的基本原理,以及OpenCV-Python对应函数erode、dilate的语法以及简单应用。

本节我们准备通过代码验证介绍一些关于OpenCV-Python对应函数erode、dilate一点比较细节和冷门的知识。

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

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

二、准备

2.1、测试函数准备

为了进行相关验证,老猿准备了如下两个函数用于输出矩阵数据以及进行矩阵内容是否相同比较:

2.1.1、矩阵输出函数print2DMatrix

print2DMatrix用于输出2阶矩阵的每个元素,每列元素间用Tab键隔开,可以很方便地将数据拷贝到excel中使用:

def print2DMatrix(matrix):
    """
    将2阶矩阵按照行和列方式打印输出每个元素
    :param matrix: 需要打印的矩阵
    :return: None
    """
    if len(matrix.shape)!=2:
        print("只能输出二阶矩阵的信息,传入实参不是二阶矩阵,退出!")
        return None

    x,y = matrix.shape
    for i in range(x):
        print(" ")
        for j in range(y):
            if matrix[i][j]==np.NaN:print(f' NAN',end=' ')
            if matrix.dtype in(np.uint8,np.uint,np.uint16,np.uint32):print(f'{matrix[i][j]:4d}',end='\t')
            else:print(f'{matrix[i][j]:4f}',end='\t')
    print("\n")
2.1.2、矩阵相等判断函数cmpMatrix

cmpMatrix函数用于比较两个矩阵的内容是否完全一致,如果是输出True,否则输出False。

def cmpMatrix(m1,m2):
    if m1.shape!=m2.shape:
        return False
    cmpM = m1==m2
    return cmpM.all()
2.2、处理素材准备
2.2.1、测试使用图片

图片文件名为pictures.png,图片内包含了多个OpenCV处理的经典图片,每张图片从1-13进行了编号,如下:
在这里插入图片描述
上述图片中,除了7号和8号图片的噪点外,3号图片增加了彩色噪点,在9号图片中加了两种不同颜色噪点、11号图片靠近左上角加了黑色噪点、13号图片靠近左下位置加了白色噪点。

2.2.2、测试小矩阵准备

除了使用图片测试外,还准备了一个10*10的小矩阵进行测试,便于输出数据查看。该矩阵的生成方法如下:

img = np.zeros((10, 10),np.uint8)
    for row in range(10):
        for col in range(10):
            img[row,col] = row*col

三、关于核矩阵的问题

3.1、核矩阵形状问题
3.1.1、具体问题
  1. 在网上看到的关于膨胀和腐蚀的介绍的文章,用到的核矩阵都是长和宽相等的正方形,那么核矩阵是否必须为正方形?
  2. 在《数字图像处理:理解什么是卷积(滤波)、卷积核以及相关参考资料》中介绍“卷积核的大小应该是奇数,这样它才有一个中心”,腐蚀和膨胀函数中的核矩阵是否必须是奇数大小?
3.1.2、验证

用代码生成一个长方形的长和宽都为偶数的核矩阵,然后对图像矩阵进行腐蚀和膨胀处理,看程序是否正常运行。

对应代码如下:

def kernalTest():#测试腐蚀和膨胀的核的作用函数

    imgMatrix = cv2.imread(r'F:\pic\pictures.png', cv2.IMREAD_GRAYSCALE) #读入图片转成灰度图像矩阵imgMatrix
    #构造小矩阵littleMatrix
    littleMatrix = np.zeros((10, 10), np.uint8)
    for row in range(10):
        for col in range(10):
            littleMatrix[row, col] = row * col

    kernal64 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(6, 4))
    imgErode = cv2.erode(littleMatrix, kernal64,  borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgDilate = cv2.dilate(littleMatrix, kernal64,  borderType=cv2.BORDER_CONSTANT, borderValue=0)
    print("kernal64矩阵内容:")
    print2DMatrix(kernal64)
    print("littleMatrix小矩阵数据如下:")
    print2DMatrix(littleMatrix)
    print("littleMatrix小矩阵腐蚀后结果数据如下:")
    print2DMatrix(imgErode)
    print("littleMatrix小矩阵膨胀后结果数据如下:")
    print2DMatrix(imgDilate)



    imgErode = cv2.erode(imgMatrix, kernal64, borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgDilate = cv2.dilate(imgMatrix, kernal64, borderType=cv2.BORDER_CONSTANT, borderValue=0)
    cv2.imshow('imgErode', imgErode)
    cv2.imshow('imgDilate', imgDilate)

    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
kernalTest()

程序执行打印输出内容如下:

kernal64矩阵内容:
 
   0	   0	   0	   1	   0	   0	 
   1	   1	   1	   1	   1	   1	 
   1	   1	   1	   1	   1	   1	 
   1	   1	   1	   1	   1	   1	

littleMatrix小矩阵数据如下:
 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   1	   2	   3	   4	   5	   6	   7	   8	   9	 
   0	   2	   4	   6	   8	  10	  12	  14	  16	  18	 
   0	   3	   6	   9	  12	  15	  18	  21	  24	  27	 
   0	   4	   8	  12	  16	  20	  24	  28	  32	  36	 
   0	   5	  10	  15	  20	  25	  30	  35	  40	  45	 
   0	   6	  12	  18	  24	  30	  36	  42	  48	  54	 
   0	   7	  14	  21	  28	  35	  42	  49	  56	  63	 
   0	   8	  16	  24	  32	  40	  48	  56	  64	  72	 
   0	   9	  18	  27	  36	  45	  54	  63	  72	  81	

littleMatrix小矩阵腐蚀后结果数据如下:
 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   0	   0	   0	   2	   4	   6	   7	   0	   0	 
   0	   0	   0	   0	   3	   6	   9	  12	   0	   0	 
   0	   0	   0	   0	   4	   8	  12	  16	   0	   0	 
   0	   0	   0	   0	   5	  10	  15	  20	   0	   0	 
   0	   0	   0	   0	   6	  12	  18	  24	   0	   0	 
   0	   0	   0	   0	   7	  14	  21	  28	   0	   0	 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	

littleMatrix小矩阵膨胀后结果数据如下:
 
   2	   3	   4	   5	   6	   7	   8	   9	   9	   9	 
   4	   6	   8	  10	  12	  14	  16	  18	  18	  18	 
   6	   9	  12	  15	  18	  21	  24	  27	  27	  27	 
   8	  12	  16	  20	  24	  28	  32	  36	  36	  36	 
  10	  15	  20	  25	  30	  35	  40	  45	  45	  45	 
  12	  18	  24	  30	  36	  42	  48	  54	  54	  54	 
  14	  21	  28	  35	  42	  49	  56	  63	  63	  63	 
  16	  24	  32	  40	  48	  56	  64	  72	  72	  72	 
  18	  27	  36	  45	  54	  63	  72	  81	  81	  81	 
  18	  27	  36	  45	  54	  63	  72	  81	  81	  81

从上面输出内容可以看出,核矩阵第1行第4列值为1,为内接椭圆顶点,因此也是默认中心点的横坐标,值为3=6/2,按此推测,则默认中心点为(3,2),以此核实相关结果矩阵数据,与输出结果相同。

除了输出小矩阵的腐蚀情况数据,程序还输出了图像矩阵的截图,其中腐蚀后图像如下:
在这里插入图片描述
可以看到原图对应灰度图腐蚀后,除了常规的亮度区域变小黑色区域变大外,3号图片噪点增大,7号、9号、13号图片噪点消失,11号图片黑色噪点扩大。

图片膨胀后结果图像如下:
在这里插入图片描述
可以看到原图对应灰度图膨胀后,除了亮度区域变大黑色区域变小外,3号图片噪点基本消失,7号、9号、13号图片噪点扩大,11号图片黑色噪点消失。

3.1.3、结论

经上述代码验证,核矩阵为长方形且长和宽为偶数情况下,腐蚀和膨胀都能正常执行。

3.2、核矩阵元素值相关问题
3.2.1、具体问题
  1. getStructuringElement函数生成的核矩阵元素全为0或1,该矩阵元素的类型是什么?核矩阵是否允许非0或1的数据甚至浮点数?
  2. 在《数字图像处理:理解什么是卷积(滤波)、卷积核以及相关参考资料》中介绍卷积运算是将源图像矩阵和核相乘后再相加,而腐蚀和膨胀是取核矩阵不为0部分对应源矩阵的最小值或最大值作为腐蚀或膨胀的结果。验证一下是否确实腐蚀和膨胀无需源矩阵和核矩阵相乘再取最小值或最大值。
3.2.2、验证

用代码生成一个3*3的数据为浮点数的核矩阵,然后对图像矩阵进行腐蚀和膨胀处理,看程序是否正常运行。

对应代码如下:

def kernalTest():#测试腐蚀和膨胀的核的作用函数
    littleMatrix = np.zeros((10, 10), np.uint8)
    for row in range(10):
        for col in range(10):
            littleMatrix[row, col] = row * col


    kernal33 = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
    kernal33Float = kernal33.astype(np.float32)*0.1

    print(f"kernal33矩阵元素类型为:{kernal33.dtype},数据内容如下:")
    print2DMatrix(kernal33)
    print(f"kernal33Float矩阵元素类型为:{kernal33Float.dtype},数据内容如下:")
    print2DMatrix(kernal33Float)

    imgErode = cv2.erode(littleMatrix, kernal33,  borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgDilate = cv2.dilate(littleMatrix, kernal33,  borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgErodeFloat = cv2.erode(littleMatrix, kernal33Float, borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgDilateFloat = cv2.dilate(littleMatrix, kernal33Float, borderType=cv2.BORDER_CONSTANT, borderValue=0)



    print("littleMatrix小矩阵数据如下:")
    print2DMatrix(littleMatrix)
    print(f"littleMatrix小矩阵采用普通0、1核矩阵腐蚀后矩阵元素类型为:{kernal33Float.dtype},结果数据如下:")
    print2DMatrix(imgErode)
    print(f"littleMatrix小矩阵采用采用普通0、1核矩阵膨胀后矩阵元素类型为:{kernal33Float.dtype},结果数据如下:")
    print2DMatrix(imgDilate)

    print(f"littleMatrix小矩阵采用浮点核矩阵腐蚀后矩阵元素类型为:{kernal33Float.dtype},结果数据如下:")
    print2DMatrix(imgErodeFloat)
    print(f"littleMatrix小矩阵采用浮点核矩阵膨胀后矩阵元素类型为:{kernal33Float.dtype},结果数据如下:")
    print2DMatrix(imgDilateFloat)

    if cmpMatrix(imgErode,imgErodeFloat):
        print("使用普通0、1核矩阵腐蚀和采用浮点核矩阵腐蚀得到的结果矩阵相同")
    else:
        print("使用普通0、1核矩阵腐蚀和采用浮点核矩阵腐蚀得到的结果矩阵不相同")
    if cmpMatrix(imgDilate, imgDilateFloat):
        print("使用普通0、1核矩阵膨胀和采用浮点核矩阵膨胀得到的结果矩阵相同")
    else:
        print("使用普通0、1核矩阵膨胀和采用浮点核矩阵膨胀得到的结果矩阵不相同")

kernalTest()

程序执行打印输出内容如下:

kernal33矩阵元素类型为:uint8,数据内容如下:
 
   1	   1	   1	 
   1	   1	   1	 
   1	   1	   1	

kernal33Float矩阵元素类型为:float32,数据内容如下:
 
0.100000	0.100000	0.100000	 
0.100000	0.100000	0.100000	 
0.100000	0.100000	0.100000	

littleMatrix小矩阵数据如下:
 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   1	   2	   3	   4	   5	   6	   7	   8	   9	 
   0	   2	   4	   6	   8	  10	  12	  14	  16	  18	 
   0	   3	   6	   9	  12	  15	  18	  21	  24	  27	 
   0	   4	   8	  12	  16	  20	  24	  28	  32	  36	 
   0	   5	  10	  15	  20	  25	  30	  35	  40	  45	 
   0	   6	  12	  18	  24	  30	  36	  42	  48	  54	 
   0	   7	  14	  21	  28	  35	  42	  49	  56	  63	 
   0	   8	  16	  24	  32	  40	  48	  56	  64	  72	 
   0	   9	  18	  27	  36	  45	  54	  63	  72	  81	

littleMatrix小矩阵采用普通0、1核矩阵腐蚀后矩阵元素类型为:uint8,结果数据如下:
 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   0	   1	   2	   3	   4	   5	   6	   7	   0	 
   0	   0	   2	   4	   6	   8	  10	  12	  14	   0	 
   0	   0	   3	   6	   9	  12	  15	  18	  21	   0	 
   0	   0	   4	   8	  12	  16	  20	  24	  28	   0	 
   0	   0	   5	  10	  15	  20	  25	  30	  35	   0	 
   0	   0	   6	  12	  18	  24	  30	  36	  42	   0	 
   0	   0	   7	  14	  21	  28	  35	  42	  49	   0	 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	

littleMatrix小矩阵采用采用普通0、1核矩阵膨胀后矩阵元素类型为:uint8,结果数据如下:
 
   1	   2	   3	   4	   5	   6	   7	   8	   9	   9	 
   2	   4	   6	   8	  10	  12	  14	  16	  18	  18	 
   3	   6	   9	  12	  15	  18	  21	  24	  27	  27	 
   4	   8	  12	  16	  20	  24	  28	  32	  36	  36	 
   5	  10	  15	  20	  25	  30	  35	  40	  45	  45	 
   6	  12	  18	  24	  30	  36	  42	  48	  54	  54	 
   7	  14	  21	  28	  35	  42	  49	  56	  63	  63	 
   8	  16	  24	  32	  40	  48	  56	  64	  72	  72	 
   9	  18	  27	  36	  45	  54	  63	  72	  81	  81	 
   9	  18	  27	  36	  45	  54	  63	  72	  81	  81	

littleMatrix小矩阵采用浮点核矩阵腐蚀后矩阵元素类型为:uint8,结果数据如下:
 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	 
   0	   0	   1	   2	   3	   4	   5	   6	   7	   0	 
   0	   0	   2	   4	   6	   8	  10	  12	  14	   0	 
   0	   0	   3	   6	   9	  12	  15	  18	  21	   0	 
   0	   0	   4	   8	  12	  16	  20	  24	  28	   0	 
   0	   0	   5	  10	  15	  20	  25	  30	  35	   0	 
   0	   0	   6	  12	  18	  24	  30	  36	  42	   0	 
   0	   0	   7	  14	  21	  28	  35	  42	  49	   0	 
   0	   0	   0	   0	   0	   0	   0	   0	   0	   0	

littleMatrix小矩阵采用浮点核矩阵膨胀后矩阵元素类型为:uint8,结果数据如下:
 
   1	   2	   3	   4	   5	   6	   7	   8	   9	   9	 
   2	   4	   6	   8	  10	  12	  14	  16	  18	  18	 
   3	   6	   9	  12	  15	  18	  21	  24	  27	  27	 
   4	   8	  12	  16	  20	  24	  28	  32	  36	  36	 
   5	  10	  15	  20	  25	  30	  35	  40	  45	  45	 
   6	  12	  18	  24	  30	  36	  42	  48	  54	  54	 
   7	  14	  21	  28	  35	  42	  49	  56	  63	  63	 
   8	  16	  24	  32	  40	  48	  56	  64	  72	  72	 
   9	  18	  27	  36	  45	  54	  63	  72	  81	  81	 
   9	  18	  27	  36	  45	  54	  63	  72	  81	  81	

使用普通0、1核矩阵腐蚀和采用浮点核矩阵腐蚀得到的结果矩阵相同
使用普通0、1核矩阵膨胀和采用浮点核矩阵膨胀得到的结果矩阵相同

Process finished with exit code 0

将核矩阵的元素换成其他数字,如直接在kernal33的元素值上乘以2作为核的元素值,结论相同。

3.2.3、结论

经测试验证核矩阵元素:

  1. 类型可以是各种矩阵元素允许的类型;
  2. 允许非0或1的数据甚至浮点数作为元素,非0的核矩阵元素与为1的核矩阵元素效果相同,腐蚀和膨胀时核元素只决定了源矩阵中的哪些元素参与运算,但核矩阵所有非0元素对腐蚀和膨胀的处理效果相同,即核矩阵中元素非0值本身无论取值多少都不会影响腐蚀和膨胀的效果。

但测试时发现有个问题,就是当核矩阵元素为浮点数时,核矩阵的元素不能出现0、0.0等零值,否则会出现如下异常:

cv2.error: OpenCV(4.3.0) C:/projects/opencv-python/opencv/modules/imgproc/src/morph.simd.hpp:649: error: (-215:Assertion failed) _kernel.type() == CV_8U in function 'cv::opt_AVX2::`anonymous-namespace'::MorphFilter<struct cv::opt_AVX2::`anonymous namespace'::MinOp<unsigned char>,struct cv::opt_AVX2::A0x30080e86::MorphVec<struct cv::opt_AVX2::`anonymous namespace'::VMin<struct cv::hal_AVX2::v_uint8x32> > >::MorphFilter'

该问题具体原因老猿暂时没有去研究。

总体来说,除了浮点类型的核矩阵不能出现零值外,核矩阵(必须小于源矩阵)可以自定义(就如同上面代码定义littleMatrix矩阵一样),其各元素的值可以随意赋值,不一定非要通过getStructuringElement构建核矩阵,大家可以自己尝试一下。

四、腐蚀和膨胀处理的图像矩阵问题

在老猿所查阅的所有介绍腐蚀和膨胀的资料中,腐蚀和膨胀处理的图像都是灰度图,没有看到处理彩色图像的,查阅官网资料,明确告知源图像矩阵可以是任意通道数的。

为此老猿做了验证,直接使用彩色图像进行腐蚀和膨胀,我们来看效果。

源代码:
def srcImgTest(imgfile):#测试腐蚀和膨胀的图像源类型函数
    img = cv2.imread(imgfile) 
    kernal = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    imgErode = cv2.erode(img, kernal, borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgDilate = cv2.dilate(img, kernal, borderType=cv2.BORDER_CONSTANT, borderValue=0)
    print("kernal:")
    print2DMatrix(kernal)
    cv2.imshow('imgErode', imgErode)
    cv2.imshow('imgDilate', imgDilate)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


srcImgTest(r'F:\pic\pictures.png')#处理彩色图像文件

腐蚀结果图像截图:
在这里插入图片描述
可以看到原图腐蚀后,总体图像变暗,除了常规的亮度区域变小浅色区域变大外,3号图片彩色噪点变大,7号、9号、13号图片噪点消失,11号图片黑色噪点扩大。

膨胀结果图像截图:
在这里插入图片描述
可以看到原图膨胀后,总体变亮,除了常规的亮度区域变大暗色区域变小外,3号图片彩色噪点与腐蚀一样变大,7号、9号、13号图片噪点变大,8号、11号图片黑色噪点消失。

因此可以得出结论,腐蚀和膨胀可以直接对彩色图像进行处理,可以用于消除部分噪点,并且这种处理方式无法通过灰度图进行腐蚀和膨胀再进行其他图像操作来达到相同效果,但总体来说灰度图的腐蚀和膨胀对图像轮廓的处理应用更广,同样有彩色图像腐蚀和膨胀无法替代的能力。

五、边界类型问题

5.1、问题

在《OpenCV-Python图像处理:腐蚀和膨胀原理及erode、dilate函数介绍:https://blog.youkuaiyun.com/LaoYuanPython/article/details/109441709》中介绍了腐蚀和膨胀函数的参数borderType的值的含义,但该值缺省值为None,具体对应的边界类型官网没有介绍。只是从边界类型取值说明中感觉BORDER_ISOLATED 这个值比较象。

5.2、验证

构建一个矩阵,用所有可能的边界类型进行腐蚀和膨胀处理,与采用borderType为None的腐蚀和膨胀结果进行对比。

验证代码:
def bordtypeTest():
    bordetype={cv2.BORDER_CONSTANT:"BORDER_CONSTANT",cv2.BORDER_REPLICATE:"BORDER_REPLICATE ",cv2.BORDER_REFLECT:"BORDER_REFLECT",
               cv2.BORDER_REFLECT_101:'BORDER_REFLECT_101', cv2.BORDER_ISOLATED:'BORDER_ISOLATED'}
    img = np.zeros((100,100),np.uint8)

    for row in range(100):
        for col in range(100):
            img[row, col] = row*2+ col

    kernal = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
    #kernal = np.zeros((3,3),dtype=np.uint8)
    kernal[0,0]  = 1
    imgDefaultErode = cv2.erode(img, kernal)
    imgDefaultDilate = cv2.dilate(img, kernal)
    for k in bordetype:
        v = bordetype[k]

        if k==0:
            imgErode = cv2.erode(img, kernal, borderType=k, borderValue=0)
            imgDilate = cv2.dilate(img, kernal, borderType=k, borderValue=0)
        else:
            imgErode = cv2.erode(img, kernal, borderType=k)
            imgDilate = cv2.dilate(img, kernal, borderType=k)


        cmpErode = cmpMatrix(imgErode,imgDefaultErode)
        cmpDilate = cmpMatrix(imgDilate,imgDefaultDilate)
        if cmpErode:
            print(f"bordtype={v}的腐蚀结果与缺省bordtype腐蚀图像相同")
        else:print(f"bordtype={v}的腐蚀结果与缺省bordtype腐蚀图像不同")
        if cmpDilate:
            print(f"bordtype={v}的膨胀结果与缺省bordtype膨胀图像相同")
        else:print(f"bordtype={v}的膨胀结果与缺省bordtype膨胀图像不同")


bordtypeTest()
输出:
bordtype=BORDER_CONSTANT的腐蚀结果与缺省bordtype腐蚀图像不同
bordtype=BORDER_CONSTANT的膨胀结果与缺省bordtype膨胀图像相同
bordtype=BORDER_REPLICATE 的腐蚀结果与缺省bordtype腐蚀图像不同
bordtype=BORDER_REPLICATE 的膨胀结果与缺省bordtype膨胀图像相同
bordtype=BORDER_REFLECT的腐蚀结果与缺省bordtype腐蚀图像不同
bordtype=BORDER_REFLECT的膨胀结果与缺省bordtype膨胀图像相同
bordtype=BORDER_REFLECT_101的腐蚀结果与缺省bordtype腐蚀图像相同
bordtype=BORDER_REFLECT_101的膨胀结果与缺省bordtype膨胀图像不同
bordtype=BORDER_ISOLATED的腐蚀结果与缺省bordtype腐蚀图像相同
bordtype=BORDER_ISOLATED的膨胀结果与缺省bordtype膨胀图像相同
5.3、结论

从上述输出可以看出,除了bordtype=BORDER_ISOLATED与等于None效果完全相同,其他值不能完全相同,并且在多种不同图像下上述输出的比较情况还会发生变化,但BORDER_ISOLATED的比较情况固定不变。

六、迭代次数的影响

在腐蚀和膨胀处理的参数中,iterations形参对应实参n(n大于1)的作用我们认为是针对每次腐蚀的结果再次进行腐蚀,直到执行腐蚀n次。

验证代码:
def iterationsImgTest(imgfile):#测试腐蚀和膨胀的图像源类型函数
    img = cv2.imread(imgfile)
    kernal = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    imgErode1 = cv2.erode(img, kernal, borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgErode2 = cv2.erode(imgErode1, kernal, borderType=cv2.BORDER_CONSTANT, borderValue=0)
    imgErodeIterations = cv2.erode(img, kernal, iterations=2,borderType=cv2.BORDER_CONSTANT, borderValue=0)
    if cmpMatrix(imgErode1,imgErodeIterations):
        print("腐蚀1次结果图像和迭代腐蚀2次结果图像相同")
    else:
        print("腐蚀1次结果图像和迭代腐蚀2次结果图像不相同")
    if cmpMatrix(imgErode2,imgErodeIterations):
        print("腐蚀2次结果图像和迭代腐蚀2次结果图像相同")
    else:
        print("腐蚀2次结果图像和迭代腐蚀2次结果图像不相同")

iterationsImgTest(r'F:\pic\pictures.png')
输出结果:
腐蚀1次结果图像和迭代腐蚀2次结果图像不相同
腐蚀2次结果图像和迭代腐蚀2次结果图像相同
结论:

iterations确实是针对每次腐蚀的结果再次进行腐蚀,直到执行腐蚀次数与iterations的实参相等。

七、小结

本文详细测试验证了OpenCV的腐蚀和膨胀erode、dilate函数在进行图像腐蚀和膨胀处理的一些细节,包括核矩阵的形状、核元素取值类型及值对腐蚀和膨胀的影响、图像矩阵是否支持彩色图片、bordType缺省值对应的边界类型分析以及迭代次数的作用,有助于大家深入理解OpenCV的腐蚀和膨胀erode、dilate函数的使用。

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

写作不易,敬请支持:

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

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

关于老猿的付费专栏

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

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

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

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

跟老猿学Python、学OpenCV!

☞ ░ 前往老猿Python博文目录 https://blog.youkuaiyun.com/LaoYuanPython ░
Python-Opencv中的膨胀和腐蚀 Python-Opencv中的膨胀和腐蚀 腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。 膨胀就是图像中的高亮部分进行膨胀,“邻域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中高亮部分被腐蚀,“邻域被蚕食”,效果图拥有比原图更小的高亮区域。 1.膨胀 膨胀过程是有一个结构元素或者模板去在原图像素比对,当比对过程中,中心像素位置的值根据其八邻域取或运算,或运算为1就取自己的中心值,... 阅读详情

相关推荐

opencv入门(四)

本文为OpenCV图像处理入门教程,主要介绍了形态学转换的基本概念和操作。文章详细阐述了图像腐蚀和膨胀的原理与应用,包括使用`cv2.erode()`和`cv2.dilate()`函数进行图像处理。同时,还介绍了开运算、闭运算、梯度运算、顶帽运算和底帽运算等高级形态学操作,并通过示例代码演示了如何使用`morphologyEx()`函数实现这些操作。

weixin_44063529的博客 1104

Python opencv膨胀函数cv2.dilate()

opencv可以利用cv2.dilate()函数对图片进行膨胀处处理。

RicardoHuang的博客 5万+

Python中的dilate函数解析

在这个例子中,我们首先使用cv2.imread函数读取了一张灰度图像。其中,src表示原始输入图像,kernel是要应用的膨胀核,dst是用于存储输出结果的可选参数,anchor是锚点的位置,iterations是膨胀迭代次数,borderType是像素外推方式,borderValue是超出边界的像素值。通过这个例子,我们可以看到dilate函数将输入图像中的边缘部分进行了膨胀操作,使得边缘变粗,并将孔洞填充。在图像处理中,膨胀(dilate)是一种常用的形态学操作,可以将图像中的物体边缘进行扩张。

学习使你进步。 1550

opencv之dilate()函数

概述 dilate()函数可以对输入图像用特定结构元素进行膨胀操作,该结构元素确定膨胀操作过程中的邻域的形状,各点像素值将被替换为对应邻域上的最大值: API说明 C++ API: void cv::dilate ( InputArray src, (原始图像:通道数不限,depth必须是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F) ...

duwangthefirst的博客 4万+

Python中的dilate函数详解

Python中的dilate函数详解dilate函数是图像处理领域中常用的一种操作,用于图像膨胀处理。它是一种形态学操作,可以扩大图像中的物体区域,使其变得更大或更宽。在本文中,我们将详细介绍Python中的dilate函数的使用方法和相关源代码。首先,我们需要导入必要的库: 然后,我们可以加载一张图像并将其转换为灰度图像: 接下来,我们需要创建一个膨胀核。膨胀核是一个定义了膨胀操作的结构元素,可以是矩形、椭圆或自定义形状。在这里,我们使用一个3x3的矩形膨胀核: 然后,我们可以使用dilate函数对图像进

2301_79366177的博客 348

Python图像处理: 实现腐蚀和膨胀(附完整源代码)

这里我们定义了一个5x5的矩形结构元素,将其作为参数传入cv2.erode()函数中,并设置迭代次数为1。腐蚀操作会将图像中的边缘缩小,达到去除不需要的区域的目的。同样地,我们定义了一个5x5的矩形结构元素,并将其作为参数传入cv2.dilate()函数中。最后,我们可以使用cv2.imshow()函数将处理后的图像显示出来,并使用cv2.waitKey()函数暂停程序,等待用户按下任意键退出。通过这段简单的代码,我们可以轻松地实现图像的腐蚀和膨胀操作,并在此基础上进行更复杂的图像处理任务。

qq_37934722的博客 961

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

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

老猿Python 1万+

python+Opencv学习教程01:图像腐蚀与膨胀操作

python opencv中的中文路径处理方法,以及腐蚀方法的使用

m1m2m3mmm的博客 5475

python学opencv|读取图像(六十一)先后使用cv2.dilate()函数和cv2.erode()函数实现图像处理

​ 使用python+opencv检验了对图像先后使用cv2.dilate()函数和cv2.erode()函数进行先膨胀后腐蚀操作的效果。 ​

专注python+工程实践的热心婶子 788

LTspice进阶技巧-031.一键加密仿真模型:LTspice Encrypt Tool实战指南

本文详细介绍了LTspice Encrypt Tool的使用方法,帮助工程师一键加密LTspice仿真模型,保护知识产权。通过图形化界面简化操作流程,支持批量加密和兼容性处理,适用于电路设计中的模型保护需求。

weixin_28304023的博客 202

跨境TRS投资操作指南与系统解决方案

3 点击【申请 TRS 账户】,查看风险披露,录入账户参数、确定录入的参数信息,进行身份验证,输入验证码,TRS 账户开户申请已提交,后台对已提交的 TRS 开户申请进行审核,审核成功后,短信邮箱提醒,进行登录;2.点击【申请TRS账户】,查看风险披露,录入账户参数、确定录入的参数信息,进行身份验证,输入验证码,TRS账户开户申请已提交,后台对已提交的TRS开户申请进行审核,审核成功后,短信邮箱提醒,进行登录;4)更广泛的投资选择:相比A股通,TRS可以交易更多的A股标的,提供了更广泛的投资选择。

2401_85487119的博客 2841

【opencv-python】形态学转换—腐蚀/膨胀

形态学操作主要包括腐蚀、膨胀、开运算、闭运算等,在opencv-python中,有相关函数可以满足要求,如cv2.erode(),cv2.dilate(),cv2.morphologyEx()等。形态学操作是根据图像形状进行的简单操作,一般情况下对二值化图像进行的操作。需要输入两个参数,一个是原始图像,第二个被称为结构化元素或核,它是用来决定操作的性质的。两个基本的形态学操作是腐蚀和膨胀,它们的变体构成了开运算、闭运算、梯度等,以下图为例逐一介绍。 首先对这张图进行腐蚀,代码如下: import cv2

hunter206的博客 489

峰值电流模式CCM BUCK的传递函数推导

电流内环闭环传递函数: Gci(s)=i^L(s)v^comp(s)=FmGid(s)1+KRiHe(s)FmGid(s)=1Ri11+s[mcL+(0.5VIN−Vo)RiVINRifSW]+s21(πfSW)2 G_{ci}(s)=\frac{\hat i_{L}(s)}{\hat v_{comp}(s)}=\frac {F_mG_{id}(s)}{1+KR_iH_e(s)F_mG_{id}(s)}=\frac{1}{R_i}\frac{1}{1+s[\frac{m_cL+(0.5V_{IN}-V_o)

c007106333的博客 2353

opencv膨胀腐蚀

腐蚀(Erosion):腐蚀操作与膨胀操作相反,它是将图像中的高亮区域(白色像素)缩小,从而消除小的高亮区域。在这个示例中,我们首先读取了一张图像,然后定义了一个 5x5 的结构元素(卷积核)。接下来,我们使用 `cv2.erode()` 和 `cv2.dilate()` 函数分别进行腐蚀和膨胀操作。膨胀(Dilation):膨胀操作是将图像中的高亮区域(白色像素)扩张,从而填充低亮区域(黑色像素)。OpenCV 是一个开源的计算机视觉库,它包含了许多图像处理的功能,其中膨胀和腐蚀是两种常用的形态学操作。

花生日记 2408

三维重建Fusion中的TSDF算法通俗描述

看个视频 https://www.youtube.com/watch?v=8M_-lSYqACo 这是mobilefusion的视频,大家先了解一下,看到在三维重建的时候外面有个长方体包围盒了吗? 数据准备: 我们不同角度拍摄的RGB图、深度图和相应的pose.txt。 步骤: 1.建立长方体包围盒 要建立一个长方体包围盒。让所有的三维点都在这个长方体里面。 假设z方向垂直相机。 很明显,x,y方...

qq_30339595的博客 1万+

Python 爬虫实战:医学临床指南爬取(含 PDF 解析与结构化存储)

在当今数字化时代,医学临床指南作为医生进行科学诊疗的重要参考资料,包含大量经过临床验证的诊疗路径和建议。这些指南通常发布在权威医学网站上,数量庞大且更新频繁。如何自动化地抓取并存储这些指南,成为医疗数据分析、医学研究以及医疗 AI 模型训练等工作的关键第一步。本文将系统讲解如何利用 Python 爬虫技术从权威医学网站爬取临床指南内容,并实现 PDF 解析与结构化存储。

u014481728的博客 449

opencv之膨胀、腐蚀

opencv之图像膨胀、腐蚀学习记录

chen_znn的博客 1403

基于STM32L4XX的环境光传感器(VCNL4040M3OE)应用程序设计

• 集成模块:红外发射器(IRED)、环境光传感器(ALS)、接近传感器(PS)及信号调理IC。#define VCNL4040_I2C_ADDR (0x60 << 1) // 7位地址左移一位。// 组合成16位值。// I2C总线句柄。// 设置参数:ALS集成时间160ms,中断禁止,ALS功能开启。// 设置参数:PS工作频率80Hz,开红外二极管,PS功能开启。// 初始化I2C外设。• 输出类型:I2C总线(ALS/PS)// 2. 配置环境光传感器 (ALS) 并启动。

myron6688的博客 143

python图像腐蚀处理_Python图像处理:图像腐蚀与图像膨胀

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

weixin_39955781的博客 337

YOLOv11知识蒸馏,实现无损涨点,包含逻辑蒸馏和特征蒸馏中的不同蒸馏方法,适用专栏内的所有模型

知识蒸馏(Knowledge Distillation)是由 Hinton 等人在 2015 年提出来的,主要是用一个复杂的教师模型去指导一个简单的学生模型训练,这样能让学生模型在保持高精度的同时,还能减少计算量。本文便是讲解如何针对的原始模型以及改进后的模型进行知识蒸馏,轻松实现无损涨点。知识蒸馏的核心在于利用已训练好的复杂模型(教师模型)去指导一个更简单的模型(学生模型)进行训练,以此让学生模型在保留较高精度的同时,降低计算成本。特征蒸馏(Feature Distillation)是知识蒸馏的一种形式,

Limiiiing的博客 4959

解决anaconda占用C盘空间过多问题

anaconda就算安装在其他盘,默认会把索引、锁定文件、压缩包等都放到系统盘(C盘),我用了两年,占用30GB。 1. 卸载不用的虚拟环境 查看已安装的虚拟环境 conda env list 卸载不用的、过期的虚拟环境 conda remove -n (要卸载的环境的名字) --all 2. 删除索引缓存、锁定文件、未使用过的包和tar包 conda clean -a 清理完之后,删除了15GB,还剩15GB,舒服了 ...

沉迷单车的追风少年 3万+

open cv学习 (九)腐蚀和膨胀

【代码】open cv学习 (九)腐蚀和膨胀。

Johnor的博客 272

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

opencv之图像分割

Opencv培养细胞图像分割

zhuguiqin1的专栏 1097

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Python----计算机视觉处理(Opencv:形态学变换)

形态学变换(Morphological Transformations)是一种基于形状的图像处理技术,主要处理的对象为二值化图像。形态学变换有两个输入和一个输出:输入为原始图像和核(即结构化元素),输出为经过形态学变换后的图像。其基本操作包括腐蚀(Erosion)和膨胀(Dilation),这两种操作互为反向过程,分别对图像中的亮度值产生不同的影响。

weixin_64110589的博客 1854

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

腐蚀/膨胀操作和开运算/闭运算(二值图像的缩小放大)

腐蚀/膨胀操作大多只用于二值图像,

weixin_54217245的博客 565

OpenCV轻松入门:面向Python【2.6】

本文介绍了OpenCV中的图像处理技术,主要包括自定义卷积和形态学操作两部分。在卷积部分,详细讲解了cv2.filter2D()函数的使用方法,通过自定义卷积核实现图像滤波,并提供了均值滤波的实现示例。在形态学操作部分,重点阐述了腐蚀和膨胀的原理及实现:腐蚀使用cv2.erode()函数缩小前景对象,膨胀使用cv2.dilate()函数扩大前景边界。通过多个示例展示了不同参数设置对处理效果的影响,包括核大小、迭代次数等,并比较了各种情况下的处理结果差异。这些基础操作是更复杂形态学运算(如开闭运算等)的基础,

qq_43416206的博客 1083
上一篇: OpenCV-Python图像处理:腐蚀和膨胀原理及erode、dilate函数介绍
下一篇: OpenCV-Python图像矩阵不扩充边界腐蚀膨胀函数处理算法探究
LaoYuanPython
LaoYuanPython 2020年博客之星Top3 2020年博客之星Top3 领域专家: Python技术领域 领域专家: Python技术领域
博客等级 码龄8年 15万+粉丝 1324原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

LaoYuanPython

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

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

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

打赏作者

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

抵扣说明:

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

余额充值