使用scikit-image将numpy数组保存为高精度(16位)图像
我正在处理二维的浮点数numpy数组,想把它们保存为高精度的灰度.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位的浮点数:
array([[ 0. , 0.33333334],
[ 0.66666669, 1. ]], dtype=float32)
但我怀疑这真的有32位,因为我保存的是16位的无符号整数到文件里。如果有人能告诉我哪里出错了,那就太好了。我希望这个方法也能扩展到三维数组(也就是说,每个颜色通道保存16位,总共48位每张图片)。
更新:
问题出在imsave上。图像是每个通道8位。怎么才能用io.imsave输出高位深的图像呢?
1 个回答
12
你想使用 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]]
关于三维数组,你需要正确地构建这个数组,然后它就能正常工作:
# 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))
这样的操作可以把它恢复到原来的形状。