Статическое изображение, отображаемое при сохранении изображений PIL в массив 4D Numpy - PullRequest
0 голосов
/ 10 января 2019

У меня есть следующий код Python, где я сохраняю некоторые изображения формы 326x490x3 в виде numpy массивов для предварительной обработки на более позднем этапе. Я хочу сохранить мои изображения в массиве 4D NumPy, чтобы позже я смог обработать их партиями. Код работает нормально, но я обнаружил, что когда я конвертирую каждый 3D-элемент массива 4D обратно в RGB-изображение, я просто получаю статическое изображение.

КОД

data = np.zeros((129, 326, 490, 3))
image_path = '0.jpg'
img = Image.open(image_path)
data[0,:,:,:] = np.asarray(img)
im = Image.fromarray(data[0], 'RGB')
im.show()

OUTPUT :

Output when using 4D array

Но когда я пытаюсь отобразить срез трехмерного массива из массива 4D в виде градаций серого , он работает нормально.

код

data = np.zeros((129, 326, 490, 3))
image_path = '0.jpg'
img = Image.open(image_path)
data[0,:,:,:] = np.asarray(img)
im = Image.fromarray(np.dot(data[0], [0.299, 0.587, 0.114]))
im.show()

OUTPUT

enter image description here

Решение, приведенное здесь , работает, как и ожидалось, когда я сохраняю изображение в трехмерном массиве и снова переключаюсь на изображение PIL.

КОД

data = np.zeros((129, 326, 490, 3))
image_path = '0.jpg'
img = Image.open(image_path)
im = Image.fromarray(np.asarray(img), 'RGB')
im.show()

OUTPUT

enter image description here

Может кто-нибудь объяснить это поведение? Я не понимаю, как код работает, как и ожидалось, для трехмерного массива, но работает иначе для среза трехмерного массива 4D.

1 Ответ

0 голосов
/ 10 января 2019

Тип данных по умолчанию для массива, созданного numpy.zeros, равен numpy.float64 (т.е. с плавающей запятой). Итак, data - массив с плавающей точкой. В строке im = Image.fromarray(data[0], 'RGB') вы явно указали режим, равный 'RGB', что означает 8-битные целые числа (см. Документацию Режимы ), поэтому fromarray интерпретирует аргумент data[0] как массив из 8-битных целых чисел. По-видимому, он не пытается преобразовать входной массив; это просто предполагает, что базовые данные в массиве хранятся как 8-битные целые числа. Поскольку data[0] на самом деле содержит значения с плавающей запятой, результат неверен.

В случае, когда вы используете im = Image.fromarray(np.dot(data[0], [0.299, 0.587, 0.114])), вы не указали явно режим, поэтому fromarray использует свой собственный код для определения режима, который в этом случае будет 'F' (32-битная плавающая точка) , Так что он правильно конвертирует ваши данные. Например, если вы указали режим 'L' (что означает 8-битное черно-белое изображение) (т. е. im = Image.fromarray(np.dot(data[0], [0.299, 0.587, 0.114]), 'L')), вызов будет успешным, но данные изображения снова будут неверными, поскольку fromarray будет интерпретировать память, которая содержит значения с плавающей запятой, как если бы она содержала 8-битные целочисленные пиксели.

Вероятно, самое простое решение - создать data как массив 8-битных целых чисел без знака:

data = np.zeros((129, 326, 490, 3), dtype=np.uint8)
...