使用 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
没有错字,xrange
是range
的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 中处理 TIFF(导入、导出)