Изменить размер всех изображений, хранящихся в массиве - PullRequest
2 голосов
/ 18 марта 2020

Я сохранил изображения, прочитанные через cv2.imread, в массиве masks. Форма массива: (10, 5248, 7936, 3) (10 images, image height, image width, 3 channels).

. Сейчас я пытаюсь скопировать этот массив, но размер каждого изображения изменяется до значений monitor_h и monitor_w. Вот что у меня есть:

resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])

for i in range(masks.shape[0]):
    resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))

Но изображения, которые я получаю с cv2.imshow, черно-белые. Что-то должно было случиться с каналами. Есть ли какие-либо выводы?

Ответы [ 2 ]

2 голосов
/ 18 марта 2020

Чтобы понять, почему ваши изображения получаются черно-белыми, давайте пройдемся по коду.

resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])

Эта строка по умолчанию создает массив типа np.float.

resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))

Эта строка присваивает результат cv2.resize срезу resized_masks.

Ваши исходные изображения и, следовательно, результат cv2.resize, предположительно, имеют тип np.uint8. Присвоение преобразует значения в float s для помещения их в буфер. Актерский состав хорош сам по себе: 5 конвертируется в 5.0, 255 конвертируется в 255.0. Проблема в том, что значения float интерпретируются как обрезанные до диапазона [0.0, 1.0], а не [0.0, 255.0]. Таким образом, в результате получаются изображения, которые фактически являются всеми нулями и единицами, даже если они содержат то, что выглядит как правильные значения.

Вы можете проверить правильность значений, отобразив

resized_masks.astype(masks.dtype)

Это не настоящее исправление. Реальное исправление состоит в том, чтобы начать с правильного типа вывода:

resized_masks = np.empty((masks.shape[0], monitor_h, monitor_w, masks.shape[3]), dtype=masks.dtype)

Обратите внимание, что принято использовать кортежи для фигур, а не списков, но это не имеет значения функционально.

Теперь давайте посмотрите, почему ваш патч сработал.

resized_masks = list(resized_masks)

Это создает список ссылок Python для каждого подмассива. Поскольку вы действительно выполняете нарезку, они все равно будут указывать на непрерывный буфер под капотом, но важно то, что каждый resized_masks[i] является отдельной ссылкой, а не срезом в один и тот же объект массива.

resized_masks[i] = list(cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h)))

Поскольку resized_masks является списком, содержащим ссылки, теперь он присваивает результат cv2.resize элементу списка i, а не назначает содержимое в срез соответствующего размера. Здесь вам не нужна оболочка list, поскольку она вводит ненужное измерение.

resized_masks = np.asarray(resized_masks)

Это просто объединяет список в массив, так как все элементы имеют правильный размер (хотя вы будете см. дополнительную единицу измерения, как указано выше). Как вы можете себе представить, это решение крайне неэффективно. Помимо того, что вы переходите в списки и из них и выделяете несколько ненужных буферов, вы также отбрасываете оригинальный массив np.empty без его использования.

Ваш патч примерно эквивалентен выполнению

resized_masks = np.array([cv2.resize(np.copy(mask), (monitor_w, monitor_h)) for mask in masks])

Я не рекомендую так делать.

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

Итак, я нашел обходной путь для своей проблемы, но мне все еще интересно узнать, что сделало изображения go черно-белыми.

Вот что я придумал:

resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])
resized_masks = list(resized_masks)

for i in range(len(resized_masks)):
    resized_masks[i] = list(cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h)))

resized_masks = np.asarray(resized_masks)
...