Найти и заменить подмассив в массиве python

У меня есть массив 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.

Или если у вас есть лучшее решение для этой задачи, буду признателен.


person Phoenix    schedule 02.07.2018    source источник
comment
Использует scikit или scipy приемлемы?   -  person Dev-iL    schedule 02.07.2018
comment
scikit в порядке   -  person Phoenix    schedule 02.07.2018
comment
Возможный дубликат Поиск последовательности в массиве NumPy   -  person RedEyed    schedule 02.07.2018


Ответы (2)


Вы можете посмотреть на морфологические фильтры 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]])
person James    schedule 02.07.2018
comment
Спасибо. Я использовал его с «закрытием» вместо «открытия», поскольку 255 представляет белый цвет на моем изображении. - person Phoenix; 03.07.2018

Мое решение похоже на существующее, но я использую 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

Что также дает желаемый результат.

person Dev-iL    schedule 02.07.2018
comment
Действительно интересное решение! - person RedEyed; 03.07.2018