作为一名长期从事地理空间数据处理的开发者,我经常需要从卫星图像中提取有价值的信息用于机器学习项目。Google Earth Engine(GEE)是目前最强大的地理空间分析平台之一,但它的Python API文档相对匮乏。本文将分享我如何通过GEE Python API获取Sentinel-2卫星图像并导出到Roboflow进行标注的完整工作流程。
这个方案特别适合需要大量标注卫星图像进行计算机视觉训练的研究人员和工程师。相比传统下载方式,通过GEE可以直接获取经过预处理的图像,节省了大量数据收集和预处理时间。下面我将详细介绍从账号注册到最终导出的每个步骤,包括一些官方文档中没有提及的实用技巧。
首先需要访问GEE注册页面申请账号。注意以下几点:
提示:如果急需使用,可以先尝试GEE的JavaScript IDE,它不需要审批即可使用基础功能。
我推荐使用conda创建独立环境以避免依赖冲突:
bash复制conda create -n gee python=3.8
conda activate gee
pip install earthengine-api google-api-python-client google-auth-httplib2 google-auth-oauthlib
运行以下代码完成认证:
python复制import ee
import google.auth
# 初始化Earth Engine
ee.Authenticate() # 这会打开浏览器完成OAuth认证
ee.Initialize()
# 同时认证Google Drive用于后续导出
credentials, project = google.auth.default()
认证过程中常见问题及解决方案:
GEE的数据以ImageCollection形式组织,每个Collection包含多个Image(图像)。Sentinel-2数据位于COPERNICUS/S2_SR(地表反射率产品)和COPERNICUS/S2(顶层大气反射率产品)。两者主要区别:
| 特性 | S2_SR | S2 |
|---|---|---|
| 预处理级别 | L2A(地表反射率) | L1C(顶层反射率) |
| 大气校正 | 已应用 | 未应用 |
| 云掩膜 | 包含SCL分类波段 | 需手动处理 |
| 适用场景 | 精确地表分析 | 大气研究 |
以下代码展示了如何获取指定区域、时间的Sentinel-2图像:
python复制# 定义感兴趣区域(Des Moines市中心坐标)
aoi = ee.Geometry.Point([-93.62, 41.59]).buffer(5000) # 5公里半径
# 获取2023年最少云的Sentinel-2图像
collection = (ee.ImageCollection('COPERNICUS/S2_SR')
.filterBounds(aoi)
.filterDate('2023-01-01', '2023-12-31')
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
.sort('CLOUDY_PIXEL_PERCENTAGE'))
# 获取最少云的图像
image = collection.first()
关键参数说明:
filterBounds: 空间范围过滤,支持Point/Polygon等几何类型filterDate: 时间范围,格式为'YYYY-MM-DD'CLOUDY_PIXEL_PERCENTAGE: 官方云量元数据,<20%可获得较清晰图像Sentinel-2包含13个光谱波段,常用RGB组合:
| 组合类型 | 红波段 | 绿波段 | 蓝波段 | 用途 |
|---|---|---|---|---|
| 真彩色 | B4 | B3 | B2 | 自然色彩可视化 |
| 假彩色 | B8 | B4 | B3 | 植被分析 |
| 农业 | B11 | B8 | B2 | 作物健康监测 |
导出到Roboflow通常使用真彩色:
python复制rgb = image.select(['B4', 'B3', 'B2']).visualize(min=0, max=3000)
注意:Sentinel-2的反射率值通常需要缩放(默认×0.0001),visualize方法已自动处理
python复制# 定义导出任务
task = ee.batch.Export.image.toDrive(
image=rgb,
description='DesMoines_Export',
folder='GEE_Exports', # Google Drive文件夹名
region=aoi,
scale=10, # Sentinel-2最高分辨率
crs='EPSG:4326', # WGS84坐标系
maxPixels=1e10
)
# 启动任务
task.start()
关键参数解析:
scale: 导出分辨率(米),Sentinel-2多光谱波段为10mmaxPixels: 最大像素数,大区域需要增加此值crs: 坐标参考系统,常用EPSG:4326(WGS84)或UTM分区GEE任务队列可通过以下方式检查:
python复制import time
def check_task_status(task_id):
status = ee.batch.Task.status(task_id)['state']
while status in ['READY', 'RUNNING']:
print(f'Task {task_id} status: {status}')
time.sleep(60)
status = ee.batch.Task.status(task_id)['state']
print(f'Final status: {status}')
return status
check_task_status(task.id)
典型问题处理:
导出的TIFF文件需要转换为Roboflow支持的格式(建议PNG/JPG):
python复制from PIL import Image
import numpy as np
# 读取导出的TIFF
with Image.open('exported.tif') as img:
arr = np.array(img)
# 转换为8bit
arr = (arr / arr.max() * 255).astype(np.uint8)
Image.fromarray(arr).save('output.jpg', quality=95)
python复制from roboflow import Roboflow
rf = Roboflow(api_key="YOUR_API_KEY")
project = rf.workspace().project("project-name")
project.upload("image_folder/")
当需要导出大量区域时,采用以下优化:
map()函数处理多个时间点python复制# 分块导出示例
grid = aoi.boundingBox().divide(3) # 3×3网格
for i in range(9):
cell = grid.geometry().coordinates().get(i)
task = ee.batch.Export.image.toDrive(
image=rgb.clip(cell),
description=f'Grid_{i}',
region=cell,
scale=10
)
task.start()
内存管理:
ee.Reducer()处理大区域统计缓存策略:
ee.data.getPixels()获取小区域数据配额监控:
python复制quota = ee.data.getAssetRootsQuota()
print(f'Used: {quota["asset_size"]["usage"]/1e9}GB / Total: {quota["asset_size"]["limit"]/1e9}GB')
以下是我在实际项目中遇到的典型问题及解决方案:
认证失败:
EEException: Invalid credentials~/.config/earthengine/credentials并重新认证导出超限:
User memory limit exceeded波段不匹配:
Roboflow上传失败:
400 Bad Request任务堆积:
ee.batch.Task.list()管理任务队列,取消低优先级任务对于需要定期运行的任务,我建议将整个流程封装为Python类,并添加异常处理和日志记录。一个实用的项目结构如下:
code复制/project
/config
credentials.json
settings.yaml
/src
gee_connector.py
image_processor.py
roboflow_uploader.py
/data
/raw
/processed
main.py
在实际应用中,这个流程已经帮助我的团队高效处理了超过10TB的卫星图像数据,用于农业监测和城市发展分析。最关键的体会是:一定要在导出前做好数据质量检查,包括云量、季节性和分辨率验证,否则后续标注工作可能事倍功半。