Как записать образец массива изображения без изменения значений пикселей - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть проект сегментации изображения, и метки истинности земли представлены как изображения, где значение пикселя обозначает метку. Мне нужно изменить размеры изображений и меток, сохраняя при этом метки в одном и том же наборе значений.

Я много чего перепробовал, Все меняют установленное значение.

Позволяет создавать фиктивные данные

from skimage.transform import rescale, resize
from scipy import ndimage
from PIL import Image
import cv2

mask = np.zeros((30,20), dtype=np.uint16)
mask[22:26,12:30]=70
mask[25:27,14:17]=30
print('original label', mask.shape, np.unique(mask))
Выходы: исходная форма этикетки: (30, 20) значения оригинальной этикетки: [0 30 70]

Мне нужно изменить размер метки, чтобы результат имел только 0, 30, 70 значений .

Что я пробовал
skimage_resized = resize(mask, (mask.shape[0]//2, mask.shape[1]//2), mode='constant')
print(skimage_resized.shape, np.unique(mask_resized))

skimage_rescale = rescale(mask, 1.0/2.0, mode='constant')
print(skimage_rescale.shape, np.unique(mask_resized))

ndimage_resized = ndimage.interpolation.zoom(mask, 0.5)
print(ndimage_resized.shape, np.unique(mask_resized))


cv2_resized = cv2.resize(mask, (mask.shape[0]//2, mask.shape[1]//2),
                        interpolation=cv2.INTER_NEAREST)
print(cv2_resized.shape, np.unique(mask_resized))

mask_pil = Image.fromarray(mask, mode=None)
pil_resized = mask_pil.thumbnail((mask.shape[0]//2, mask.shape[1]//2), Image.NEAREST)
print(skimage_resized.shape, np.unique(pil_resized))

Выход:

(15, 10) [ 0  5  6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [ 0  5  6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [ 0  5  6 28 29 30 31 61 62 65 70 71 74 75 76]
(10, 15) [ 0  5  6 28 29 30 31 61 62 65 70 71 74 75 76]
(15, 10) [None]

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Нашел решение с помощью openCV.

import numpy as np
import cv2
resizeto = 2
small_lable = cv2.resize(mask, (mask.shape[1]//resizeto, 
                         mask.shape[0]//resizeto),
                        interpolation=cv2.INTER_NEAREST)
small_lable = (np.array(small_lable)).astype('uint8')
print(small_lable.shape, np.unique(small_lable))
plt.imshow(small_lable)

выход:

(15, 10) [ 0 30 70]
0 голосов
/ 26 апреля 2018

Из документов (выделено мое):

Обратите внимание, что при понижающей дискретизации изображения для изменения размера и масштабирования необходимо выполнить сглаживание по Гауссу , чтобы избежать искажения артефактов. См. Аргументы anti_aliasing и anti_aliasing_sigma для этих функций.

Уменьшение масштаба служит для понижающей дискретизации n-мерного изображения с помощью целочисленных коэффициентов с использованием локального среднего для элементов каждого блока коэффициентов размера, заданных в качестве параметра функции.

Одним из возможных путей решения вашей проблемы было бы сокращение выборки с помощью базового среза :

import numpy as np

dx, dy = 2, 2
mask = np.zeros((30, 20), dtype=np.uint16)
mask[22:26, 12:30] = 70
mask[25:27, 14:17] = 30

downsampled = mask[::dx, ::dy]
print(downsampled.shape, np.unique(downsampled))

Выходные данные из приведенного выше фрагмента:

(15, 10) [ 0 30 70]
...