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

Posted

技术标签:

【中文标题】Python:读写 TIFF 16 位,三通道,彩色图像【英文标题】:Python: Read and write TIFF 16 bit , three channel , colour images 【发布时间】:2013-08-26 14:41:49 【问题描述】:

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

【问题讨论】:

【参考方案1】:

它的功能有限,尤其是在将非 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)

【讨论】:

这行得通!但这是处理 tiff 图像的正确方法吗?我使用 gdal_translate convert tiff ti png 并使用此方法通过转换为 PIL 图像来读取 tiff 和输出 png。图像像素值不同。使用这种方法得到的值比使用gdal得到的值略低 tifffile 可以通过“pip install tifffile”获取。 ref - pypi.org/project/tifffile 推荐使用 pip 安装,运行速度更快。例如,imread 大约快 99 倍。【参考方案2】:

@Jaime 的回答有效。

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

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

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

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

所以下面会不经转换就读取图片:

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

【讨论】:

是否可以使用 cv2.imshow() 显示图像?我能够重现您的示例,但无法显示图像.. 我可以用 cv2.imshow 显示图像,所以我不确定为什么它在你的情况下不起作用。 为了使用 imshow 查看图像,我建议移动并缩放到 8 位范围。这是我的代码 sn-p imin, imax = np.min(im), np.max(im); im -= imin; imf = np.array(im,'float32'); imf *= 255./(imax-imin); im = np.asarray(np.round(imf), 'uint8')【参考方案3】:

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

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

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

对于使用 Ubuntu 的任何人,FreeImage 可以通过 libfreeimage3 使用 apt 获得。

如果使用 tifffile.py 插件选项,则必须将 tifffile.py 复制到 skimage/io/_plugins 目录(例如,在 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')

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

【讨论】:

这个方法给出ValueError: cannot decompress jpeg error【参考方案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 列表,您可以使用它来写入数据。

【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:

尝试使用 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”)。

【讨论】:

以上是关于Python:读写 TIFF 16 位,三通道,彩色图像的主要内容,如果未能解决你的问题,请参考以下文章

python-PIL-16bit-灰度图像生成-tiff

如何在 Python OpenCV 中读取 TIFF 图像的 alpha 通道?

ImageJ 16 位照片到 tiff 值

16位tiff解码器,用于flex

如何编写 5+ 通道 TIFF?

使用Albumentations 对16位图像做增强