如何从 opencv morphologyEx 获得关于图像边界的预期行为?

How to get expected behavior from opencv's morhpologyEx with regard to image boundaries?

我正在使用 opencv(版本 4.1.0,Python 3.7)对二进制图像执行形态学闭合。我在使用大闭合内核时遇到边界问题。

我的代码是:

close_size = 20
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (close_size, close_size))
result = cv2.morphologyEx(im, cv2.MORPH_CLOSE, kernel)

我读了 and , and also the the docs,这让我也尝试改变 borderValue morphologyEx() 中的参数像这样

result = cv2.morphologyEx(im, cv2.MORPH_CLOSE, kernel,borderValue=[cv2.BORDER_CONSTANT,0])

但这两种方法都没有达到我想要的效果。我在下图中总结了他们的行为。

我的原图在上面。我期望的行为是两个点对于小内核(例如,内核 = 1)保持分开,并合并在一起以获得足够大的内核。
正如你所看到的,对于默认边框(图像的左列),当kernel = 6时合并是正确的,但是一旦变大,点就开始与边界合并。
对于恒定边界(图像的右列),可以使用更大的内核,但是对于真正更大的内核(例如内核 = 20),仍然会出现意想不到的行为,其中点消失了。

关闭内核在最终软件中作为参数留给用户,以便能够合并非常远的点。所以理想情况下,我需要能够平滑地处理比对象和边界之间的距离更大的内核。

原图:

此答案解释了如何通过向图像添加缓冲区来在图像边缘周围使用 MORPH_CLOSE

您可以使用 numpy 创建零图像来添加缓冲区:

# Import packages
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Read in the image
img = cv2.imread('/home/stephen/Desktop/OKoUh.png', 0)
# Create a black bufffer around the image
h,w = img.shape
buffer = max(h,w)
bg = np.zeros((h+buffer*2, w+buffer*2), np.uint8)
bg[buffer:buffer+h, buffer:buffer+w] = img

然后你可以迭代并检查它在不同内核大小下的表现:

for close_size in range(1,11):
    temp  = bg.copy()
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (close_size, close_size))
    result = cv2.morphologyEx(temp, cv2.MORPH_CLOSE, kernel)
    results = result[buffer:buffer+h, buffer:buffer+w]
    cv2.imshow('img', result)
    cv2.waitKey()

我的结果:

根据 Stephen 的回答,这是我最终实现的代码片段:

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (close_size, close_size))
# Padding
im=cv2.copyMakeBorder(im,close_size,close_size,close_size,close_size,
                      borderType=cv2.BORDER_CONSTANT, value = 0)
# Closing
im = cv2.morphologyEx(im, cv2.MORPH_CLOSE, kernel)
# Unpadding
im = im[close_size:-close_size,close_size:-close_size]

正如我在评论中提到的,对于大内核大小,这可能会导致更长的计算时间。填充较低的值,例如 close_size/2 可能足以防止边界问题(未测试)。