Вырезать маску из изображения с определенным запасом в пикселях numpy opencv - PullRequest
2 голосов
/ 02 марта 2020

Я играю с программой сегментации Mask RCNN (https://github.com/matterport/Mask_RCNN), которая обучается на наборе данных COCO. Он обнаруживает людей (наряду со многими другими объектами, которыми я также пренебрегаю) на изображении и возвращает одну или несколько масок Person, то есть логические массивы Numpy, содержащие значения True для всех пикселей, которые классифицируются как «Person», и значения False для всех другие пиксели:

Overlay Image

Таким образом, введенное изображение (массив формы uint8 (3900,2922,3)) становится маской (массив логических форм ( 3900,2922)) или несколько масок, когда на снимке обнаружено несколько человек.

Теперь я могу использовать эту маску, чтобы вырезать человека из изображения с помощью простого Numpy индексации массива:

mask3d = np.dstack([mask]*3)
cut_out_mask = np.invert(mask3d)
res = np.where(cut_out_mask, 0, image)

Это возвращает следующее изображение: Cut_out Image

Поскольку маски, возвращаемые программой Mask_RCNN, довольно узкие, я хотел бы добавить поле в несколько пикселей (скажем, 15 пикселей), так что я получаю что-то вроде этого:

manual

Какие функции Numpy / OpenCV можно использовать, чтобы вырезать маску из исходное изображение (похоже на нп .where), добавив поле 15 пикселей вокруг маски?

Ответы [ 3 ]

1 голос
/ 03 марта 2020

Один из способов сделать это - использовать cv2.dilate для увеличения площади поверхности маски. В зависимости от формы маски, вы можете создавать различные формы и размеры структурирующих элементов с помощью cv2.getStructuringElement. Например, если ваша маска имеет прямоугольную форму angular, вы можете использовать cv2.MORPH_RECT или если ваша маска имеет круглую форму, вы можете использовать cv2.MORPH_ELLIPSE. Кроме того, вы можете изменить размер ядра и количество итераций для расширения. Расширив маску, вы можете использовать cv2.bitwise_and, чтобы получить свой результат. Вот минимальный воспроизводимый пример:

Исходное изображение

image

Маска

image

Расширение

image

Бит-а для результата

image

import cv2

# Load image and mask
image = cv2.imread('1.png')
mask = cv2.imread('mask.png')

# Create structuring element, dilate and bitwise-and
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,25))
dilate = cv2.dilate(mask, kernel, iterations=3)
result = cv2.bitwise_and(image, dilate)

cv2.imshow('dilate', dilate)
cv2.imshow('result', result)
cv2.waitKey()
0 голосов
/ 03 марта 2020

Вы можете использовать cv2.dlate морфологическая операция для расширения маски:

new_mask = cv2.dilate(mask, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (50,50)))

Пример кода, который загружает маску и расширяет маску:

import cv2

# Read the mask from a file (for testing).
mask = cv2.imread("sample_mask.png", cv2.IMREAD_GRAYSCALE);

new_mask = cv2.dilate(mask, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (50,50)))

# Display mask and new_mask
cv2.imshow('mask', mask)
cv2.imshow('new_mask', new_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

маска:
enter image description here

new_mask:
enter image description here

0 голосов
/ 02 марта 2020

Функция, которую вы ищете: cv2.filter2D().

Я написал для вас короткую демонстрацию:

import numpy as np
import cv2

Сначала мы создаем демонстрационную маску, содержащую квадрат в середина:

mask = np.zeros((300, 300))
mask[100:200, 100:200] = 1

Затем мы создадим наше ядро ​​для функции filter2D:

kernel = np.ones((32, 32))

Я использовал размер 32, чтобы получить требуемый отступ в 15 пикселей.

paddedMask = cv2.filter2D(mask, 1, array)

Просто для демонстрации я отображаю изображение со следующим кодом:

image = cv2.threshold(np.array(padding, type=np.uint8), 1, 255, 1)[1]
cv2.imshow("Test", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...