GeoAI数据下载源码逻辑拆解
jie
在 GeoAI 整个体系中,数据获取并不是一个简单的“下载动作”,而是一条完整的数据管道。从代码实现上看,GeoAI 将这一过程集中在 geoai/download.py 模块中,并围绕 STAC(SpatioTemporal Asset Catalog)构建了一套统一的数据访问方式。这一设计的核心思想是:**把“数据源差异”隐藏在统一接口之后,让用户只关注空间范围和任务本身。**本文将围绕源码中的关键函数,拆解 GeoAI 的数据获取逻辑,并解释其背后的设计思路。
GeoAI 数据下载的真实执行路径
在代码层面,GeoAI 的数据下载不是单一函数,而是一条典型流程:
STAC查询 → 获取Item → 签名访问 → 获取Asset → 下载/读取 → 本地保存
对应到源码逻辑,可以拆成三类核心函数:
-
1. STAC Item 处理(数据定位) -
2. Asset 读取(数据访问) -
3. 文件下载与保存(数据落地)
GeoAI 如何找到数据
GeoAI 的数据获取是基于 STAC 标准完成的,这一点非常关键。STAC 的本质是:用统一 JSON 描述遥感数据的位置、时间、波段等信息在源码中,GeoAI 并不会直接下载数据,而是先获取 STAC Item,然后从 Item 中提取 Asset。
STAC Item → 可访问资源
signed_item = pc.sign(item)
这行代码看似简单,其实是整个下载流程的关键。
代码解释
-
• item:STAC Item(包含影像元数据) -
• pc.sign():对 Planetary Computer 资源进行签名认证 -
• 返回:带有访问权限的 Item
为什么需要这一步?因为很多遥感数据(如 Microsoft Planetary Computer)是需要签名 URL 才能访问的。如果不签名,拿到的只是:
https://.../image.tif?token=xxx
而 pc.sign() 会自动补充访问令牌。 本质:解决“数据能不能访问”的问题
从元数据到真实影像
在 STAC Item 中,真正的数据并不在 Item 本身,而是在 assets 字段中。GeoAI 的做法是:
rgb_asset = signed_item.assets.get("image")
代码解释
-
• assets是一个字典,包含多个波段或资源 -
• "image"是常见的 RGB 影像 key -
• 返回的是一个 Asset 对象(包含 URL)
接下来关键一步:
rgb_asset.href
这才是真正的下载地址
一个完整的 Asset 访问流程
original_filename = os.path.basename( rgb_asset.href.split("?")[0])
这里做了三件事:
-
1. 去掉 URL 参数(token 等) -
2. 提取文件名 -
3. 为本地保存做准备
GeoAI 如何处理不同数据源
GeoAI 并没有简单使用 requests.get(),而是做了更复杂的兼容处理。
核心代码如下:
if rgb_asset.href.startswith("http"): download_with_progress(rgb_asset.href, output_path)else: data = rxr.open_rasterio(rgb_asset.href) data.rio.to_raster(output_path)
代码拆解
HTTP 下载
download_with_progress(url, output_path)
说明:
-
• 使用流式下载 -
• 带进度条 -
• 适用于普通文件服务器
典型场景:公开遥感数据
非 HTTP(如云存储 / 虚拟文件系统)
data = rxr.open_rasterio(rgb_asset.href)
说明:
-
• 使用 rioxarray直接读取 -
• 支持: -
• COG(Cloud Optimized GeoTIFF) -
• S3 / Azure Blob -
• 虚拟文件系统
然后:
data.rio.to_raster(output_path)
写入本地
设计亮点
这一段代码体现了 GeoAI 的一个核心设计:不区分“下载”和“读取”,统一为“数据访问”
多波段数据处理:不仅下载,还做融合
GeoAI 支持多波段下载与处理,例如 Sentinel-2 的多个光谱波段。
核心逻辑如下:
band_data = rxr.open_rasterio(band_url)
然后根据参数:
if merge_bands: band_data_arrays.append((band, band_data))
最终:
band_data.rio.to_raster(file_path)
关键点解释
1. 按波段读取
每个 band 单独读取
2. 可选融合
如果 merge_bands=True:
-
• 会将多个波段 stack 成一个 raster
3. 自动重采样
源码中有一段非常关键:
resampling_method = ( Resampling.bilinearif current_res < cell_sizeelse Resampling.nearest)
说明:
-
• 分辨率不同会自动统一 -
• 高分 → 低分:双线性 -
• 低分 → 高分:最近邻
这解决了遥感数据最常见的问题:分辨率不一致
STAC Asset 读取函数
GeoAI 提供了一个非常典型的函数:
defread_pc_item_asset(item, asset, output=None, as_cog=True):
代码逐行解析
1. 输入处理
ifisinstance(item, str): item = pystac.Item.from_file(item)
支持:
-
• URL -
• 本地 JSON -
• STAC Item 对象
2. 权限签名
signed_item = pc.sign(item)
3. Asset 校验
if asset notin signed_item.assets:raise ValueError(...)
防止请求不存在波段
4. 数据读取
ds = rxr.open_rasterio(asset_url)
直接读取为 xarray 数据
5. 输出为 COG
kwargs["driver"] = "COG"
说明:
-
• 输出 Cloud Optimized GeoTIFF -
• 支持分块读取 -
• 适合 Web GIS
6. 保存
ds.rio.to_raster(output)
这个函数的意义
它其实是一个统一接口:
👉 输入:STAC Item + asset名👉 输出:Raster(内存 or 文件)
矢量数据获取
GeoAI 也支持矢量数据,例如 Overture Maps:
gdf = core.geodataframe(overture_type, bbox=bbox)
代码解释
-
• overture_type:数据类型(如 buildings) -
• bbox:空间范围 -
• 返回:GeoDataFrame
然后:
gdf.to_file(output)
写成 GeoJSON / Shapefile
这一设计的意义
GeoAI 并没有区分:
-
• “影像下载” -
• “矢量下载”
而是统一为:
空间数据获取
GeoAI 下载模块的设计本质
如果你从架构角度看,这个模块其实做了三件事:
统一数据入口
无论是:
-
• Sentinel -
• NAIP -
• Overture Maps
最终都被抽象为:
STAC Item / GeoDataFrame
统一访问方式
通过:
-
• pc.sign()(权限) -
• rxr.open_rasterio()(读取)
实现统一数据访问接口
统一输出格式
最终数据都可以输出为:
-
• GeoTIFF -
• COG -
• GeoJSON
GeoAI 的下载模块,本质不是“下载器”,而是:一个面向空间数据的统一访问层(Data Access Layer)它把复杂的数据源、认证机制、格式差异全部隐藏起来,让上层 AI 和 GIS 只面对“干净的数据”。
夜雨聆风