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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18446804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 10:46:50  来源:igfitidea点击:

Python: Read and write TIFF 16 bit , three channel , colour images

pythonimagenumpypngtiff

提问by Lars Chr

Does anyone have a method for importing a 16 bit per channel, 3 channel TIFF image in Python?

有没有人有在 Python 中导入每通道 16 位、3 通道 TIFF 图像的方法?

I have yet to find a method which will preserve the 16 bit depth per channel when dealing with the TIFF format. I am hoping that some helpful soul will have a solution.

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

Here is a list of what I have tried so far without success and the results:

以下是我迄今为止尝试过但没有成功的列表和结果:

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

So far the only solution I have found is to convert the image to PNG with ImageMagick. Then the bog standard matplotlib.pyplot.imreadreads the PNG file without any problems.

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

Another problem I have is saving any numpy arrays as 16 bit PNG files which so far has not been straightforward either.

我遇到的另一个问题是将任何 numpy 数组保存为 16 位 PNG 文件,到目前为止,这也不是很简单。

采纳答案by Jaime

It has limited functionality, especially when it comes to writing back to disk non RGB images, but Christoph Gohlke's tifffilemodulereads in 3 channel 16-bit TIFFs with no problems, I just tested it:

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

And Photoshop reads without complaining what I get from doing:

Photoshop 阅读时不会抱怨我所做的事情:

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

回答by Lars Chr

The answer by @Jaimeworks.

@Jaime的回答有效。

In the mean time I managed to also solve the problem using cv2.imreadin OpenCV.

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

By default cv2.imreadwill convert a 16 bit, three channel image in a.tifto 8 bit as shown in the question.

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

cv2.imreadaccepts a flag after the filename ( cv2.imread(filename[, flags])) which specifies the colour type of the loaded image cf. the documentation:

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

  1. >0returns a 3 channel colour image. This results in conversion to 8 bit as shown above.
  2. 0returns a greyscale image. Also results in conversion to 8 bit.
  3. <0returns the image as is. Thiswill return a 16 bit image.
  1. >0返回 3 通道彩色图像。这会导致转换为 8 位,如上所示。
  2. 0返回灰度图像。也会导致转换为 8 位。
  3. <0按原样返回图像。将返回一个 16 位图像。

So the following will read the image without conversion:

因此,以下将读取图像而无需转换:

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

Note that OpenCV returns the R, G and B channels in reverse order so im[:,:,0]is the B channel, im[:,:,1]the G channel and im[:,:,2]is the R channel.

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

I have also found that cv2.imwritecan write 16 bit, three channel TIFF files.

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

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

Checking the bit depth with ImageMagick:

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

回答by Lars Chr

I found an additional alternative to the two methods above.

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

The scikit-imagepackage can also read 16 bit, three channel TIFF files using both tifffile.pyand FreeImage and specifying them as the plugin to be used.

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

While reading using tifffile.pyis probably done more simply in the manner shown by @Jaime, I thought I would show how it is used along with scikit-image in case anyone wants to do it in this manner.

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

For anyone using Ubuntu, FreeImage is available as libfreeimage3using apt.

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

If the tifffile.pyplugin option is used the tifffile.py must be copied to the skimage/io/_plugins directory (f.ex. on Ubuntu the full path in my case was /usr/local/lib/python2.7/dist-packages/skimage/io/_plugins/).

如果使用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:

写入 TIFF 文件:

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

Checking the bitdepth of both b.tifand c.tifusing ImageMagick shows that each channel in both images are 16 bit.

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

回答by G M

For me the previous alternatives did not work. I have used gdalsuccessfully for reading a 16bit images of 1 GB.

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

You can open an image with something like this:

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

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

There is a list of supported diverthat you can use to write the data.

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

回答by zeno

I recommend using the python bindings to OpenImageIO, it's the standard for dealing with various image formats in the vfx domain (which usually are 16/32bit).

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

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

回答by barnwaldo

Just struggled considerably trying to read a multi-image TIFF with JPEG compression using Scikits-Image (skimage.io). Am using a Windows 10 distribution of Anaconda Python3; tifffile was installed through Anaconda Navigator or 'conda install'.

只是在尝试使用 Scikits-Image (skimage.io) 读取带有 JPEG 压缩的多图像 TIFF 时非常挣扎。正在使用 Anaconda Python3 的 Windows 10 发行版;tifffile 是通过 Anaconda Navigator 或“conda install”安装的。

Finally, uninstalled 'tifffile' with 'conda remove tifffile'. Next re-installed 'tifffile' with 'pip install tifffile'. This installed the latest 'tifffile' plugin - version 2020.5.5. Next installed image codecs with 'pip install imagecodecs'. And now the following code works:

最后,使用“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')

Note this only works if the install of 'tifffile' and 'imagecodes' was done in the order outlined above (and the Anaconda 'tifffile' is first removed).

请注意,这仅在按上述顺序安装“tifffile”和“imagecodes”时才有效(并且首先删除了 Anaconda 的“tifffile”)。