У меня есть следующий код 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()
ВЫХОД:
Но когда я пытаюсь отобразить срез трехмерного массива из массива 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()
ВЫХОД:
Приведенное здесь решение работает, как и ожидалось, когда я сохраняю изображение в виде трехмерного массива и переключаюсь обратно в изображение 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()
ВЫХОД:
Может кто-нибудь объяснить, пожалуйста, это поведение? Я не понимаю, как код работает, как ожидается, для трехмерного массива массивов, но работает по-разному для среза трехмерного массива массива 4D.
Тип данных по умолчанию для массива, созданного с помощью numpy.zeros
- это numpy.float64
(т.е. с плавающей запятой). Таким образом, data
являются массивом с плавающей запятой. В строке im = Image.fromarray(data[0], 'RGB')
, вы явно указан режим, чтобы быть 'RGB'
, что означает 8 - битные целые числа (см Modes документацию), так 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)