实现目标的一种简单方法是与正方形 3x3 内核卷积。对于每个像素,您现在知道其邻域(包括其自身)中有多少前景像素。将此阈值设置为 2 ( >= 2
) 以获得邻域中至少有 2 个前景像素的所有像素。最后,与原始图像的逻辑与将给出具有至少一个前景邻居的所有前景像素。
这是一个例子:
import scipy.ndimage
import numpy as np
img = np.array([[0., 0., 0., 0., 0., 0., 0., 1., 1., 1.],
[0., 1., 0., 0., 0., 0., 0., 1., 1., 1.],
[0., 0., 0., 0., 0., 0., 0., 0., 1., 1.],
[0., 0., 0., 0., 0., 0., 1., 0., 1., 1.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 1., 1., 0., 1., 0., 0., 0., 0., 0.],
[0., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 1., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 0., 0., 0., 1., 1., 0.],
[0., 0., 0., 0., 1., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.]], dtype=np.float32)
tmp = scipy.ndimage.convolve(img, np.ones((3,3)), mode='constant')
out = np.logical_and(tmp >= 2, img).astype(np.float32)
输出是:
[[0. 0. 0. 0. 0. 0. 0. 1. 1. 1.]
[0. 0. 0. 0. 0. 0. 0. 1. 1. 1.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 1.]
[0. 0. 0. 0. 0. 0. 1. 0. 1. 1.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 1. 1. 0.]
[0. 0. 0. 0. 1. 1. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
当然,一些图像库将具有专门为此目的设计的功能。不知道 OpenCV 或者 ndimage 或者 scikit-image 有没有这样的功能,我对这些库了解不够。但 DIPlib 确实(披露:我是作者):
import diplib as dip
out = img - dip.GetSinglePixels(img > 0)
该img > 0
部分是将浮点数组转换为逻辑数组,这是 DIPlib 期望的二进制图像。这大约是 512x512 图像的其他解决方案的 5 倍。