• Python-OpenCV——Morphological Transformations(形态学转换)


    目标

    这一节

    • 我们将学习不同的形态学操作,如腐蚀、膨胀、开、闭......
    • 我们将看到不同的函数,如:cv2.erode()、cv2.dilate()、cv2.morphology()

    理论

          形态变换是基于图像形状的一些简单操作。它通常在二进制图像上执行。它需要两个输入,一个是我们的原始图像,第二个是称为结构元素或内核,它决定了操作的本质。两个基本的形态学运算符是侵蚀和膨胀。然后它的变体形式如Opening,Closing,Gradient等也发挥作用。我们将在以下图片的帮助下逐一看到它们:

    1、腐蚀(Erosion)

          腐蚀的基本思想就像土壤侵蚀一样,它会侵蚀前景物体的边界(总是试图保持前景为白色)。那它是做什么的?内核在图像中滑动(如在2D卷积中)。只有当内核下的所有像素都是1时,原始图像中的像素(1或0)才会被视为1,否则它将被侵蚀(变为零)

          所以发生的事情是,边界附近的所有像素都将被丢弃,具体取决于内核的大小。因此,前景对象的厚度或大小减小,或者图像中的白色区域减小。它有助于消除小的白噪声(正如我们在色彩空间章节中看到的那样),分离两个连接的对象等。

    在这里,作为一个例子,我将使用一个全1的5x5内核,其中包含完整的内核。让我们看看它是如何工作的:

    import cv2
    import numpy as np
    
    img = cv2.imread('j.png',0)
    kernel = np.ones((5,5),np.uint8)
    erosion = cv2.erode(img,kernel,iterations = 1)

    结果:

    2、膨胀(Dilation)

          它恰好与腐蚀相反。这里,如果内核下的至少一个像素为“1”,则像素元素为“1”。因此它增加了图像中的白色区域或前景对象的大小增加。通常,在去除噪音的情况下,腐蚀之后再膨胀。因为,腐蚀会消除白噪声,但它也会缩小我们的物体,所以我们需要再扩大它。由于噪音消失了,它们不会再回来,但我们的物体区域会增加。它也可用于连接对象的破碎部分。

    dilation = cv2.dilate(img,kernel,iterations = 1)

    结果:

     3、开运算(Opening)

    开运算是腐蚀再膨胀的另一种说法。如上所述,它有助于消除噪音。这里我们使用函数cv2.morphologyEx().

    opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

    结果:

    4. 闭运算(Closing)

    开运算与闭运算,腐蚀和膨胀是相反的。闭运算就是先膨胀再腐蚀,它可用于关闭前景对象内的小孔或对象上的小黑点。

    closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

    结果:

     我们可以通过以下代码观察之间的关系:

    import cv2
    import numpy as np
    
    img = cv2.imread('./Pictures/j.png',0)
    kernel = np.ones((5,5),np.uint8)
    erosion = cv2.erode(img,kernel,iterations = 1)
    
    img2 = ~img
    dilation = cv2.dilate(img2,kernel,iterations = 1)
    dilation = ~dilation
    
    htich = np.hstack((img, erosion, dilation))
    cv2.imshow("erosion", htich)
    cv2.waitKey(0)

    结果:

    可见,img开运算等同于反转图闭运算再反转。

    5、形态梯度(Morphological Gradient)

    它是一张图像膨胀和腐蚀之间的差异,结果看起来像对象的轮廓。

    gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

    结果:

    其效果等同于膨胀减去腐蚀

    import cv2
    import numpy as np
    
    img = cv2.imread('./Pictures/j.png',0)
    kernel = np.ones((5,5),np.uint8)
    erosion = cv2.erode(img,kernel,iterations = 1)
    dilation = cv2.dilate(img,kernel,iterations = 1)
    diff = dilation - erosion
    
    gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
    
    
    htich = np.hstack((img, gradient, diff))
    cv2.imwrite("./Pictures/i.png", htich)
    cv2.imshow("erosion", htich)
    cv2.waitKey(0)

    效果:

    6、高帽变换(Top Hat/White Top-Hot)

    它是输入图像和图像开运算之间的区别。下面的示例是针对9x9内核完成的。 

    tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)

    结果:

    其等同于膨胀后减去原图,例如,该图在使用2x2内核时,两者效果比较接近。

    import cv2
    import numpy as np
    
    img = cv2.imread('./Pictures/j.png',0)
    kernel = np.ones((2,2),np.uint8)
    erosion = cv2.erode(img,kernel,iterations = 1)
    dilation = cv2.dilate(img,kernel,iterations = 1)
    diff = img - dilation
    diff2 = dilation - img
    
    tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
    
    
    htich = np.hstack((img, tophat, diff2))
    cv2.imwrite("./Pictures/i.png", htich)
    cv2.imshow("erosion", htich)
    cv2.waitKey(0)

    结果:

     7、黑帽变换(Black Hat/Black Top-Hot)

    它是闭运算与输入图像的差异。

    blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

    结果:

     其等同于原图减去闭运算,显然这两个都能用来提取轮廓,有什么区别呢?WTH能使较暗背景中较亮的像素聚集,BTH能使较亮背景中较暗像素的聚集。前者使“峰”更尖,后者使“谷”更深。两者结合$THE(f)=f+WTH(f,b)-BTH(f,b)$,对比更加明显。

    结构元素(Structuring Element)

    我们在Numpy的帮助下手动创建了前面示例中的结构元素。它是矩形。但在某些情况下,您可能需要椭圆/圆形内核。因此,为此,OpenCV有一个函数cv2.getStructuringElement()。您只需传递内核的形状和大小,即可获得所需的内核。

    # Rectangular Kernel
    >>> cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
    array([[1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1]], dtype=uint8)
    
    # Elliptical Kernel
    >>> cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
    array([[0, 0, 1, 0, 0],
           [1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1],
           [1, 1, 1, 1, 1],
           [0, 0, 1, 0, 0]], dtype=uint8)
    
    # Cross-shaped Kernel
    >>> cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
    array([[0, 0, 1, 0, 0],
           [0, 0, 1, 0, 0],
           [1, 1, 1, 1, 1],
           [0, 0, 1, 0, 0],
           [0, 0, 1, 0, 0]], dtype=uint8)

    参考链接:OpenCV-Python Tutorials https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html#dilation

  • 相关阅读:
    APUE.3源码编译(Ubuntu16.04)
    《UNIX环境高级编程》(第三版)阅读笔记---2018-5-9
    css回归之用户界面
    css回归之文本
    js回归之字符串
    js回归之BOM
    js回归之事件
    百度前端面试总结
    书单
    剑指offer做题收获之一:补码
  • 原文地址:https://www.cnblogs.com/lfri/p/10620778.html
Copyright © 2020-2023  润新知