乐于分享
好东西不私藏

GeoAI数据下载源码逻辑拆解

GeoAI数据下载源码逻辑拆解

 jie

在 GeoAI 整个体系中,数据获取并不是一个简单的“下载动作”,而是一条完整的数据管道。从代码实现上看,GeoAI 将这一过程集中在 geoai/download.py 模块中,并围绕 STAC(SpatioTemporal Asset Catalog)构建了一套统一的数据访问方式。这一设计的核心思想是:**把“数据源差异”隐藏在统一接口之后,让用户只关注空间范围和任务本身。**本文将围绕源码中的关键函数,拆解 GeoAI 的数据获取逻辑,并解释其背后的设计思路。


GeoAI 数据下载的真实执行路径

在代码层面,GeoAI 的数据下载不是单一函数,而是一条典型流程:

STAC查询 → 获取Item → 签名访问 → 获取Asset → 下载/读取 → 本地保存

对应到源码逻辑,可以拆成三类核心函数:

  1. 1. STAC Item 处理(数据定位)
  2. 2. Asset 读取(数据访问)
  3. 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. 1. 去掉 URL 参数(token 等)
  2. 2. 提取文件名
  3. 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 只面对“干净的数据”。

接下来的内容将围绕几种数据展开介绍,主旨还是以geoai的几种数据源,敬请期待吧。