使用光栅显示 tiff 图像的特定部分,而无需加载整个文件
Posted
技术标签:
【中文标题】使用光栅显示 tiff 图像的特定部分,而无需加载整个文件【英文标题】:Display specific part of tiff image using rasterio without having to load the entire file 【发布时间】:2021-07-27 03:41:49 【问题描述】:我有一个包含地图的大型 tiff 文件(大约 2GB)。我已经能够成功读取数据,甚至使用以下 python 代码显示它:
import rasterio
from rasterio.plot import show
with rasterio.open("image.tif") as img:
show(img)
data = img.read()
这很好用。但是,我需要能够显示此地图的特定部分,而不必将整个文件加载到内存中(因为它占用了太多的 RAM,并且在许多其他 PC 上不可行)。为此,我尝试使用 rasterio 的 Window 类,但是当我尝试显示地图时,结果与显示完整地图的方式不同(好像它导致数据丢失):
import rasterio
from rasterio.plot import show
from rasterio.windows import Window
with rasterio.open("image.tif") as img:
data = img.read(window=Window(0, 0, 100000, 100000))
show(data)
所以我的问题是,我怎样才能显示地图的一部分,而不必将整个文件加载到内存中,同时让它看起来好像是从完整的地图图像中裁剪出来的?
提前感谢:)
【问题讨论】:
你能澄清一下你所说的结果不同是什么意思吗?我假设坐标,还有其他的东西,比如颜色? @mihi 两者。首先,它显示了所有的地图,而宽度和高度小于实际的宽度和高度。另外,这是一张地形图。当我完全显示它时,它看起来很棒,但是当我尝试显示它的一部分时,它显示为黄色和紫色,并且高度根本不清楚。 【参考方案1】:它在第一种情况下显示得很好但在第二种情况下显示不好的原因是,在第一种情况下,您将rasterio.DatasetReader
的实例传递给show
(show(img)
),但在第二种情况下,您传入一个 numpy 数组 (show(data)
)。 DatasetReader
包含附加信息,特别是仿射变换和颜色解释,show
使用。
show
在第一种情况下(用于 RGB 数据)所做的其他事情可以为窗口情况重新创建,如下所示:
import rasterio
from rasterio.enums import ColorInterp
from rasterio.plot import show
from rasterio.windows import Window
with rasterio.open("image.tif") as img:
window = Window(0, 0, 100000, 100000)
# Lookup table for the color space in the source file
source_colorinterp = dict(zip(img.colorinterp, img.indexes))
# Read the image in the proper order so the numpy array will have the colors in the
# order expected by matplotlib (RGB)
rgb_indexes = [
source_colorinterp[ci]
for ci in (ColorInterp.red, ColorInterp.green, ColorInterp.blue)
]
data = img.read(rgb_indexes, window=window)
# Also pass in the affine transform corresponding to the window in order to
# display the correct coordinates and possibly orientation
show(data, transform=img.window_transform(window))
(通过查看源代码here,我知道show
做了什么)
对于具有单通道的数据,用于绘图的底层 matplotlib 库根据数据的最小值和最大值缩放颜色范围。要获得与以前完全相同的颜色,您需要知道整个图像的最小值和最大值,或者一些相当接近的值。
然后你可以明确告诉matplotlib的imshow
如何缩放:
with rasterio.open("image.tif") as img:
window = Window(0, 0, 100000, 100000)
data = img.read(window=window, masked=True)
# adjust these
value_min = 0
value_max = 255
show(data, transform=img.window_transform(window), vmin=value_min, vmax=value_max)
其他 kwargs(如 vmin
和 vmax
此处)将传递给 matplotlib.axes.Axes.imshow
,如文档中的 here 所述。
来自matplotlibdocumenation:
vmin,vmax:浮动,可选 当使用标量数据且没有明确的范数时,vmin 和 vmax 定义颜色图覆盖的数据范围。默认情况下,颜色图覆盖所提供数据的完整值范围。当给出 norm 时,不推荐使用 vmin/vmax。使用 RGB(A) 数据时,参数 vmin/vmax 被忽略。
这样您还可以更改它使用的颜色图等。
【讨论】:
虽然它没有 RGB 通道...只是灰色。这是我打印 source_colorinterp 字典时得到的:<ColorInterp.gray: 1>: 1
啊,我明白了。我还为单通道案例添加了一些细节。不过,如果没有一些实际数据,我也不是 100% 确定的。我希望它仍然有帮助:)以上是关于使用光栅显示 tiff 图像的特定部分,而无需加载整个文件的主要内容,如果未能解决你的问题,请参考以下文章