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-pimin, 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.tif
和 c.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 位,三通道,彩色图像的主要内容,如果未能解决你的问题,请参考以下文章