30

有没有人有在 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 文件,到目前为止这也不是很简单。

4

6 回答 6

35

它的功能有限,尤其是在将非 RGB 图像写回磁盘时,但Christoph Gohlke 的tifffile模块可以毫无问题地读取 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)
于 2013-08-26T16:51:51.723 回答
28

@Jaime的答案有效。

同时,我也设法解决了cv2.imread在 OpenCV 中使用的问题。

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

cv2.imread在文件名 ( ) 之后接受一个标志,该标志cv2.imread(filename[, flags])指定加载图像的颜色类型 cf. 文档:_

  1. >0返回 3 通道彩色图像。这导致转换为 8 位,如上所示。
  2. 0返回灰度图像。也会导致转换为 8 位。
  3. <0按原样返回图像。将返回一个 16 位图像。

因此,以下将读取图像而不进行转换:

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

请注意,OpenCV 以相反im[:,:,0]的顺序返回 R、G 和 B 通道,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
  ....
于 2013-08-27T09:14:55.657 回答
12

我找到了上述两种方法的另一种替代方法。

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

虽然阅读 using可能更简单地以@Jaimetifffile.py所示的方式完成,但我想我会展示它如何与 scikit-image 一起使用,以防有人想以这种方式进行操作。

对于使用 Ubuntu 的任何人,FreeImage 都可以作为libfreeimage3使用apt.

如果使用tifffile.py插件选项,则必须将 tifffile.py 复制到 skimage/io/_plugins 目录(f.ex. 在 Ubuntu 上,我的完整路径是/usr/local/lib/python2.7/dist-packages/skimage/io/_plugins/)。

>>> 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)

编写 TIFF 文件:

>>> skimage.io.imsave('b.tif', im, plugin='tifffile')
>>> skimage.io.imsave('c.tif', im, plugin='freeimage')

检查两者的位深度b.tifc.tif使用 ImageMagick 显示两个图像中的每个通道都是 16 位。

于 2013-08-28T08:33:22.040 回答
6

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

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

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

有一个受支持的潜水员列表,您可以使用它来写入数据。

于 2016-09-23T15:48:43.637 回答
1

我推荐使用 Python 绑定到 OpenImageIO,它是处理 vfx 域(通常是 16/32 位)中各种图像格式的标准。

import OpenImageIO as oiio
input = oiio.ImageInput.open ("/path/to/image.tif")
于 2018-12-17T18:10:50.387 回答
1

尝试使用 Scikits-Image (skimage.io) 读取具有 JPEG 压缩的多图像 TIFF 非常困难。我正在使用 Anaconda Python3 的 Windows 10 发行版;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”)。

于 2020-05-07T02:33:37.533 回答