简体   繁体   English

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

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

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.我还没有找到一种方法,可以在处理 TIFF 格式时保留每个通道的 16 位深度。 I am hoping that some helpful soul will have a solution.我希望一些有用的灵魂会有一个解决方案。

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.到目前为止,我找到的唯一解决方案是使用 ImageMagick 将图像转换为 PNG。 Then the bog standard matplotlib.pyplot.imread reads the PNG file without any problems.然后沼泽标准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 文件,到目前为止,这也不是很简单。

It has limited functionality, especially when it comes to writing back to disk non RGB images, but Christoph Gohlke's tifffile module reads 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)

The answer by @Jaime works. @Jaime的回答有效。

In the mean time I managed to also solve the problem using cv2.imread in OpenCV.与此同时,我还cv2.imread在 OpenCV 中使用cv2.imread解决了这个问题。

By default cv2.imread will convert a 16 bit, three channel image in a.tif to 8 bit as shown in the question.默认情况下, cv2.imread会将cv2.imread的 16 位三通道图像a.tif为 8 位,如问题所示。

cv2.imread accepts a flag after the filename ( cv2.imread(filename[, flags]) ) which specifies the colour type of the loaded image cf. cv2.imread在文件名( cv2.imread(filename[, flags]) )之后接受一个标志cv2.imread(filename[, flags])它指定加载图像的颜色类型。 the documentation : 文档

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

I found an additional alternative to the two methods above.我找到了上述两种方法的另一种替代方法。

The scikit-image package can also read 16 bit, three channel TIFF files using both tifffile.py and FreeImage and specifying them as the plugin to be used. scikit-image包还可以使用tifffile.py和 FreeImage 读取 16 位、三通道 TIFF 文件,并将它们指定为要使用的插件。

While reading using tifffile.py is 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.虽然使用tifffile.py阅读可能以@Jaime所示的方式更简单,但我想我会展示它是如何与 scikit-image 一起使用的,以防有人想以这种方式进行。

For anyone using Ubuntu, FreeImage is available as libfreeimage3 using apt .对于使用 Ubuntu 的任何人,FreeImage 可以作为libfreeimage3使用apt

If the tifffile.py plugin 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.tif and c.tif using ImageMagick shows that each channel in both images are 16 bit.使用 ImageMagick 检查b.tifc.tif显示两个图像中的每个通道都是 16 位。

For me the previous alternatives did not work.对我来说,以前的替代方法不起作用。 I have used gdal successfully 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 diver that you can use to write the data.有一个可用于写入数据的受支持 diver的列表。

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

Just struggled considerably trying to read a multi-image TIFF with JPEG compression using Scikits-Image (skimage.io).只是在尝试使用 Scikits-Image (skimage.io) 读取带有 JPEG 压缩的多图像 TIFF 时非常挣扎。 Am using a Windows 10 distribution of Anaconda Python3;正在使用 Anaconda Python3 的 Windows 10 发行版; tifffile was installed through Anaconda Navigator or 'conda install'. tifffile 是通过 Anaconda Navigator 或“conda install”安装的。

Finally, uninstalled 'tifffile' with 'conda remove tifffile'.最后,使用“conda remove tifffile”卸载“tifffile”。 Next re-installed 'tifffile' with 'pip install tifffile'.接下来使用“pip install tifffile”重新安装“tifffile”。 This installed the latest 'tifffile' plugin - version 2020.5.5.这安装了最新的“tifffile”插件 - 版本 2020.5.5。 Next installed image codecs with 'pip install imagecodecs'.接下来使用“pip install imagecodecs”安装图像编解码器。 And now the following code works:现在以下代码有效:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM