python - 使用光栅显示 tiff 图像的特定部分,而无需加载整个文件
问题描述
我有一个包含地图的大型 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)
所以我的问题是,如何在不必将整个文件加载到内存的情况下显示地图的一部分,同时让它看起来好像是从完整的地图图像中裁剪出来的?
提前致谢 :)
解决方案
它在第一种情况下显示得很好,但在第二种情况下显示不好的原因是,在第一种情况下,您传递了一个rasterio.DatasetReader
to show
( show(img)
) 的实例,但在第二种情况下,您传递了一个 numpy 数组 ( show(data)
)。包含附加信息,DatasetReader
特别是仿射变换和颜色解释,它show
使用。
在第一种情况下(对于 RGB 数据)所做的其他事情show
可以为窗口情况重新创建,如下所示:
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))
(我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 (like vmin
and vmax
here) 将被传递给matplotlib.axes.Axes.imshow
,如此处所述。来自 matplotlib文档:
vmin, vmax: float, optional
当使用标量数据且没有明确的范数时,vmin 和 vmax 定义颜色图覆盖的数据范围。默认情况下,颜色图覆盖所提供数据的完整值范围。当给出 norm 时,不推荐使用 vmin/vmax。当使用 RGB(A) 数据时,参数 vmin/vmax 被忽略。
这样,您还可以更改它使用的颜色图等。
推荐阅读
- python - Python:有没有办法提取和连接多个文本文件系列,同时删除每个文件的前 3 行?
- excel - 在其他工作表和向下填充日期的最后一行下方复制和粘贴动态范围
- markdown - doxygen 抱怨我的 image-in-link 标签
- html - 是否可以在中使用样式属性
tag?</h1> <div id="body"><p>How to use <code>style</code> attribute in <code><title></code> tag? Is it possible?</p> </div> </data> <hr><data id="62063004"> - elasticsearch - 如何理解 x-pack 上“搜索延迟”的弹性搜索性能
- c++ - C ++中具有未知数组大小的指针转换
- reactjs - 一个组件中页面刷新后上下文值为空
- javascript - 在反应中处理不确定的复选框
- java - @Valid @ModelAttribute 无法正常工作
- haskell - 为什么 Haskell 中的以下阶乘代码有效?