Python:读写TIFF 16位,三通道彩色图像

时间:2013-08-26 14:41:50

标签: python image numpy png tiff

有没有人有一种方法可以在Python中导入每通道16位,3通道TIFF图像?

我还没有找到一种方法,在处理TIFF格式时会保留每个通道的16位深度。我希望一些有用的灵魂能有解决方案。

以下列出了我迄今为止尝试过但未取得成功的结果:

import numpy as np
import PIL.Image as Image
import libtiff
import cv2

im = Image.open('a.tif')
# IOError: cannot identify image file

tif = libtiff.TIFF.open('a.tif')
im = tif.read_image()
# im only contains one of the three channels. im.dtype is uint16 as desired.
im = []
for i in tif.iter_images():
    # still only returns one channel

im = np.array(cv2.imread('a.tif'))
# im.dtype is uint8 and not uint16 as desired.
# specifying dtype as uint16 does not correct this

到目前为止,我找到的唯一解决方案是使用ImageMagick将图像转换为PNG。然后,沼泽标准matplotlib.pyplot.imread读取PNG文件没有任何问题。

我遇到的另一个问题是将任何numpy数组保存为16位PNG文件,到目前为止还不是直截了当。

6 个答案:

答案 0 :(得分:29)

功能有限,特别是在写回磁盘非RGB图像时,Christoph Gohlke's tifffile module读取3通道16位TIFF并没有问题,我只是测试了它:

>>> import tifffile as tiff
>>> a = tiff.imread('Untitled-1.tif')
>>> a.shape
(100L, 100L, 3L)
>>> a.dtype
dtype('uint16')

而且Photoshop在没有抱怨我从做什么的情况下阅读:

>>> tiff.imsave('new.tiff', a)

答案 1 :(得分:22)

@Jaime的答案有效。

与此同时,我设法在OpenCV中使用cv2.imread来解决问题。

默认情况下,cv2.imread会将a.tif中的16位三通道图像转换为8位,如问题所示。

cv2.imread接受文件名(cv2.imread(filename[, flags]))后面的标志,该标志指定加载图像的颜色类型cf. documentation

  1. > 0 返回3通道彩色图像。这导致转换为8位,如上所示。
  2. 0 返回灰度图像。也导致转换为8位。
  3. < 0 按原样返回图像。 将返回16位图像。
  4. 因此,以下内容将在不转换的情况下读取图像:

    >>> im = cv2.imread('a.tif', -1)
    >>> im.dtype
    dtype('uint16')
    >>> im.shape
    (288, 384, 3)
    

    请注意,OpenCV以相反的顺序返回R,G和B通道,因此im[:,:,0]是B通道,im[:,:,1]是G通道,im[:,:,2]是R通道。

    我还发现cv2.imwrite可以写16位,三通道TIFF文件。

    >>> cv2.imwrite('out.tif', im)
    

    使用ImageMagick检查位深度:

    $ identify -verbose out.tif
      Format: TIFF (Tagged Image File Format)
      Class: DirectClass
      Geometry: 384x288+0+0
      Resolution: 72x72
      Print size: 5.33333x4
      Units: PixelsPerInch
      Type: TrueColor
      Base type: TrueColor
      Endianess: MSB
      Colorspace: sRGB
      Depth: 16-bit
      Channel depth:
        red: 16-bit
        green: 16-bit
        blue: 16-bit
      ....
    

答案 2 :(得分:10)

我找到了上述两种方法的另一种选择。

scikit-image包还可以使用tifffile.py和FreeImage读取16位三通道TIFF文件,并将它们指定为要使用的插件。

虽然使用tifffile.py进行阅读可能更简单地按照@Jaime所示的方式进行,但我想我会展示它是如何与scikit-image一起使用的,以防有人想要这样做方式。

对于使用Ubuntu的任何人,使用libfreeimage3的{​​{1}}可以使用FreeImage。

如果使用apt插件选项,则必须将tif​​ffile.py复制到skimage / io / _plugins目录(在Ubuntu上为f.ex.,我的案例中的完整路径为tifffile.py)。

/usr/local/lib/python2.7/dist-packages/skimage/io/_plugins/

编写TIFF文件:

>>> import skimage.io
>>> im = skimage.io.imread('a.tif', plugin='tifffile')
>>> im.dtype
dtype('uint16')
>>> im.shape
(288, 384, 3)
>>> im = skimage.io.imread('a.tif', plugin='freeimage')
>>> im.dtype
dtype('uint16')
>>> im.shape
(288, 384, 3)

使用ImageMagick检查>>> skimage.io.imsave('b.tif', im, plugin='tifffile') >>> skimage.io.imsave('c.tif', im, plugin='freeimage') b.tif的bitdepth显示两个图像中的每个通道都是16位。

答案 3 :(得分:4)

对我来说,之前的替代方案不起作用。我已成功使用gdal来读取1 GB的16位图像。

您可以使用以下内容打开图片:

from osgeo import gdal
import numpy as np
ds = gdal.Open("name.tif")
channel = np.array(ds.GetRasterBand(1).ReadAsArray())

您可以使用supported diver列表来编写数据。

答案 4 :(得分:0)

我建议使用与OpenImageIO的python绑定,这是处理vfx域(通常为16/32位)中各种图像格式的标准。

import OpenImageIO as oiio
input = oiio.ImageInput.open ("/path/to/image.tif")

答案 5 :(得分:0)

试图使用Scikits-Image(skimage.io)读取具有JPEG压缩的多图像TIFF只是相当费力。我正在使用Windows 10发行版的Anaconda Python3; tifffile是通过Anaconda Navigator或“ conda install”安装的。

最后,用“ conda remove tifffile”卸载了“ tifffile”。接下来用“ pip install tifffile”重新安装“ tifffile”。这安装了最新的“ tifffile”插件-版本2020.5.5。接下来使用“ pip install imagecodecs”安装的图像编解码器。现在,以下代码可以工作了:

import skimage.io
img = skimage.io.imread('picture.tiff', plugin='tifffile')

请注意,只有在按照上述顺序完成“ tifffile”和“ imagecodes”的安装(并且首先删除了Anaconda“ tifffile”)后,此方法才有效。