【问题标题】:Erode x pixels from side of mask with hole in OpenCV在 OpenCV 中从带有孔的掩码侧面侵蚀 x 像素
【发布时间】:2021-09-15 08:29:34
【问题描述】:

我有一个面具,里面可能有洞。我想从遮罩的外部(而不是孔)横向侵蚀一定数量的像素。

诀窍是,如果我向内侵蚀 5px 并且在某个点有一个距离边缘 3px 的孔,我想侵蚀这 3px,然后将剩余的 2px 侵蚀到孔之外。所以我总是每边侵蚀 5px,基本上跳过了任何漏洞。

例如使用这个掩码:

这些灰色区域将被侵蚀:

我可以通过遍历每一行来了解如何做到这一点,例如:

erode_px = 5
for y, row in enumerate(mask):
    idxs = np.nonzero(row)[0]
    if idxs.size:
        if idxs.size < erode_px * 2:
            mask[y] = 0
        else:
            mask[y, :idxs[erode_px]] = 0
            mask[y, idxs[-erode_px]:] = 0

但我正在处理非常大的面具,这需要高效。有没有办法在不遍历 Python 中的每一行的情况下实现这一点?最好只使用 OpenCV / numpy。

【问题讨论】:

  • 您可以在 C++ 中实现它,将其添加到 openCV 源代码中并在 Python 中使用包装器。
  • 也许有一个复杂的算法,有两个或三个单独的距离变换等。不确定。
  • 整合图像可能有用。

标签: python numpy opencv image-processing


【解决方案1】:

您可以使用累积和完成您想要的:

  1. 沿水平线计算累积和。
  2. 在所需距离处的阈值累积和n
  3. 与输入逻辑与。

这将取消设置每条线上的第一个n 设置像素。要从右边缘应用操作,翻转矩阵,应用上面的操作,然后翻转结果。

以下代码演示了操作:

import numpy as np
import matplotlib.pyplot as plt

def erode_left(mask, n):
   return np.logical_and(np.cumsum(mask, axis=1) > n, mask)

def erode_both(mask, n):
   mask = erode_left(mask, n)
   mask = np.fliplr(erode_left(np.fliplr(mask), n))
   return mask
   

mask = np.array([[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
                 [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
                 [0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
                 [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,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]], dtype=bool)

f, axarr = plt.subplots(2,2)
axarr[0,0].imshow(mask)
axarr[0,0].title.set_text('Input')
axarr[0,1].imshow(erode_left(mask, 5))
axarr[0,1].title.set_text('Eroded left side')
axarr[1,0].imshow(erode_both(mask,5))
axarr[1,0].title.set_text('Eroded both sides')
axarr[1,1].imshow(erode_both(mask,5) + 2*mask)
axarr[1,1].title.set_text('Overlay')
plt.show()

【讨论】:

    【解决方案2】:

    我必须承认,这不是最好的解决方案,我不确定它是否符合您的意图,但这是您描述的一种方法:

    import numpy as np
    from skimage.morphology import closing, erosion
    from matplotlib import pyplot as plt
    
    np.random.seed(0)
    idxs = np.random.randint(0, 15 ,(2, 30))
    
    mask = np.ones((15, 15))
    mask[:2] = 0
    mask[-2:] = 0
    mask[:, :2] = 0
    mask[:, -2:] = 0
    mask[idxs[0], idxs[1]] = 0
    
    mask_cls = closing(mask, selem = np.ones((2, 2)))
    
    mask_erd = erosion(mask_cls, selem = np.ones((3, 3)))
    
    mask_erd_out = mask*mask_erd
    

    输出:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      相关资源
      最近更新 更多