【翻译:OpenCV-Python教程】形态变化

⚠️这个系列是自己瞎翻的,文法很丑,主要靠意会,跳着跳着捡重要的部分翻,翻错了不负责,就这样哈。

⚠️基于3.4.3,Morphological Transformations,原文

目标

在这一章节,

理论

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

j.png

1、侵蚀

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

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

这里,作为一个例子,我用一个完整的 5x5 内核。让我们看看它是如何工作的:

import cv2 as cv

import numpy as np

img = cv.imread('j.png',0)

kernel = np.ones((5,5),np.uint8)

erosion = cv.erode(img,kernel,iterations = 1)

结果:

erosion.png

2、 膨胀

它刚好于侵蚀相反。这里,如果内核下至少有一个像素元素是 '1' ,那我们就认为这个像素点为 '1' 。因此它令到图像上的白色区域或者前景的大小增加了。通常,在如去除噪声这样的情景下,侵蚀之后要用一次膨胀算法。因为,侵蚀虽然能去掉白噪声,但也会让我们的物体缩小。因此我们要(用膨胀算法把它再展开)。自从噪声(从侵蚀算法中)消失之后,它们就不会再(因为膨胀算法而)出现了。但我们的物体区域会增加,它也有助于连接物体的破碎部分。

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

结果:

dilation.png

3、开放

开放就是腐蚀之后接膨胀的另一种叫法。它有助于消除噪声,就像我们在上面解释的那样,这里我们使用 cv.morphologyEx() 方法。

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

结果:

opening.png

4、闭合

闭合与开放相反,膨胀之后接侵蚀。它有助于关闭掉前景对象上的小洞,或者对象上的小黑点。

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

结果:

closing.png

5、梯度

梯度是一张图像膨胀和侵蚀的差。

这个结果看起来像是物体的外边线。

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

结果:

gradient.png

6、顶帽运算

它是原图与运行过开放算法的原图之差,以下是示例是按一个9x9内核来进行的运算。

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

结果:

tophat.png

7、黑帽运算

它是原图经过闭合运算之后的结果与原图之差。

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

结果:

blackhat.png

结构化元素

在之前的示例中,我们在Numpy的帮助下手动创建了一个结构化的元素。它是长方形的,但在某些情况下,你可能需要圆形或者椭圆形的内核。所以为了达到这个目的,OpenCV 有个方法,cv.getStructuringElement() 。你只需要传入内核的形状以及大小,你就能得到你需要的内核。
 

# Rectangular Kernel
>>> cv.getStructuringElement(cv.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
>>> cv.getStructuringElement(cv.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
>>> cv.getStructuringElement(cv.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教程】图像平滑

下篇:【翻译:OpenCV-Python教程】图像梯度

猜你喜欢

转载自blog.csdn.net/ssybc/article/details/84453508