【问题标题】:Python and 16 Bit TiffPython 和 16 位 Tiff
【发布时间】:2011-11-07 00:33:20
【问题描述】:

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

【问题讨论】:

标签: python tiff 16-bit


【解决方案1】:

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

这里有一个解决方法:

i16.mode = 'I'
i16.point(lambda i:i*(1./256)).convert('L').save('foo.png')

【讨论】:

  • 我得到:ValueError: unknown raw mode
  • @mankoff:抱歉,我一定是尝试了两种不同的方法,然后复制了错误的一种。我已将答案从mode='I;16' 编辑为mode='I',现在试试吧。
  • 这似乎有效。数据是否丢失?我认为(?)I 模式是 8 位。
  • @mankoff,如果不出意外,转换为“L”模式将截断为 8 位。如果您想查看原始数据,请在模式设置为'I' 后尝试getpixelload
【解决方案2】:

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

from PythonMagick import Image
Image('pinei_2002300_1525_modis_ch02.tif').write("foo.png")

【讨论】:

  • 这怎么可能是无损的?您将从每像素 16 位变为 8 位。
  • PNG 格式支持每通道 16 位灰度(1 通道)。 en.wikipedia.org/wiki/Portable_Network_Graphics#Color_depth
  • 我使用 PNG 很多年了,从来不知道它支持每通道 16 位。回到 RFC 2083,我可以看到从一开始就是这样。谢谢你今天教我一些东西!
  • 很好的解决方案但是 PythonMagick 不包含在许多默认安装(EPD、sage)中,这使得代码的可移植性降低。
【解决方案3】:

偶然发现这个线程试图用 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 条存储的图像)。

【讨论】:

    【解决方案4】:

    使用 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')
    

    【讨论】:

      猜你喜欢
      • 2011-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多