Сохранить массив numpy как изображение с высокой точностью (16 бит) с scikit-image
Я работаю с двумерными массивами numpy с плавающей запятой, которые я бы хотел сохранить в greyscale.png файлах с высокой точностью (например, 16 бит). Я хотел бы сделать это, используя пакет scikit-image skimage.io
, если это возможно.
Вот главное, что я пробовал:
import numpy as np
from skimage import io, exposure, img_as_uint, img_as_float
im = np.array([[1., 2.], [3., 4.]], dtype='float64')
im = exposure.rescale_intensity(im, out_range='float')
im = img_as_uint(im)
im
дает:
array([[ 0, 21845],
[43690, 65535]], dtype=uint16)
Сначала я попытался сохранить это как изображение, а затем перезагрузить с помощью библиотеки изображений Python:
# try with pil:
io.use_plugin('pil')
io.imsave('test_16bit.png', im)
im2 = io.imread('test_16bit.png')
im2
дает:
array([[ 0, 85],
[170, 255]], dtype=uint8)
Итак, где-то (в записи или чтении) я потерял точность. Затем я попытался использовать плагин matplotlib:
# try with matplotlib:
io.use_plugin('matplotlib')
io.imsave('test_16bit.png', im)
im3 = io.imread('test_16bit.png')
im3
дает мне 32-битный float:
array([[ 0. , 0.33333334],
[ 0.66666669, 1. ]], dtype=float32)
но я сомневаюсь, что это действительно 32-бит, учитывая, что я сохранил 16-битный uint для файла. Было бы здорово, если бы кто-то мог указать мне, где я ошибаюсь. Я хотел бы, чтобы это также распространялось на 3D-массивы (то есть сохраняло 16 бит на цветной канал, для 48 бит на изображение).
UPDATE:
Проблема заключается в imsave. Изображения имеют 8 бит на канал. Как можно использовать io.imsave для вывода изображения с высокой глубиной?
Ответы
Ответ 1
Вы хотите использовать библиотеку freeimage
для этого:
import numpy as np
from skimage import io, exposure, img_as_uint, img_as_float
io.use_plugin('freeimage')
im = np.array([[1., 2.], [3., 4.]], dtype='float64')
im = exposure.rescale_intensity(im, out_range='float')
im = img_as_uint(im)
io.imsave('test_16bit.png', im)
im2 = io.imread('test_16bit.png')
Результат:
[[ 0 21845]
[43690 65535]]
Что касается 3D-массивов, вам нужно правильно построить массив, а затем он будет работать:
# im = np.array([[1, 2.], [3., 4.]], dtype='float64')
im = np.linspace(0, 1., 300).reshape(10, 10, 3)
im = exposure.rescale_intensity(im, out_range='float')
im = img_as_uint(im)
io.imsave('test_16bit.png', im)
im2 = io.imread('test_16bit.png')
Обратите внимание, что прочитанное изображение перевернуто, поэтому что-то вроде np.fliplr(np.flipud(im2))
приведет к оригинальной форме.