使用 numpy 在 Python 中处理 TIFF(导入、导出)

Posted

技术标签:

【中文标题】使用 numpy 在 Python 中处理 TIFF(导入、导出)【英文标题】:Working with TIFFs (import, export) in Python using numpy 【发布时间】:2011-11-26 00:58:48 【问题描述】:

我需要一个 python 方法来打开 TIFF 图像并将其导入 numpy 数组,这样我就可以分析和修改像素数据,然后再次将它们保存为 TIFF。 (它们基本上是灰度的光强度图,代表每个像素的相应值)

我找不到任何有关 TIFF 的 PIL 方法的文档。我试图弄清楚,但只有“错误模式”或“不支持文件类型”错误。

我需要在这里使用什么?

【问题讨论】:

【参考方案1】:

首先,我从this page 下载了一个名为a_image.tif 的测试TIFF 图像。然后我用 PIL 像这样打开:

>>> from PIL import Image
>>> im = Image.open('a_image.tif')
>>> im.show()

这显示了彩虹图像。要转换为 numpy 数组,很简单:

>>> import numpy
>>> imarray = numpy.array(im)

我们可以看到图像的大小和数组的形状匹配:

>>> imarray.shape
(44, 330)
>>> im.size
(330, 44)

并且该数组包含uint8 值:

>>> imarray
array([[  0,   1,   2, ..., 244, 245, 246],
       [  0,   1,   2, ..., 244, 245, 246],
       [  0,   1,   2, ..., 244, 245, 246],
       ..., 
       [  0,   1,   2, ..., 244, 245, 246],
       [  0,   1,   2, ..., 244, 245, 246],
       [  0,   1,   2, ..., 244, 245, 246]], dtype=uint8)

一旦你完成了数组的修改,你可以像这样把它变成一个 PIL 图像:

>>> Image.fromarray(imarray)
<Image.Image image mode=L size=330x44 at 0x2786518>

【讨论】:

我遇到了数据类型的问题。对某些人来说效果很好,例如如果我的数组中有 numpy.int16 数字,但对于 numpy.uint16 image.fromarray 产生:“TypeError:无法处理此数据类型” 看fromarray的源码,貌似不是处理无符号16位数组的。 @Jakob 截至 2020 年 6 月 PIL doesn't support color images with more than 8 bits per color,您将不得不使用不同的库(或自己贡献功能)。 这是我在尝试打开一个对 PIL 来说太大的图像时得到的结果:DecompressionBombError: Image size (900815608 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack. 对我来说 imarray.shape 给 (x,y , 3) ??我错过了什么??【参考方案2】:

我使用 matplotlib 来读取 TIFF 文件:

import matplotlib.pyplot as plt
I = plt.imread(tiff_file)

I 将是ndarray 类型。

根据文档,虽然它实际上是 PIL 在处理 TIFF 时在幕后工作,因为 matplotlib 仅在本机读取 PNG,但这对我来说效果很好。

还有一个plt.imsave 函数用于保存。

【讨论】:

这是迄今为止使用 TIFF 最简单的方法!尝试了十几种方法,这就是票。一定要点赞! 观看部分怎么样? 看来matplotlib改变了策略:ValueError: Only know how to handle extensions: ['png']; with Pillow installed matplotlib can handle more images【参考方案3】:

您也可以使用 GDAL 来执行此操作。我知道它是一个地理空间工具包,但没有什么要求您拥有制图产品。

链接到用于 windows 的预编译 GDAL 二进制文件(假设这里是 windows) http://www.gisinternals.com/sdk/

访问数组:

from osgeo import gdal

dataset = gdal.Open("path/to/dataset.tiff", gdal.GA_ReadOnly)
for x in range(1, dataset.RasterCount + 1):
    band = dataset.GetRasterBand(x)
    array = band.ReadAsArray()

【讨论】:

上面的代码是单页TIF还是多页TIF?我想使用 gdal 将 16 位 tiff 堆栈加载到 nparrays 中。 这应该读入输入数据类型或将所有内容移动到numpy的float64。您可以在ReadAsArray() 调用的末尾添加.astype(sometype) 调用以进行转换。不确定这是否可以复制(只是尚未测试)。 @Chikinn 点评来源: ***.com/review/suggested-edits/17962780 xrange 没有错字,xrangerange 的python 2 版本。我接受了这个编辑,因为 python 3 仍在积极改进中,而 python 2 没有。【参考方案4】:

PyLibTiff 对我来说比 PIL 效果更好,截至 2021 年 5 月,still doesn't support 彩色图像的每种颜色超过 8 位。

from libtiff import TIFF

tif = TIFF.open('filename.tif') # open tiff file in read mode
# read an image in the current TIFF directory as a numpy array
image = tif.read_image()

# read all images in a TIFF file:
for image in tif.iter_images(): 
    pass

tif = TIFF.open('filename.tif', mode='w')
tif.write_image(image)

您可以使用安装 PyLibTiff

pip3 install numpy libtiff

PyLibTiff 的自述文件中也提到了tifffile 库,但我没有尝试过。

【讨论】:

这很好。到目前为止,tifffile 已包含在 SciKit skimage.external.tifffile 中,但如果您从 Christoph Gohlke 先生那里下载 tifffile.py,它也可以作为模块导入 pip install 不会在 Windows 上“正常工作”,请参阅 ***.com/questions/39483328/…【参考方案5】:

在图像堆栈的情况下,我发现使用scikit-image 更容易阅读,matplotlib 更容易显示或保存。我已经使用以下代码处理了 16 位 TIFF 图像堆栈。

from skimage import io
import matplotlib.pyplot as plt

# read the image stack
img = io.imread('a_image.tif')
# show the image
plt.imshow(img,cmap='gray')
plt.axis('off')
# save the image
plt.savefig('output.tif', transparent=True, dpi=300, bbox_inches="tight", pad_inches=0.0)

【讨论】:

而不是“plt.imshow(mol...”你的意思是“plt.imshow(img...”吗?【参考方案6】:

您也可以使用我是作者的pytiff。

import pytiff

with pytiff.Tiff("filename.tif") as handle:
    part = handle[100:200, 200:400]

# multipage tif
with pytiff.Tiff("multipage.tif") as handle:
    for page in handle:
        part = page[100:200, 200:400]

这是一个相当小的模块,可能没有其他模块那么多的功能,但它支持平铺的 TIFF 和 BigTIFF,因此您可以读取大图像的一部分。

【讨论】:

这个功能正是我需要的! (能够读取大文件的一小部分)。但是,当我尝试 pip install 时,我收到 gcc 错误 如果您创建一个带有错误消息的issue,我会看看能否找出问题所在。 是的,我也很感兴趣,但在我尝试安装它时也遇到了错误。我是通过 pip 在 Windows 和 Ubuntu 下完成的。不幸的是,它不起作用!我在这里创建了一个问题:github.com/FZJ-INM1-BDA/pytiff/issues/15 无法安装【参考方案7】:

有一个名为tifffile 的不错的包,它使处理 .tif 或 .tiff 文件变得非常容易。

使用 pip 安装包

pip install tifffile

现在,以 numpy 数组格式读取 .tif/.tiff 文件:

from tifffile import tifffile
image = tifffile.imread('path/to/your/image')
# type(image) = numpy.ndarray

如果要将 numpy 数组保存为 .tif/.tiff 文件:

tifffile.imwrite('my_image.tif', my_numpy_data, photometric='rgb')

tifffile.imsave('my_image.tif', my_numpy_data)

你可以阅读更多关于这个包的信息here。

【讨论】:

只有这个解决方案对我有用,谢谢! pip install tifffile 对我来说还不够。您可能还需要pip install imagecodecs【参考方案8】:

使用 cv2

import cv2
image = cv2.imread(tiff_file.tif)
cv2.imshow('tif image',image)

【讨论】:

这里最简单的方法!【参考方案9】:

我建议使用 Python 绑定到 OpenImageIO,它是处理 vfx 世界中各种图像格式的标准。与 PIL 相比,我发现它在读取各种压缩类型方面更可靠。

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

【讨论】:

Borderline 无法在 Windows 上安装,除非您已经有编译器。【参考方案10】:

如果你想用geoTiff 保存 tiff 编码。你可以使用rasterio

一个简单的代码:

import rasterio

out = np.random.randint(low=10, high=20, size=(360, 720)).astype('float64')
new_dataset = rasterio.open('test.tiff', 'w', driver='GTiff',
                            height=out.shape[0], width=out.shape[1],
                            count=1, dtype=str(out.dtype),
                            )
new_dataset.write(out, 1)
new_dataset.close()

有关 numpy 2 GEOTiff 的更多详细信息。您可以点击:https://gis.stackexchange.com/questions/279953/numpy-array-to-gtiff-using-rasterio-without-source-raster

【讨论】:

以上是关于使用 numpy 在 Python 中处理 TIFF(导入、导出)的主要内容,如果未能解决你的问题,请参考以下文章

python 调用HEG工具批量处理modis数据将hdf转为tif

python读取tif格式的遥感影像(灰度图)并用迭代法阈值选择算法进行二值化处理

使用 NumPy 在 Python 中进行简单的多处理

使用 numpy 在 Python 中处理 TIFF(导入、导出)

如何使用 Python 多处理 Pool.map 在 for 循环中填充 numpy 数组

你如何在 Python 中使用 numpy 处理自然日志(例如“ln()”)?