我设法通过使用 midtiby 建议的命中和未命中转换来解决这个问题。我使用以下内核来检测顶部、右侧、底部和左侧的单像素。
-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 1 1 1 -1 -1 -1 -1 -1 -1 -1 1
其中-1 表示背景,1 表示前景,0 表示无关(在本例中未使用)。
四次命中和未命中变换的结果将用作掩码以去除单个像素。以下是 Python/OpenCV 中的完整代码:
import numpy as np
import cv2
def hitmiss(src, kernel):
im = src / 255
k1 = (kernel == 1).astype('uint8')
k2 = (kernel == -1).astype('uint8')
e1 = cv2.erode(im, k1, borderType=cv2.BORDER_CONSTANT)
e2 = cv2.erode(1-im, k2, borderType=cv2.BORDER_CONSTANT)
return e1 & e2
if __name__ == "__main__":
im = cv2.imread('blobs.png', cv2.CV_LOAD_IMAGE_GRAYSCALE)
_, im_binary = cv2.threshold(im, 50, 255, cv2.THRESH_BINARY)
kernel = np.array([[-1,-1, 1],
[-1, 1, 1],
[-1,-1, 1]])
im_mask = np.zeros(im_binary.shape, np.uint8)
im_mask |= hitmiss(im_binary, kernel)
im_mask |= hitmiss(im_binary, np.fliplr(kernel))
im_mask |= hitmiss(im_binary, kernel.T)
im_mask |= hitmiss(im_binary, np.flipud(kernel.T))
im_dst = im_binary & ((1 - im_mask) * 255)
cv2.imwrite('dst.png', im_dst)
给定这个输入图像:
脚本将产生以下输出: