首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在OpenCV中用孔腐蚀掩模侧面的x像素

在OpenCV中用孔腐蚀掩模侧面的x像素
EN

Stack Overflow用户
提问于 2021-07-04 02:25:47
回答 2查看 398关注 0票数 2

我有个面具里面可能有洞。我想从面具的外部侵蚀(所以不是洞),水平的,一定数量的像素。

诀窍是,如果我向内侵蚀5px,在某一点上,从边缘有一个3px洞,我想要腐蚀这3px,然后剩下的2px通过洞。因此,我总是侵蚀每一侧5便士,实质上是跳过任何洞。

例如,使用此掩码:

这些灰色地带将被侵蚀:

我可以看到如何通过遍历每一行来实现这一点,如下所示:

代码语言:javascript
复制
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。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-07-04 13:46:12

您可以使用累积和完成所需的任务:

计算沿水平lines.

  • Threshold累积和在您期望的距离n.

  • Logical和输入的

这将取消沿每条线设置的第一个n集像素。若要从右侧边缘应用该操作,请翻转矩阵,应用上面的操作,并翻转结果。

以下代码演示了该操作:

代码语言:javascript
复制
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()

票数 3
EN

Stack Overflow用户

发布于 2021-07-04 07:08:35

我必须承认,这不是最好的解决方案,我也不确定它能实现你想要做的事情,但有一种方法可以像你所说的那样:

代码语言:javascript
复制
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

输出:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68241209

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档