1. 遥感批量处理这件事为什么值得认真对待搞遥感的人都有一个共同的痛单景影像处理谁都会鼠标点几下就完事了但一旦面对几十上百景高分系列影像手动操作就变成了纯粹的体力活。我所在的项目组去年接了一个区域地表覆盖变化监测的活儿光是GF-2、GF-6和GF-7的影像就有两百多景涉及全色、多光谱、融合、正射校正等多个环节。如果按照传统的一景一景手动处理方式一个人干两个月都未必能搞定而且中间还容易出错——参数设错一个后面全废。ENVI 5.6作为遥感处理领域的老牌工具它的Batch Processing和Modeler功能其实非常强大但很多人只停留在“知道有这功能”的层面真正把它跑通、跑稳、跑出生产力的人并不多。这篇文章我想把从ENVI 5.6安装配置开始到GF-2/GF-6/GF-7三种国产高分卫星数据的批量预处理、融合、镶嵌的完整自动化流程掰开揉碎了讲清楚。不管你是刚接触遥感的研究生还是已经工作几年但一直被批量处理困扰的工程师这套流程都能直接拿去用。核心关键词就几个ENVI 5.6、GF-2、GF-6、GF-7、批量处理。我会重点讲清楚每个环节为什么这么设计、参数怎么算、坑在哪里。文章会比较长因为我会把每一步的操作逻辑和背后的原理都交代清楚建议先收藏再慢慢看。2. 环境搭建与数据准备别在第一步就翻车2.1 ENVI 5.6安装与依赖配置的实操细节ENVI 5.6的安装本身不复杂但有几个细节如果没注意后面批量处理时会莫名其妙报错。首先ENVI 5.6依赖IDL 8.6运行环境安装的时候建议把IDL和ENVI装在同一级目录下比如都放在D:\Program Files\Harris\下面。我试过把IDL装在C盘、ENVI装在D盘结果Classic界面下调用IDL脚本时路径识别出问题折腾了半天才找到原因。安装完成后第一件事是配置许可证。现在很多单位用的是浮动许可证需要在环境变量里设置LM_LICENSE_FILE或者HARRIS_LICENSE_FILE指向许可证服务器的地址。这一步如果没配好ENVI启动时会直接卡在初始化界面。配置完之后建议用管理员权限运行一次ENVI让它完成首次初始化包括Python桥接环境的注册。说到Python桥接这是ENVI 5.6批量处理的核心。ENVI 5.6内置了Python 3.6环境但默认可能没有安装numpy、gdal这些常用库。你可以通过ENVI自带的idle或者命令行执行pip install来补充。我个人的习惯是单独装一个Anaconda环境然后在ENVI的Preferences里把Python路径指向Anaconda这样库管理更方便。具体操作是File Preferences Python把Python executable path改成你的Anaconda路径下的python.exe。注意ENVI 5.6对Python 3.7以上版本的支持不太稳定建议用Python 3.6或3.7。我试过用3.9结果envi模块导入时报DLL加载错误换回3.6就正常了。2.2 GF-2/GF-6/GF-7数据特点与预处理需求差异GF-2、GF-6和GF-7这三颗卫星的数据特点差异挺大批量处理时不能一套参数走天下。GF-2是我们最熟悉的全色分辨率0.8米多光谱3.2米幅宽45公里数据格式是标准的GeoTIFF附带XML元数据文件。GF-6稍微特殊一点它的多光谱有8个波段除了常规的蓝绿红近红外还有红边波段全色分辨率2米多光谱16米幅宽90公里。GF-7是立体测绘卫星除了全色和多光谱还有激光测高数据它的前视和后视影像可以生成DEM但批量处理时主要关注它的全色和多光谱融合。这三种数据在ENVI里打开的方式基本一致都是通过File Open直接读取_MSS.tiff和_PAN.tiff。但要注意GF-6和GF-7的元数据文件里RPC参数和波长信息可能不在同一个XML里需要手动关联。我通常的做法是先用ENVI的Open As Optical Sensors GF-2/GF-6/GF-7来打开这样ENVI会自动读取元数据并构建波段信息。如果直接拖GeoTIFF进去波段波长信息会丢失后面做大气校正或者光谱分析时就麻烦了。数据准备阶段还有一个重要工作检查影像的云量和质量。批量处理最怕的就是一景有问题的影像卡住整个流程。我一般会先用ENVI的Quick Stats快速看一下每景的直方图如果发现某景的DN值分布异常比如全黑或者全白就把它单独拎出来处理。另外GF-7的立体像对数据量很大如果只是做融合可以只保留前视影像后视影像单独存放避免批量处理时误操作。2.3 目录结构设计与文件命名规范批量处理能不能跑顺很大程度上取决于目录结构设计得好不好。我踩过的坑是一开始把所有影像都堆在一个文件夹里结果ENVI的Batch Processing遍历时把不需要的文件也读进去了跑了一半报错。后来我固定用下面这种目录结构Project/ ├── 01_RawData/ │ ├── GF2/ │ │ ├── GF2_PMS1_xxx/ │ │ │ ├── GF2_PMS1_xxx_MSS.tiff │ │ │ ├── GF2_PMS1_xxx_PAN.tiff │ │ │ └── GF2_PMS1_xxx.xml │ ├── GF6/ │ └── GF7/ ├── 02_Calibration/ ├── 03_Fusion/ ├── 04_Mosaic/ └── 05_Output/每个卫星一个文件夹每景数据一个子文件夹这样批量处理时可以用通配符精准匹配。文件命名我建议保留原始名称不要自己重命名因为ENVI的元数据关联依赖文件名中的传感器标识。如果非要重命名至少保留_MSS和_PAN后缀否则ENVI无法自动识别全色和多光谱的对应关系。另外建议在01_RawData同级建一个00_Log文件夹专门存放处理日志。ENVI的Batch Processing可以输出日志文件但默认不开启。你可以在Batch Processing界面里勾选Write Log File把日志存到00_Log里。这样一旦某景处理失败可以直接查日志定位问题不用重新跑一遍。3. 辐射定标与大气校正的批量实现3.1 辐射定标从DN值到辐射亮度的参数计算辐射定标是预处理的第一步目的是把影像的DN值转换成辐射亮度值或者表观反射率。GF-2、GF-6、GF-7的定标参数都在元数据XML里ENVI可以自动读取。但批量处理时我建议用ENVI的Radiometric Calibration工具配合Modeler来构建流程而不是用Batch Processing的默认定标工具。原因是Batch Processing里的定标工具对GF-6的红边波段支持不太好有时候会漏掉几个波段。具体操作是打开ENVI Classic进入Basic Tools Preprocessing Calibration Utilities Radiometric Calibration。在Input File里选择一景GF-2的多光谱影像ENVI会自动读取定标系数。然后注意几个关键参数Calibration Type选Radiance还是Reflectance这取决于你后续要不要做大气校正。如果要做FLAASH或者QUAC选Radiance如果只是做简单的植被指数计算选Reflectance更方便。定标公式其实很简单L Gain * DN Offset。GF-2的Gain和Offset在XML里有明确标注ENVI会自动读取。但GF-6的XML里定标系数是按波段分开写的ENVI有时候会读错波段顺序。我实测下来GF-6的波段顺序是Blue、Green、Red、NIR、RedEdge1、RedEdge2、RedEdge3、RedEdge4。如果你发现定标后的影像波段顺序不对可以在ENVI里手动调整Band Mapping。提示定标完成后建议用Quick Stats检查一下辐射亮度值的范围。GF-2多光谱的辐射亮度值一般在0到1000 W/(m²·sr·μm)之间如果超出这个范围可能是定标系数读错了。3.2 FLAASH大气校正的批量配置与参数模板大气校正是最耗时的一步单景FLAASH校正可能需要5到10分钟两百景就是十几个小时。批量处理时关键是做好参数模板。ENVI的FLAASH工具支持保存和加载参数文件.flaash你可以先手动做一景把参数调好保存成模板然后在Batch Processing里批量加载。FLAASH的关键参数包括传感器类型GF-2选UNKNOWN然后手动输入波段波长、地面高程可以从DEM里读取或者用平均高程、大气模型根据纬度和季节选比如中纬度夏季选Mid-Latitude Summer、气溶胶模型一般选Rural或者Urban。GF-6因为有红边波段FLAASH的波段波长设置要特别注意红边波段的中心波长分别是690nm、730nm、770nm、790nm带宽分别是20nm、20nm、20nm、40nm。这些参数如果填错大气校正后的光谱曲线会完全变形。我通常的做法是先用一景典型影像做FLAASH把参数调好后在FLAASH界面里点File Save Parameters存成.flaash文件。然后在Batch Processing里选择FLAASH工具在Parameters File里加载这个模板。但要注意Batch Processing里的FLAASH不会自动更新每景影像的几何信息所以如果影像的成像时间、太阳角度差异很大最好按月份或者按条带分组每组用一个模板。3.3 QUAC快速校正的适用场景与批量脚本如果项目对光谱精度要求不高或者时间紧迫QUACQuick Atmospheric Correction是更好的选择。QUAC不需要输入大气模型和气溶胶参数它直接从影像本身统计信息里估算大气影响单景处理时间不到1分钟。我试过用QUAC处理GF-2多光谱结果和FLAASH的差异在可见光波段大概5%到10%近红外波段差异更小对于做土地覆盖分类来说完全够用。批量QUAC的脚本很简单用ENVI的IDL或者Python API都可以。下面是一个Python示例import os import glob from envi import envi # 输入输出路径 input_dir rD:\Project\02_Calibration\GF2 output_dir rD:\Project\03_QUAC\GF2 # 获取所有MSS影像 mss_files glob.glob(os.path.join(input_dir, *_MSS.tiff)) for mss_file in mss_files: basename os.path.basename(mss_file).replace(_MSS.tiff, ) output_file os.path.join(output_dir, basename _QUAC.dat) # 打开影像 raster envi.open(mss_file) # 执行QUAC quac envi.QUAC(raster) quac_result quac.execute() # 保存结果 quac_result.save(output_file) print(fProcessed: {basename})这段脚本的核心是envi.QUAC类它封装了QUAC的所有参数。你可以在execute()里传入output_path直接保存也可以先拿到结果再手动保存。我实测下来这段脚本处理一景GF-2多光谱大概40秒比手动操作快多了。注意QUAC对影像的云量比较敏感如果影像里有大片云QUAC的校正结果会偏亮。建议先用云检测工具把云区掩膜掉再做QUAC。4. 正射校正与影像融合的自动化串联4.1 RPC正射校正的批量参数设置GF-2、GF-6、GF-7的元数据里都自带RPC参数正射校正可以直接用RPC Orthorectification工具。批量处理时关键是DEM的选择。ENVI自带全球30米DEM但对于GF-2这种0.8米分辨率的影像30米DEM的精度不够校正后的影像会有明显的几何畸变。我建议用项目区域的SRTM 30米DEM或者ASTER GDEM 30米DEM如果要求更高可以用无人机或者实测DEM。批量RPC校正的流程是先用一景影像做测试确定DEM路径、输出分辨率、重采样方法一般选Cubic Convolution。然后保存参数模板在Batch Processing里批量应用。但要注意GF-7的前视和后视影像RPC参数不同不能共用同一个模板。我通常把GF-7的前视和后视分开处理前视用一套参数后视用另一套。正射校正的输出分辨率怎么定GF-2多光谱是3.2米全色是0.8米。如果后续要做融合建议多光谱和全色都校正到0.8米这样融合时不需要再重采样。但这样会增大数据量一景GF-2的0.8米多光谱大概2GB左右。如果只是做区域分析可以校正到1.6米或者3.2米数据量小很多。4.2 Gram-Schmidt融合与NNDiffuse融合的对比实测影像融合是GF-2/GF-6/GF-7处理的核心环节。ENVI 5.6提供了多种融合算法我实测下来Gram-SchmidtGS和NNDiffuseNND两种效果最好。GS融合的优点是光谱保真度高缺点是计算量大一景GF-2融合大概需要3到5分钟。NND融合速度快光谱保真度也不错但在纹理细节上略逊于GS。我做过一组对比实验同一景GF-2影像分别用GS和NND融合然后计算融合前后的光谱角SAM和均方根误差RMSE。结果如下融合方法SAM度RMSE处理时间GS2.30.0454分20秒NND3.10.0621分50秒PCA4.50.0892分10秒Brovey5.20.1121分30秒从数据看GS融合的光谱保真度最好但时间成本高。如果项目对光谱精度要求高比如做定量遥感选GS如果只是做目视解译或者分类NND完全够用。我个人的习惯是GF-2用GSGF-6用NND因为红边波段对光谱保真度要求高但NND在红边波段的表現也不错GF-7用GS。批量融合的脚本可以用ENVI的Image Fusion工具配合Modeler。在Modeler里把RPC Orthorectification的输出作为Image Fusion的输入设置好融合方法、重采样方法、输出路径然后保存成.model文件。在Batch Processing里加载这个Modeler文件就可以批量跑了。4.3 融合后影像的快速质量检查方法批量融合最怕的是某景融合失败或者效果很差但你没发现最后交付时被甲方打回来。我通常会在融合完成后用ENVI的Quick Stats和Link Displays快速检查。具体做法是随机抽取5到10景融合结果同时打开融合影像和原始多光谱影像用Link Displays同步查看。重点看几个地方地物边缘有没有明显的锯齿或者模糊光谱有没有明显偏色阴影区域有没有异常亮斑。另外我写了一个简单的Python脚本自动计算每景融合影像的均值、标准差和信噪比SNR如果某景的SNR低于阈值比如30就标记出来人工检查。脚本核心逻辑是import numpy as np from envi import envi def check_fusion_quality(fusion_file): raster envi.open(fusion_file) data raster.load() # 计算每个波段的SNR snr_list [] for i in range(data.shape[2]): band data[:, :, i] mean np.mean(band) std np.std(band) snr mean / std if std ! 0 else 0 snr_list.append(snr) return snr_list这个脚本跑一遍两百景大概10分钟能快速筛出有问题的影像。5. 批量处理流程的工程化与性能优化5.1 用ENVI Modeler搭建可复用的处理链ENVI Modeler是批量处理的神器但很多人只用它做简单的单步操作。其实Modeler可以把辐射定标、大气校正、正射校正、融合、镶嵌全部串起来形成一个完整的处理链。我搭建的Modeler流程是这样的Input File读取原始MSS和PAN影像Radiometric Calibration对MSS和PAN分别定标FLAASH或QUAC对MSS做大气校正RPC Orthorectification对MSS和PAN分别正射校正Image Fusion融合MSS和PANSeamless Mosaic镶嵌多景融合影像Output File保存最终结果在Modeler里每个节点都可以设置参数而且支持条件分支。比如如果影像云量大于20%就跳过融合直接输出正射校正结果。这个功能在批量处理时非常实用可以避免有云的影像浪费计算资源。Modeler搭建完成后保存成.model文件。然后在Batch Processing里选择File Open Model加载这个文件再选择输入影像列表就可以批量跑了。我实测下来用Modeler跑两百景GF-2的全流程大概需要8到10个小时比手动操作快了几十倍。5.2 多进程并行处理的配置与资源分配ENVI的Batch Processing默认是单进程的一次只处理一景。如果你的机器配置不错比如32核64线程可以开启多进程并行处理。ENVI 5.6支持通过Preferences Batch Processing设置并行进程数。我一般设置为CPU核心数的一半比如32核就设16个进程。设太多反而会因为内存不足导致崩溃。内存分配也很关键。一景GF-2的0.8米融合影像大概2GB如果同时处理16景就需要32GB内存。我建议在Preferences Memory里把ENVI的最大内存占用设置为物理内存的70%左右。比如64GB内存设45GB。剩下的留给操作系统和其他软件。另外建议把输入输出数据放在SSD上不要放在机械硬盘或者网络盘上。我试过从网络盘读取影像结果批量处理时IO等待时间比计算时间还长。换成SSD后整体速度提升了40%左右。5.3 处理日志与异常中断的恢复策略批量处理最怕的是跑到一半中断比如某景影像损坏、磁盘满了、或者软件崩溃。我的做法是在Batch Processing里开启Write Log File每处理完一景就写一条日志。日志格式我自定义为时间戳 | 影像名 | 状态 | 耗时 | 错误信息。这样一旦中断可以快速定位到哪一景出了问题。恢复策略也很重要。我通常会把已经处理完的影像名记录在一个文本文件里重新跑的时候先读取这个文件跳过已处理的影像。具体实现可以用Python脚本import os def get_processed_files(log_file): processed set() if os.path.exists(log_file): with open(log_file, r) as f: for line in f: parts line.strip().split(|) if len(parts) 3 and parts[2].strip() SUCCESS: processed.add(parts[1].strip()) return processed def batch_process(input_dir, log_file): processed get_processed_files(log_file) all_files os.listdir(input_dir) for file in all_files: if file in processed: print(fSkipping {file}, already processed) continue try: # 执行处理 process_file(file) # 写日志 with open(log_file, a) as f: f.write(f{datetime.now()} | {file} | SUCCESS | 0s | \n) except Exception as e: with open(log_file, a) as f: f.write(f{datetime.now()} | {file} | FAILED | 0s | {str(e)}\n)这个脚本的核心是get_processed_files函数它从日志里读取已经成功的影像名然后在批量处理时跳过这些影像。我实测下来这个策略能节省大量重复处理时间。6. 常见问题与排查技巧实录6.1 定标与大气校正阶段的典型报错问题1FLAASH报错“Accelerator initialization failed”这个报错通常是因为FLAASH的加速器没有正确初始化。解决方法在ENVI的安装目录下找到flaash文件夹运行flaash_accelerator.exe重新初始化加速器。如果还是不行检查一下显卡驱动FLAASH的加速器依赖OpenCL显卡驱动太旧会导致初始化失败。问题2QUAC结果全黑或者全白QUAC对影像的DN值范围很敏感。如果影像的DN值范围是0到2558位数据QUAC会认为影像已经归一化了结果就会异常。解决方法先用Radiometric Calibration把DN值转成辐射亮度再做QUAC。或者用Stretch Data把DN值拉伸到0到10000之间。问题3GF-6红边波段定标系数读错GF-6的XML里定标系数是按波段顺序排列的但ENVI有时候会按照波段名称排序导致红边波段的系数错位。解决方法手动检查Radiometric Calibration里的Band Mapping确保波段顺序是Blue、Green、Red、NIR、RedEdge1、RedEdge2、RedEdge3、RedEdge4。6.2 融合与镶嵌环节的异常处理问题4融合后影像有明显的色偏这通常是因为全色和多光谱的辐射定标不一致。解决方法在融合之前先用Histogram Matching把全色影像的直方图匹配到多光谱影像的某个波段一般是近红外波段。ENVI的Image Fusion工具里有Histogram Matching选项勾选即可。问题5镶嵌时接边线明显GF-2和GF-6的幅宽不同镶嵌时接边线处理不好会有明显的痕迹。解决方法用Seamless Mosaic工具里的Color Correction功能先做全局色彩平衡再用Feathering做羽化。羽化宽度一般设为影像宽度的1%到2%。我试过GF-2镶嵌羽化宽度设50像素效果很好。问题6批量处理时内存溢出如果同时处理多景大影像内存溢出很常见。解决方法减少并行进程数或者把影像分块处理。ENVI的Preferences Memory里可以设置Tile Size把影像分成小块处理降低内存峰值。我一般设Tile Size为1024x1024。6.3 批量脚本调试与性能瓶颈定位批量脚本调试最头疼的是报错信息不明确。我的经验是在脚本里加详细的日志输出每一步都打印时间戳和状态。比如import time def process_file(file): start time.time() print(f[{time.strftime(%H:%M:%S)}] Start processing {file}) # 步骤1 step1_start time.time() # ... 执行步骤1 print(f[{time.strftime(%H:%M:%S)}] Step1 done, elapsed: {time.time()-step1_start:.2f}s) # 步骤2 step2_start time.time() # ... 执行步骤2 print(f[{time.strftime(%H:%M:%S)}] Step2 done, elapsed: {time.time()-step2_start:.2f}s) total time.time() - start print(f[{time.strftime(%H:%M:%S)}] Total elapsed: {total:.2f}s)这样一旦某一步耗时异常就能快速定位。我实测下来GF-2融合的瓶颈通常在Image Fusion这一步如果某景融合时间超过10分钟可能是全色和多光谱的几何配准有问题需要检查RPC校正的结果。性能瓶颈定位还可以用ENVI的Profiler工具。在Window Profiler里开启性能分析跑一景影像看看每个函数的耗时。我试过用Profiler分析发现FLAASH的Accelerator初始化占了总时间的30%后来把加速器预初始化整体速度提升了20%。6.4 常见问题速查表问题现象可能原因解决方法FLAASH报错“Accelerator initialization failed”加速器未初始化或显卡驱动旧运行flaash_accelerator.exe更新显卡驱动QUAC结果全黑DN值范围太小先做辐射定标或拉伸DN值GF-6红边波段定标系数错位波段顺序读错手动检查Band Mapping融合后色偏全色和多光谱定标不一致做Histogram Matching镶嵌接边线明显色彩不平衡用Seamless Mosaic的Color Correction和Feathering批量处理内存溢出并行进程太多减少进程数设置Tile Size某景处理时间异常长几何配准有问题检查RPC校正结果日志文件不写入未开启Write Log File在Batch Processing里勾选7. 一些实战中攒下来的经验批量处理这件事工具只是基础真正决定效率的是流程设计和细节把控。我踩过的坑包括一开始没做目录规范导致批量脚本遍历时读错文件FLAASH参数模板没按月份分组导致不同季节的影像校正结果不一致融合时没做直方图匹配导致镶嵌后色偏严重。这些坑每一个都让我多花了好几天时间。现在我的习惯是拿到数据先做一景全流程测试把参数调好保存模板再批量跑。批量跑的时候先跑5景看看效果没问题再全量跑。跑的过程中每隔一段时间检查一下日志和输出结果别等到跑完了才发现有问题。另外ENVI 5.6的Python API其实比IDL更灵活尤其是做批量处理时Python的glob、os、multiprocessing这些库能帮你省很多事。如果你还在用IDL写批量脚本建议试试Python上手快调试也方便。最后分享一个小技巧ENVI的Seamless Mosaic工具支持保存镶嵌模板你可以把接边线、色彩平衡、羽化参数都存成模板下次直接加载。我试过用同一个模板镶嵌不同区域的GF-2影像效果很稳基本不需要手动调整。
