Python 与 16 位 TIFF
我想知道如何在Python中转换并保存一个16位单通道的TIF文件。
我可以顺利加载16位和32位的图像,并且看到32位的图像模式是F
,而16位的图像模式是I;16S
:
import Image
i32 = Image.open('32.tif')
i16 = Image.open('16.tif')
i32
# <TiffImagePlugin.TiffImageFile image mode=F size=2000x1600 at 0x1098E5518>
i16
# <TiffImagePlugin.TiffImageFile image mode=I;16S size=2000x1600 at 0x1098B6DD0>
但是我在处理16位图像时遇到了麻烦。如果我想把它保存为PNG格式,直接保存是行不通的:
i32.save('foo.png')
# IOError: cannot write mode F as PNG
i16.save('foo.png')
# ValueError: unrecognized mode
如果我把32位的图像转换一下,就可以保存了:
i32.convert('L').save('foo.png')
但是同样的命令在16位图像上就不管用了:
i16.convert('L').save('foo.png')
# ValueError: unrecognized mode
4 个回答
8
我在找方法用PIL和numpy保存16位的TIFF图片时,偶然发现了这个讨论。
使用的版本是:python 2.7.1 - numpy 1.6.1 - PIL 1.1.7
我写了一个简单的测试。首先是一个uint16的numpy数组,然后把它转换成字符串,再转换成PIL的'I;16'类型的图片,最后保存为16位的TIFF格式。
在ImageJ中打开这个图片,能看到正确的水平渐变效果,图片类型显示为'每像素位数:16(无符号)'
import Image
import numpy
data = numpy.zeros((1024,1024),numpy.uint16)
h,w = data.shape
for i in range(h):
data[i,:] = numpy.arange(w)
im = Image.fromstring('I;16',(w,h),data.tostring())
im.save('test_16bit.tif')
补充: 从1.1.7版本开始,PIL不支持写入压缩文件,但pylibtiff支持(使用lzw压缩)。所以测试代码变成了(在pylibtiff 0.3下测试):
import Image
import numpy
from libtiff import TIFFimage
data = numpy.zeros((1024,1024),numpy.uint16)
h,w = data.shape
for i in range(w):
data[:,i] = numpy.arange(h)
tiff = TIFFimage(data, description='')
tiff.write_file('test_16bit.tif', compression='lzw')
#flush the file to disk:
del tiff
请注意:测试代码改成生成垂直渐变,否则无法实现压缩(参考警告:pylibtiff目前支持读取和写入使用TIFF条带存储的图片)。
8
看起来你遇到了PIL(Python图像库)中的一个小问题,或者是一个没有实现的特殊情况。
这里有一个解决办法:
i16.mode = 'I'
i16.point(lambda i:i*(1./256)).convert('L').save('foo.png')
9
如果你想把16位灰度的TIFF图片无损地转换成PNG格式,可以使用PythonMagick这个工具:
from PythonMagick import Image
Image('pinei_2002300_1525_modis_ch02.tif').write("foo.png")