OpenCV -如何通过二进制图像的模式匹配内核?



我正在实现二值图像中像素级宽轮廓的轮廓查找算法。它需要对单个像素的删除(即像素宽的间隙)具有鲁棒性。

膨胀的各种尝试&侵蚀核还没有产生可靠的解决方案。

相反,我想实现的可靠解决方案是在图像上传递一个模式匹配内核,它可以直接根据周围的像素填充空白。例如,当在某个位置观察到左侧的确切模式时,将其替换为右侧的模式(其中*表示通配符):

[1 * *]          [1 * *]
[* 0 *]   ==>    [* 1 *]
[* * 1]          [* * 1]
[1 0 *]          [1 0 *]
[* 0 1]   ==>    [* 1 1]
[* * *]          [* * *]
[* 1 *]          [* 1 *]
[* 0 *]   ==>    [* 1 *]
[* 1 *]          [* 1 *]

并定义约14个必要的替换来填充每个3x3窗口的可能空隙。

它可以在原始Python中实现,但如果没有低级向量化操作,可能会非常慢。

这可以通过OpenCV或其他一些快速操作完成吗?

感谢@beaker上面的评论,我实现了一个解决方案。设计一个内核,其中感兴趣的相邻像素为0.5,中心为1,如果中心缺失,它将用1填充,尽管其他一些像素将为2。然后将值裁剪为1,您将得到所需的结果。

它需要独立应用于每个方向的间隙,这不是理想的,但仍然有效。

img_with_gap = np.array(
[[1,0,0,0,0],
[0,1,0,0,0],
[0,0,0,0,0],
[0,0,0,1,0],
[0,0,0,0,1]], dtype=np.uint8)

kernel = np.array(
[[0.5,  0,   0],
[0  ,  1,   0],
[0  ,  0, 0.5]])

connected_img = np.minimum(cv2.filter2D(img_with_gap, -1, kernel), 1)
connected_img

一个更严格的实现是做一个精确的模式匹配,惩罚0个1,裁剪到{0,1},并确保没有从原始图像中删除:

kernel = np.array([[0.5,  -10.0,   -10.0],
[-10.0  ,  1,   -10.0],
[-10.0  ,  -10.0, 0.5]])
connected_img = np.maximum(img, np.clip(cv2.filter2D(img, -1, kernel), 0, 1))