添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Python。读取和写入TIFF 16位、三通道、彩色图像

31 人关注

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

python
image
numpy
png
tiff
Lars Chr
Lars Chr
发布于 2013-08-26
6 个回答
Jaime
Jaime
发布于 2020-05-07
已采纳
0 人赞同

它的功能有限,特别是在写回磁盘的非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转换tiff ti png,用这个方法读取tiff并通过转换为PIL图像输出png。图像的像素值不同。用这种方法得到的值比用gdal得到的值要低一些
tifffile可以通过'pip install tifffile'获得。 ref - pypi.org/project/tifffile 建议使用pip安装,它的操作要快得多。例如,imread的速度大约是99倍。
Lars Chr
Lars Chr
发布于 2020-05-07
0 人赞同

的答案。 @Jaime works.

与此同时,我还设法用以下方法解决了这个问题 cv2.imread in OpenCV.

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

替换代码0】在文件名后接受一个标志( cv2.imread(filename[, flags]) ),该标志指定了所加载图像的颜色类型,参见。 文件 :

  • >0 returns a 3 channel colour image. This results in conversion to 8 bit as shown above.
  • 0 returns a greyscale image. Also results in conversion to 8 bit.
  • <0 returns the image as is. This will return a 16 bit image.
  • 因此,下面将读取图像而不进行转换。

    >>> 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
        
    zml
    是否可以用cv2.imshow()来显示图像?我能够重现你的例子,但不能显示图像。
    我能够用cv2.imshow显示图片,所以我不知道为什么它在你的情况下不能工作。
    为了用imshow查看图像,我建议将图像移到8位范围内,并进行缩放。这里是我的代码片段 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')
    Lars Chr
    Lars Chr
    发布于 2020-05-07
    0 人赞同

    我发现了上述两种方法之外的另一个选择。

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

    Writing TIFF files:

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

    使用ImageMagick检查b.tifc.tif的比特深度,显示这两张图片的每个通道都是16比特。

    该方法给出ValueError:无法解压jpeg错误
    G M
    G M
    发布于 2020-05-07
    0 人赞同

    对我来说,以前的替代方案并不奏效。我使用了 gdal 成功读取1GB的16bit图像。

    你可以用这样的方法打开一个图像。

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

    有一个清单,其中包括supported diver你可以用它来写数据。

    zeno
    zeno
    发布于 2020-05-07
    0 人赞同

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

    import OpenImageIO as oiio
    input = oiio.ImageInput.open ("/path/to/image.tif")
        
    barnwaldo
    barnwaldo
    发布于 2020-05-07
    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'安装了图像编解码器。现在下面的代码可以工作了。