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,1,1]],dtype=np.uint8)


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


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

更严格的实现是通过惩罚零、剪裁到 {0,1} 并确保没有从原始图像中删除任何内容来进行精确模式匹配:

kernel = np.array([[0.5,-10.0,-10.0],[-10.0,0.5]])

connected_img = np.maximum(img,np.clip(cv2.filter2D(img,1))