在python数组中查找并替换子数组

时间:2018-07-02 15:30:12

标签: python arrays numpy replace noise-reduction

我有一个6600X5100 numpy数组,它代表黑白图像。 我想从黑色像素噪声中清除此图像-删除所有短于2个像素的黑色像素线(垂直和水平)。

所以,如果我有这样的东西:

[0,  0,  0,   0,   0, 255]
[0, 255,255, 255, 255, 0 ]
[0, 255,255, 255,  0,  0 ]
[0, 255,255 ,255,  0, 255]
[0, 255,255, 255,  0, 255]
[0,  0,  0,   0,   0,  0 ]

输出数组将如下所示:

[0,  0,  0,   0,   0,  0 ]
[0, 255,255, 255,  0 , 0 ]
[0, 255,255, 255,  0,  0 ]
[0, 255,255 ,255,  0,  0 ]
[0, 255,255, 255,  0,  0 ]
[0,  0,  0,   0,   0,  0 ]

此处的性能至关重要,因此无法在数组上进行简单循环。 有没有一种方法可以快速找到并替换数组中的子数组? 因此,如果[0,255,255,0]或[0,255,0]位于图像数组中,则将这些部分替换为0。

或者如果您对此任务有更好的解决方案,我将不胜感激。

2 个答案:

答案 0 :(得分:4)

您可能想看看scikit-image的形态过滤器。

您可以定义简单的过滤器,并使用opening函数清理图像。您必须使用过滤器才能完全根据需要获得它们,但是该库非常快。

import numpy as np
from skimage.morphology import opening

img = np.array([[0,  0,  0,   0,   0, 255],
                [0, 255,255, 255, 255, 0 ],
                [0, 255,255, 255,  0,  0 ],
                [0, 255,255 ,255,  0, 255],
                [0, 255,255, 255,  0, 255],
                [0,  0,  0,   0,   0,  0 ]])


# horizontal and vertical filters
hf = np.array([[0,0,0,0,0],
               [0,1,1,1,0],
               [0,0,0,0,0]])
vf = hf.T

# apply each filter in turn
out = opening(opening(img, hf),vf)

out
# returns:
array([[  0,   0,   0,   0,   0,   0],
       [  0, 255, 255, 255,   0,   0],
       [  0, 255, 255, 255,   0,   0],
       [  0, 255, 255, 255,   0,   0],
       [  0, 255, 255, 255,   0,   0],
       [  0,   0,   0,   0,   0,   0]])

答案 1 :(得分:2)

我的解决方案与现有解决方案相似,但是我使用2d卷积:

import numpy as np
from scipy.signal import convolve2d as conv2

in_arr = np.array([
    [0,  0,  0,   0,   0, 255],
    [0, 255,255, 255, 255, 0 ],
    [0, 255,255, 255,  0,  0 ],
    [0, 255,255 ,255,  0, 255],
    [0, 255,255, 255,  0, 255],
    [0,  0,  0,   0,   0,  0 ]])

padded = np.pad(in_arr, 1, mode='constant', constant_values=0)

# Create a kernel
kern = np.ones((1, 3))

# Perform convolution
mask = np.logical_and((conv2(in_arr, kern,   mode='same') // 255) >= 2,
                      (conv2(in_arr, kern.T, mode='same') // 255) >= 2)

# Apply mask:
out_arr = in_arr * mask

这也会产生预期的结果。