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

Lar*_*Chr 26 python png tiff numpy image

有没有人有一种在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
Run Code Online (Sandbox Code Playgroud)

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

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

Jai*_*ime 30

它的功能有限,特别是在写回磁盘非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')
Run Code Online (Sandbox Code Playgroud)

Photoshop没有抱怨我从中做的事情就读了:

>>> tiff.imsave('new.tiff', a)
Run Code Online (Sandbox Code Playgroud)


Lar*_*Chr 23

@Jaime的答案有效.

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

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

cv2.imread在filename(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)
Run Code Online (Sandbox Code Playgroud)

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

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

>>> cv2.imwrite('out.tif', im)
Run Code Online (Sandbox Code Playgroud)

使用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
  ....
Run Code Online (Sandbox Code Playgroud)


Lar*_*Chr 10

我发现了上述两种方法的另一种替代方法.

所述scikit图像包也可读取16位,同时使用三个通道TIFF文件tifffile.py中使用和FreeImage的并指定它们作为插件.

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

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

如果使用tifffile.py插件选项,则必须将tif​​ffile.py复制到skimage/io/_plugins目录(在Ubuntu上为f.ex.,在我的情况下是完整路径/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)
Run Code Online (Sandbox Code Playgroud)

编写TIFF文件:

>>> skimage.io.imsave('b.tif', im, plugin='tifffile')
>>> skimage.io.imsave('c.tif', im, plugin='freeimage')
Run Code Online (Sandbox Code Playgroud)

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


G M*_*G M 5

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

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

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

有一个可用于写入数据的受支持 diver的列表。