形态学运算 (OpenCV) 中的迭代与内核大小

Iterations vs. Kernel Size in Morphological Operations (OpenCV)

我一直在 OpenCV 中使用 morph opening 来通过 opencv 减少图像中 ROI 之外的噪声,直到现在,每当我需要更高程度的降噪时,我只是随机增加内核大小或增加迭代次数,直到我满意为止。结果是否有显着差异,具体取决于您增加了哪些/您将如何决定在给定情况下更改哪些?除了猜测和检查之外,我正在尝试想出一种更好的方法来更改(更改多少)参数。

这取决于内核类型。对于奇方核的扩张或侵蚀,无论是增加大小还是增加迭代次数都没有区别(假设使用的值会使它们相等)。例如:

>>> M = np.zeros((7,7), dtype=np.uint8)
>>> M[3,3] = 1

>>> k1 = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
>>> M1 = cv2.dilate(M, k1, iterations=2)

>>> k2 = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
>>> M2 = cv2.dilate(M, k2, iterations=1)

>>> M1
[[0 0 0 0 0 0 0]
 [0 1 1 1 1 1 0]
 [0 1 1 1 1 1 0]
 [0 1 1 1 1 1 0]
 [0 1 1 1 1 1 0]
 [0 1 1 1 1 1 0]
 [0 0 0 0 0 0 0]]

>>> M2
[[0 0 0 0 0 0 0]
 [0 1 1 1 1 1 0]
 [0 1 1 1 1 1 0]
 [0 1 1 1 1 1 0]
 [0 1 1 1 1 1 0]
 [0 1 1 1 1 1 0]
 [0 0 0 0 0 0 0]]

这是相当直观的。用于膨胀的 3x3 矩形内核将找到任何白色像素,并将相邻像素变为白色。所以很容易看出,这样做两次会使任何一个白色像素变成一个 5x5 的白色像素块。这里我们假设中心像素是被比较的像素——anchor——但这可以改变,这可能会影响结果。例如,假设您正在比较 (2, 2) 内核的两次迭代与 (3, 3) 内核的一次迭代:

>>> M = np.zeros((5, 5), dtype=np.uint8)
>>> M[2,2] = 1

>>> k1 = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
>>> M1 = cv2.dilate(M, k1, iterations=2)

>>> k2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
>>> M2 = cv2.dilate(M, k2, iterations=1)

>>> M1
[[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 1 1 1]
 [0 0 1 1 1]
 [0 0 1 1 1]]

>>> M2
[[0 0 0 0 0]
 [0 1 1 1 0]
 [0 1 1 1 0]
 [0 1 1 1 0]
 [0 0 0 0 0]]

您可以看到,虽然它创建了形状(直观),但它们不在同一个地方(不直观)。那是因为 (2, 2) 内核的锚点不能位于内核的中心——在这种情况下,我们看到对于居中像素,膨胀的邻居仅在右下角,因为它有选择一个方向,因为它只能扩展单个像素来填满一个 (2, 2) 正方形。

对于非矩形内核,事情变得更加棘手。例如:

>>> M = np.zeros((5, 5), dtype=np.uint8)
>>> M[2,2] = 1

>>> k1 = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
>>> M1 = cv2.dilate(M, k1, iterations=2)

>>> k2 = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
>>> M2 = cv2.dilate(M, k2, iterations=1)

>>> M1
[[0 0 1 0 0]
 [0 1 1 1 0]
 [1 1 1 1 1]
 [0 1 1 1 0]
 [0 0 1 0 0]]

>>> M2
[[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]]

M1 的第一遍创建了一个高 3 像素、宽 3 像素的小十字。但是随后这些像素中的每一个都在其位置创建了一个十字,这实际上创建了一个菱形图案。

所以总结一下基本的形态学操作,用矩形核,至少是奇数维的,结果是一样的---但是对于其他核,结果是不同的。您可以将其他形态学操作应用于像这样的简单示例,以了解它们的行为方式、您应该使用哪些以及如何增强它们的效果。