numpy 平滑速度更快的等效函数

f0brbegy  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(107)

我写了一个函数,可以移除二进制掩码中的单个突出像素:


的数据

def remove_dots(mask, mode='constant', cval=0):
    patterns = [
        np.array([[1, 0, 0],
                  [1, 1, 0],
                  [1, 0, 0]]),
       
        np.array([[0, 0, 1],
                  [0, 1, 1],
                  [0, 0, 1]]),
        
        np.array([[1, 1, 1],
                  [0, 1, 0],
                  [0, 0, 0]]),
        
        np.array([[0, 0, 0],
                  [0, 1, 0],
                  [1, 1, 1]])
    ]
    
    punches = [
        np.array([[1, 0, 0],
                  [1, 0, 0],
                  [1, 0, 0]]),
        
        np.array([[0, 0, 1],
                  [0, 0, 1],
                  [0, 0, 1]]),
        
        np.array([[1, 1, 1],
                  [0, 0, 0],
                  [0, 0, 0]]),
        
        np.array([[0, 0, 0],
                  [0, 0, 0],
                  [1, 1, 1]])
    ]
    
    for y in range(mask.shape[1]-2):
        for x in range(mask.shape[0]-2):
            for i, a in enumerate(patterns):
                if np.array_equal(mask[x:x+a.shape[0], y:y+a.shape[1]], a):
                    mask[x:x+a.shape[0], y:y+a.shape[1]] = punches[i]

    return mask

字符串
一个明显的问题是该函数的数组比较速度很慢。你知道一个功能,做完全相同的事情,但明显更快?

nbnkbykc

nbnkbykc1#

我可能会建议使用四个3x3匹配过滤器,并根据您的形状定制内核。像scipy.signal.convolve2d这样的东西应该完全适合您的需要。在一般情况下,替换是不平凡的,但您可以使用这样一个事实,即您只替换输出中的单个中心像素。

from scipy.signal import convolve2d

for p in patterns:
    # Use defaults mode='full', boundary='fill', fillvalue=0
    mask = (convolve2d(image, 2 * p - 1) == p.sum(None))
    image[mask] = 0

字符串
在卷积中执行2 * p - 1而不仅仅是p的原因是您希望区分实际的冲孔和实心区域。如果您的模式是0和1,则以下两个芯片返回相同的输出:

0 0 1   0 0 1              1 1 1   0 0 1
0 1 1 , 0 1 1 -> 4   and   1 1 1 , 0 1 1 -> 4
0 0 1   0 0 1              1 1 1   0 0 1


但是如果你惩罚无效的条目,你会得到正确的结果:

0 0 1   -1 -1  1              1 1 1   -1 -1  1
0 1 1 , -1  1  1 -> 4   and   1 1 1 , -1  1  1 -> -1
0 0 1   -1 -1  1              1 1 1   -1 -1  1

相关问题