在做遥感数据预处理时,批量重投影几乎是绕不开的一步。尤其是当我们面对多个季节、多个景幅、多个波段的影像时,手工逐个处理不仅费时间,还容易出错。
这篇文章结合一个批处理脚本的思路,整理出一套适合分享的做法:如何用 ArcPy 批量完成遥感影像重投影,并且分成两种常见情况说明。
- 原始遥感影像已经有坐标系
- 原始遥感影像没有坐标系
如果你平时也在做 Landsat、Sentinel 或其他栅格影像的批量处理,这个思路很适合直接改成自己的项目脚本。
一、为什么要先分清有没有坐标系
重投影前最关键的一步,不是直接转换,而是先判断原始数据是否已经带有正确的空间参考。
- 如果影像已经有坐标系,可以直接做 ProjectRaster 重投影。
- 如果影像没有坐标系,必须先用 DefineProjection 补上正确的原始坐标系,再进行投影转换。
这两步不能混淆,因为“定义投影”和“重投影”不是一回事:DefineProjection 只是告诉软件这份数据原本属于哪个坐标系,ProjectRaster 才是真正把数据转换到新的坐标系。
二、批量处理的核心思路
- 遍历不同季节、不同日期目录。
- 按波段筛选目标文件,比如 B2、B4、B5。
- 复制临时文件并处理空间参考。
- 输出到统一的目标坐标系。
如果把流程拆开看,关键代码其实只有两部分:批量查找影像,以及处理空间参考并重投影。
三、关键代码提取
1.环境与坐标系准备
import arcpy |
这段代码做了三件事:开启覆盖输出、创建输出目录、定义原始坐标系和目标坐标系。
2.批量查找影像并筛选波段
for season, dirs in seasons.items(): |
这段逻辑适合批量处理遥感数据目录:外层按季节或项目分组,中层遍历影像目录,内层按波段查找对应文件。
3. 重投影的核心处理
src = found[0] |
- shutil.copy2:先复制一份临时文件,避免直接改原数据。
- DefineProjection:给没有正确空间参考的源文件补投影信息。
- ProjectRaster:将影像真正重投影到目标坐标系。
- BILINEAR:双线性插值,适合连续型遥感数据。
- cell_size="30":指定输出分辨率,保持 30m 尺度。
四、情况一:原始遥感影像已经有坐标系
这是最简单、也最推荐的情况。如果原始影像已经包含正确的空间参考信息,那么你只需要直接重投影即可,不需要再执行 DefineProjection。
示例代码
import arcpy |
- 确认原始影像坐标系正确。
- 直接调用重投影工具。
- 设置目标坐标系和输出分辨率。
- 影像元数据完整。
- 数据本身已经带有 .prj 或空间参考信息。
- 你只想把它统一到另一个投影带或坐标系。
五、情况二:原始遥感影像没有坐标系
这是很多实际项目中更麻烦的情况。如果原始影像没有坐标系,软件并不知道它原本属于哪个空间参考,这个时候不能直接重投影,否则结果大概率会错位。
正确做法是先定义原始坐标系,再进行重投影。
示例代码
import arcpy |
- 先复制一份临时文件。
- 用 DefineProjection 说明原始数据属于哪个坐标系。
- 再用 ProjectRaster 转到目标坐标系。
- 删除临时文件,保持目录整洁。
- 原始数据缺少空间参考信息。
- 影像只有像素值,没有正确的投影描述。
- 你已经明确知道它本来属于哪个坐标系。
六、两个情况的区别总结
可以直接记成一句话:有坐标系就直接重投影,没有坐标系就先定义,再重投影。
情况 | 是否需要 DefineProjection | 是否需要 ProjectRaster |
原始影像已有坐标系 | 不需要 | 需要 |
原始影像没有坐标系 | 需要 | 需要 |
七、参数选择建议
- out_coor_system:目标坐标系,建议统一成项目标准。
- resampling_type:连续数据通常用 BILINEAR。
- cell_size:如果原始分辨率是 30m,输出也建议保持 30m。
- 临时文件命名:建议加 _tmp_ 前缀,方便清理和排错。
八、我在实际批处理里常用的写法
如果你要把这套逻辑整理成可复用脚本,建议把“是否已有坐标系”单独封装成一个判断流程。这样后面换数据源时,只需要改少量参数。
def reproj_raster(src, dst, source_sr=None, target_sr=None): |
九、结语
批量重投影并不复杂,真正要注意的是先判断原始影像有没有坐标系,再决定是否需要先定义投影。
如果你已经有原始空间参考,就直接重投影;如果没有,就先补上正确的原始坐标系,再统一转换到目标投影。把这条逻辑理顺之后,ArcPy 和其他 GIS 工具的批处理思路其实都是一致的。