目标
- 我们将学习不同的形态学操作,如腐蚀、膨胀、开运算、闭运算等。
- 我们将看到不同的函数,如:cv.erode()、cv.dilate()、cv.morphologyEx() 等。
理论知识
形态变换是一些基于图像形状的简单操作。它通常在二进制图像上执行。它需要两个输入,一个是我们的原始图像,第二个称为结构元素或内核,它决定了操作的性质。两个基本的形态学算子是侵蚀和膨胀。然后它的变体形式如开、闭、梯度等也开始发挥作用。我们将在下图的帮助下一一看到它们:
腐蚀
侵蚀的基本思想就像土壤侵蚀一样,它侵蚀掉前景物体的边界(总是尽量让前景保持白色)。那它有什么作用呢?内核在图像中滑动(如在 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)
结果如下:
膨胀
它与侵蚀正好相反。这里,如果内核下的至少一个像素为“1”,则像素元素为“1”。因此它增加了图像中的白色区域或前景对象的大小增加。通常,在去除噪声等情况下,腐蚀之后是膨胀。因为,腐蚀去除了白噪声,但它也缩小了我们的对象。所以我们扩大它。由于噪音消失了,它们不会回来,但我们的对象区域增加了。它还可用于连接对象的损坏部分。
dilation = cv.dilate(img,kernel,iterations = 1)
开运算
开运算只是先腐蚀后膨胀的别名。正如我们上面所解释的,它在去除噪声方面很有用。这里我们使用函数 cv.morphologyEx()
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)
闭运算
闭运算与开运算相反,先膨胀后腐蚀。它对于关闭前景对象内的小孔或对象上的小黑点很有用。
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)
形态梯度
这是图像膨胀和腐蚀之间的区别。结果将看起来像对象的轮廓。
gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)
顶帽运算(Top Hat)
这是输入图像和图像的Opening之间的区别。顶帽运算就是将原图减去开运算后的图像,放大了裂痕或局部低亮度区域,下面的示例是针对 9x9 内核完成的。
tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)
黑帽运算(Black Hat)
它是输入图像和输入图像的闭运算之间的差异。与顶帽运算相反。
blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)
内核创造函数
在 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)