python - 在 OpenCV 中从带有孔的掩模侧面腐 eclipse x 像素

标签 python numpy opencv image-processing

我有一个口罩,里面可能有洞。我想从蒙版的外部(而不是孔)水平方向侵 eclipse 一定数量的像素。

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

例如使用这个掩码:

Original mask

这些灰色区域将被侵 eclipse :

result

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

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。

最佳答案

您可以使用累积总和来完成您想要的事情:

  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()

output of code above

关于python - 在 OpenCV 中从带有孔的掩模侧面腐 eclipse x 像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68241209/

相关文章:

Pythonic 方式来遍历阴影等

python - 在 pyspark 中将行转置为列

python - 如何标记CNN的训练数据?

android - 错误 : Cause: compileSdkVersion is not specified

python-3.x - OpenCV Python Numpy : ValueError: too many values to unpack (expected 2)

python - 了解cvFilter2d的输出

python - 使用生成器时访问连续的项目

python - 复制二维 numpy 数组中的边界

python - 检查 numpy 数组是否按字典顺序排序

Python - Matplotlib/matplotlib.cbook.TimeoutError : LOCKERROR