13

如何在 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

4 回答 4

9

对于从 16 位灰度 TIFF 到 PNG 的无损转换,请使用PythonMagick

from PythonMagick import Image
Image('pinei_2002300_1525_modis_ch02.tif').write("foo.png")
于 2011-08-30T20:01:46.230 回答
8

偶然发现这个线程试图用 PIL / numpy 保存 16 位 TIFF 图像。

版本:python 2.7.1 - numpy 1.6.1 - PIL 1.1.7

这是我写的一个快速测试。uint16 numpy 数组 -> 转换为字符串 -> 转换为“I;16”类型的 PIL 图像 -> 保存为 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 条存储的图像)。

于 2012-01-27T10:09:41.133 回答
6

您似乎偶然发现了一个 PIL 错误,或者一个未实现的极端案例。

这是一个解决方法:

i16.mode = 'I'
i16.point(lambda i:i*(1./256)).convert('L').save('foo.png')
于 2011-08-30T19:09:40.360 回答
0

使用 PIL 4.1+ 将 ImageJ TIFF 转换为 JPEG

im = numpy.array(Image.open('my.tiff'))
image = Image.fromarray(im / numpy.amax(im) * 255)
image.save('my.jpg')
于 2017-04-18T20:25:18.197 回答