形态学运算 (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 像素的小十字。但是随后这些像素中的每一个都在其位置创建了一个十字,这实际上创建了一个菱形图案。
所以总结一下基本的形态学操作,用矩形核,至少是奇数维的,结果是一样的---但是对于其他核,结果是不同的。您可以将其他形态学操作应用于像这样的简单示例,以了解它们的行为方式、您应该使用哪些以及如何增强它们的效果。
我一直在 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 像素的小十字。但是随后这些像素中的每一个都在其位置创建了一个十字,这实际上创建了一个菱形图案。
所以总结一下基本的形态学操作,用矩形核,至少是奇数维的,结果是一样的---但是对于其他核,结果是不同的。您可以将其他形态学操作应用于像这样的简单示例,以了解它们的行为方式、您应该使用哪些以及如何增强它们的效果。