#python #numpy #opencv #mask #pixel-manipulation
Вопрос:
Я пытаюсь изменить все красные и синие пиксели на изображении на черные, чтобы иметь только зеленые пиксели (в зависимости от определенных условий).
Чтобы сделать это прямо сейчас, я использую несколько циклов for, и процесс, хотя и работает, идет чрезвычайно медленно.
Код, который у меня есть до сих пор —
### Test image is my original RGB image
mat = np.asarray(testim)
for elemento in mat:
for pixel in element:
if ((pixel[0] pixel[2]) >= (2*pixel[1])): #Non-vegetation background changing to black according to the rule (R B >= 2G)
pixel[0] = 0
pixel[1] = 0
pixel[2] = 0
elif pixel[1] > pixel[0] and pixel[1] > pixel[2] and pixel[1] > 25: # Treat these as green vegetation and do not change anything
continue
else: # Change background to black
pixel[0] = 0
pixel[1] = 0
pixel[2] = 0
cv2_imshow(testim)
print(testim.shape)
Есть ли какой-либо способ векторизовать это с помощью Numpy без использования вложенных циклов for, чтобы ускорить работу одного и того же процесса? Я немного новичок в операциях NumPy и не понимаю, как это сделать. Я ценю вашу помощь!
Например : Мое входное изображение — [1]: https://i.stack.imgur.com/zWGtA.jpg
Выходное изображение, которое у меня сейчас есть с приведенной выше логикой — [2]: https://i.stack.imgur.com/VkmLC.jpg
Я хотел бы получить тот же результат с более быстрым кодом, предпочтительно с использованием NumPy вместо вложенных циклов for, которые у меня есть в настоящее время
Комментарии:
1. У вас есть данные для
testim
работы?2. @JoostVn только что отредактировал вопрос с образцом изображения и выводом
Ответ №1:
Я разделил массив изображений на три массива (r, g, b), чтобы сделать правила более интуитивно понятными. В этом формате должно быть легко добавлять любые новые!
r, g, b = mat[:,:,0], mat[:,:,1], mat[:,:,2]
rule_1 = (r b > 2 * g)
rule_2 = ~((g > r) amp; (g > b) amp; (g > 25))
mat[rule_1 | rule_2] = 0
Комментарии:
1. Этот подход тоже сработал! Большое спасибо за помощь!
Ответ №2:
Вы должны иметь возможность получить доступ к своей красной матрице с mat[:,:,0]
помощью зеленого и синего и аналогично с ними.
Ваша маска из зеленых пикселей затем:
mask = (mat[:,:,1]>mat[:,:,0]) amp; (mat[:,:,1]>mat[:,:,2]) amp; (mat[:,:,1]>25)
где вы проводите сравнения по элементам и по элементам И объединяете сравнения в логическую 2D-матрицу.
Затем вы можете обнулить пиксели друг друга, выполнив:
# Repeat mask along the three channels
mask = np.repeat(mask[:,:,np.newaxis], 3, axis=2)
# Zero non-green elements
mat[~mask] = 0
Комментарии:
1. Большое вам спасибо за быстрый ответ и объяснение! Это сработало именно так, как я хотел
Ответ №3:
Из вашего кода следует, что вы не меняете значения, когда
pixel[1] > pixel[0] and pixel[1] > pixel[2] and pixel[1] > 25
Таким образом, мы можем сформировать логический массив этого условия и проиндексировать его обратно в массив и установить эти места равными 0:
# since used more than once, assign to a variable
green = mat[:, :, 1]
# your "elif" condition
not_change_condition = (green > mat[:, :, 0]) amp; (green > mat[:, :, 2]) amp; (green > 25)
# index with its inverse and change
mat[~not_change_condition] = 0
Комментарии:
1. Этот подход тоже сработал, и ваши комментарии помогли мне понять, почему.. Большое спасибо за помощь!