用 IDL 处理高分一号(GF-1 / GF-1B/C/D)数据
适用环境:
- ENVI 6.1 + IDL 9.1
- GeoScene 批处理扩展(Toolbox → Batch Processing)
- 数据示例路径按本机实际目录书写,换机器时只改路径常量
本文代码来源:
- NV5 官方帮助:
ENVITask、ENVITask::ParameterNames、ENVITask::Execute、ENVICoordSys、ENVI() - 本机任务定义:
E:\Program Files\NV5\ENVI61\custom_code\NEW_Batch_Processing\RadiometricCalibrationDuBatch.task...\QUACDuBatch.task...\RPCOrthorectificationDuBatch.task...\PanSharpeningDuBatch.task
不要和 NV5 自带任务搞混:
| 用途 | 正确任务名 | 不要用 |
|---|---|---|# 用 IDL 处理高分一号(GF-1 / GF-1B/C/D)数据
适用环境:
- ENVI 6.1 + IDL 9.1
- GeoScene 批处理扩展(Toolbox → Batch Processing)
- 数据示例路径按本机实际目录书写,换机器时只改路径常量
本文代码来源:
- NV5 官方帮助:
ENVITask、ENVITask::ParameterNames、ENVITask::Execute、ENVICoordSys、ENVI() - 本机任务定义:
E:\Program Files\NV5\ENVI61\custom_code\NEW_Batch_Processing\RadiometricCalibrationDuBatch.task...\QUACDuBatch.task...\RPCOrthorectificationDuBatch.task...\PanSharpeningDuBatch.task
不要和 NV5 自带任务搞混:
| 用途 | 正确任务名 | 不要用 |
|---|---|---|
| Toolbox 里的辐射定标 Batch | RadiometricCalibrationDuBatch |
RadiometricCalibration |
| Toolbox 里的 QUAC Batch | QUACDuBatch |
QUAC |
| Toolbox 里的 RPC 正射 Batch | RPCOrthorectificationDuBatch |
RPCOrthorectification |
自带任务参数是单数 INPUT_RASTER;GeoScene Batch 是数组 INPUT_RASTERS。
1. 在哪执行
启动:开始菜单 → ENVI 6.1 → ENVI 6.1 + IDL 9.1
提示符变成 ENVI> 后,ENVI 已经在跑。此时:
idl
e = ENVI()
返回的是当前会话,不会再开一套界面。
官方说明:ENVI.HEADLESS=1 可无界面启动。已经打开 ENVI 时不必再设。
有两种跑法。
1.1 IDL Console(一行一行敲)
适合试 3~5 行。不需要 PRO / END。
idl
e = ENVI()
PRINT, e.VERSION
PRINT, e.TASK_NAMES
1.2 .pro 程序(正式处理必须用这个)
.pro 必须写成:
idl
PRO 程序名
COMPILE_OPT IDL2
; 代码
END
文件名必须和程序名一致,例如 run_rpc_one_scene.pro 里只能是 PRO run_rpc_one_scene。
常见错误:
End of file encountered before end of program.
原因:把 Console 命令直接存进 .pro,没有 PRO / END。
运行:
idl
.run_rpc_one_scene
或打开文件后点绿色运行。改过代码再跑,先:
idl
.compile run_rpc_one_scene
run_rpc_one_scene
2. 官方 ENVITask 固定写法
来自 ENVITask.htm 和 ENVITask::Execute.htm。
idl
e = ENVI()
task = ENVITask('任务名')
; 查看参数(这是方法,不是属性)
PRINT, task.ParameterNames()
PRINT, task.Parameter('input_rasters')
; 赋值后执行
task.某参数 = 值
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err
核对参数必须用:
idl
names = task.ParameterNames()
PRINT, names
不要写 task.PARAMETER_NAMES,本机 ENVI 6.1 会报:
No parameter or property name matches PARAMETER_NAMES.
路径建议:
- 字符串里用正斜杠
'E:/data/a.dat' - 或用
PATH_SEP()拼接 - 不要写
'E:\data\a.dat',\a会被 IDL 当成转义
3. 高分一号数据约定
3.1 卫星和传感器后缀
| 卫星 / 相机 | 多光谱 | 全色 |
|---|---|---|
| GF1 PMS1 | -MSS1 |
-PAN1 |
| GF1 PMS2 | -MSS2 |
-PAN2 |
| GF1B / GF1C / GF1D | -MUX |
-PAN |
| GF6 PMS | -MUX |
-PAN |
筛选元数据 XML:
*-MSS1.xml;*-MSS2.xml;*-MUX.xml;*-PAN1.xml;*-PAN2.xml;*-PAN.xml
不要只写 MSS1 / PAN1,否则 GF1B/C/D 和 GF6 会漏掉。
3.2 推荐目录
按本机实际数据:
E:\xunlei\2026GF2m\need_process_data\
upfile\ 解压后的原始产品(tiff / xml / rpb)
GFbcd_result\ 辐射定标输出 *_rad.dat
quac\ 多光谱大气校正 *_quac.dat
rpcortho\ 正射 *_rpcortho.dat
need_rerun_pan_rpcortho\ 需要补跑的全色
DEM(已转成输出坐标系 EPSG:4536):
E:\ZL_data\xinjiang_12m_dem_extracted\fivecitydem_envi_4536.tif
不要用带 VERTCS["unknown"] 的 ArcGIS 裁剪结果 fivecitydem.tif,GeoScene 正射会报:
The DEM file does not have standard projection.
3.3 处理顺序
原始 XML/TIFF
→ 辐射定标(多光谱 + 全色) *_rad.dat
→ QUAC(只做多光谱) *_rad_quac.dat
→ RPC 正射
多光谱:用 *_rad_quac.dat
全色: 用 *_rad.dat(不做 QUAC)
→ (可选)融合
输出像元:
- 多光谱 8 m
- 全色 2 m
- 坐标系 EPSG:4536(CGCS2000 3 度带,中央经线 81°E)
- Grid Spacing 用 1000(任务默认是 10,不改会极慢)
4. 通用工具程序
先把下面存成:
C:\Users\hello\IDLWorkspace\Default\gf_envi_utils.pro
idl
PRO gf_envi_utils
; 空壳,真正用的是下面的函数。
END
FUNCTION gf_get_envi
COMPILE_OPT IDL2
e = ENVI(/CURRENT)
IF ~ISA(e, 'ENVI') THEN e = ENVI()
RETURN, e
END
FUNCTION gf_open_rasters, files
COMPILE_OPT IDL2
e = gf_get_envi()
n = N_ELEMENTS(files)
rasters = OBJARR(n)
FOR i=0, n-1 DO BEGIN
rasters[i] = e.OpenRaster(files[i])
ENDFOR
RETURN, rasters
END
FUNCTION gf_list_files, dir, pattern
COMPILE_OPT IDL2
files = FILE_SEARCH(dir, pattern, COUNT=n, /FOLD_CASE)
IF n EQ 0 THEN RETURN, !NULL
RETURN, files
END
FUNCTION gf_output_exists, outDir, inFile, postfix
COMPILE_OPT IDL2
name = FILE_BASENAME(inFile)
dot = STRPOS(name, '.', /REVERSE_SEARCH)
IF dot GT 0 THEN name = STRMID(name, 0, dot)
outFile = outDir + PATH_SEP() + name + postfix
RETURN, FILE_TEST(outFile)
END
使用前先编译:
idl
.compile gf_envi_utils
5. 步骤 0:确认任务已加载
idl
PRO check_gf_tasks
COMPILE_OPT IDL2
e = ENVI()
names = e.TASK_NAMES
PRINT, 'RadiometricCalibrationDuBatch in list? ', $
MAX(STRUPCASE(names) EQ 'RADIOMETRICCALIBRATIONDUBATCH')
PRINT, 'QUACDuBatch in list? ', $
MAX(STRUPCASE(names) EQ 'QUACDUBATCH')
PRINT, 'RPCOrthorectificationDuBatch in list? ', $
MAX(STRUPCASE(names) EQ 'RPCORTHORECTIFICATIONDUBATCH')
task = ENVITask('RPCOrthorectificationDuBatch')
PRINT, task.NAME
PRINT, task.ParameterNames()
END
三个都应打印非 0。若找不到任务,说明当前 ENVI 没加载
E:\Program Files\NV5\ENVI61\custom_code\NEW_Batch_Processing
界面 Toolbox 能看到 Batch,但 IDL 找不到时,重启 ENVI 6.1 + IDL 9.1。
6. 步骤 1:辐射定标
任务:RadiometricCalibrationDuBatch
本机参数:
| 参数 | 必填 | 推荐值 |
|---|---|---|
input_rasters |
是 | 元数据 XML 数组 |
calibration_type |
是 | 'Radiance' |
scale_factor |
是 | 1.0 |
output_data_type |
是 | 'Float' |
output_interleave |
是 | 'BIL' |
apply_flaash_settings |
是 | 0 |
output_postfix |
是 | '_rad.dat' |
display_result |
是 | 0 |
output_dir |
是 | 定标输出目录 |
输入用 XML,不要只用 tiff。GF 定标系数在 *-MSS1.xml / *-MUX.xml / *-PAN.xml 里。
idl
PRO gf_radiometric_cal
COMPILE_OPT IDL2
e = ENVI()
inDir = 'E:\xunlei\2026GF2m\need_process_data\upfile'
outDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result'
xmls = FILE_SEARCH(inDir, '*-MSS1.xml', COUNT=n1, /FOLD_CASE)
xmls = [xmls, FILE_SEARCH(inDir, '*-MSS2.xml', COUNT=n2, /FOLD_CASE)]
xmls = [xmls, FILE_SEARCH(inDir, '*-MUX.xml', COUNT=n3, /FOLD_CASE)]
xmls = [xmls, FILE_SEARCH(inDir, '*-PAN1.xml', COUNT=n4, /FOLD_CASE)]
xmls = [xmls, FILE_SEARCH(inDir, '*-PAN2.xml', COUNT=n5, /FOLD_CASE)]
xmls = [xmls, FILE_SEARCH(inDir, '*-PAN.xml', COUNT=n6, /FOLD_CASE)]
xmls = xmls[WHERE(xmls NE '', /NULL)]
n = N_ELEMENTS(xmls)
PRINT, 'XML count = ', n
IF n EQ 0 THEN MESSAGE, 'No metadata XML found'
rasters = OBJARR(n)
FOR i=0, n-1 DO rasters[i] = e.OpenRaster(xmls[i])
task = ENVITask('RadiometricCalibrationDuBatch')
task.INPUT_RASTERS = rasters
task.CALIBRATION_TYPE = 'Radiance'
task.SCALE_FACTOR = 1.0D
task.OUTPUT_DATA_TYPE = 'Float'
task.OUTPUT_INTERLEAVE = 'BIL'
task.APPLY_FLAASH_SETTINGS = 0
task.OUTPUT_POSTFIX = '_rad.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = outDir
err = ''
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err ELSE PRINT, '定标完成'
END
一次塞几十景可以,但更稳的是循环,一景失败不影响后面。循环版见第 10 节。
成功标志:GFbcd_result 里出现 *-MSS1_rad.dat / *-MUX_rad.dat / *-PAN_rad.dat 以及对应 .hdr。
7. 步骤 2:QUAC(只做多光谱)
任务:QUACDuBatch
全色不要做 QUAC。
本机参数:
| 参数 | 必填 | 推荐值 |
|---|---|---|
input_rasters |
是 | *_MSS*_rad.dat 或 *_MUX_rad.dat |
sensor |
是 | 'Generic / Unknown Sensor' |
output_postfix |
是 | '_quac.dat' |
display_result |
是 | 0 |
output_dir |
是 | ...\quac |
idl
PRO gf_quac_mss
COMPILE_OPT IDL2
e = ENVI()
inDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result'
outDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\quac'
files = FILE_SEARCH(inDir, '*-MUX_rad.dat', COUNT=n1, /FOLD_CASE)
files = [files, FILE_SEARCH(inDir, '*-MSS1_rad.dat', COUNT=n2, /FOLD_CASE)]
files = [files, FILE_SEARCH(inDir, '*-MSS2_rad.dat', COUNT=n3, /FOLD_CASE)]
files = files[WHERE(files NE '', /NULL)]
n = N_ELEMENTS(files)
PRINT, 'MSS rad count = ', n
IF n EQ 0 THEN MESSAGE, 'No MSS/MUX rad files'
rasters = OBJARR(n)
FOR i=0, n-1 DO rasters[i] = e.OpenRaster(files[i])
task = ENVITask('QUACDuBatch')
task.INPUT_RASTERS = rasters
task.SENSOR = 'Generic / Unknown Sensor'
task.OUTPUT_POSTFIX = '_quac.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = outDir
err = ''
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err ELSE PRINT, 'QUAC 完成'
END
成功标志:quac 目录里出现 *-MUX_rad_quac.dat(约几百 MB)。
SENSOR 必须是任务 CHOICE_LIST 里的字符串,不能自己改成 GF1。高分多光谱用 Generic 即可。
8. 步骤 3:RPC 正射
任务:RPCOrthorectificationDuBatch
本机 ParameterNames() 实测结果:
input_rasters
dem_raster
dem_is_height_above_ellipsoid
output_coordinate_system
output_mss_pixel_size
output_pan_pixel_size
resampling
grid_spacing
cut_edge_pixels
output_postfix
display_result
output_dir
output_rasters ; 输出,不要赋值
| 参数 | 必填 | 推荐值 |
|---|---|---|
input_rasters |
是 | 多光谱用 *_rad_quac.dat;全色用 *_rad.dat |
dem_raster |
否,但必须给 | fivecitydem_envi_4536.tif |
dem_is_height_above_ellipsoid |
否 | 0 |
output_coordinate_system |
否 | ENVICoordSys(COORD_SYS_CODE=4536) |
output_mss_pixel_size |
否 | 8 |
output_pan_pixel_size |
否 | 2 |
resampling |
否 | 'Bilinear' |
grid_spacing |
是 | 1000(默认 10,必须改) |
cut_edge_pixels |
是 | 10 |
output_postfix |
是 | '_rpcortho.dat' |
display_result |
是 | 0 |
output_dir |
是 | ...\rpcortho |
坐标系官方示例(ENVICoordSys.htm):
idl
CoordSys = ENVICoordSys(COORD_SYS_CODE=20354)
这里改成 4536。
8.1 先跑一景全色(推荐)
存为 run_rpc_one_scene.pro:
idl
PRO run_rpc_one_scene
COMPILE_OPT IDL2
e = ENVI()
inFile = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\' + $
'need_rerun_pan_rpcortho\' + $
'GF1C_PMS_E81.2_N44.6_20260630_L1A1022661246-PAN_rad.dat'
demFile = 'E:\ZL_data\xinjiang_12m_dem_extracted\fivecitydem_envi_4536.tif'
outDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\rpcortho'
IF ~FILE_TEST(inFile) THEN MESSAGE, '找不到输入: ' + inFile
IF ~FILE_TEST(demFile) THEN MESSAGE, '找不到 DEM: ' + demFile
raster = e.OpenRaster(inFile)
dem = e.OpenRaster(demFile)
coordSys = ENVICoordSys(COORD_SYS_CODE=4536)
PRINT, 'bands/cols/rows = ', raster.NBANDS, raster.NCOLUMNS, raster.NROWS
PRINT, coordSys
task = ENVITask('RPCOrthorectificationDuBatch')
task.INPUT_RASTERS = [raster]
task.DEM_RASTER = dem
task.DEM_IS_HEIGHT_ABOVE_ELLIPSOID = 0
task.OUTPUT_COORDINATE_SYSTEM = coordSys
task.OUTPUT_PAN_PIXEL_SIZE = 2D
task.OUTPUT_MSS_PIXEL_SIZE = 8D
task.RESAMPLING = 'Bilinear'
task.GRID_SPACING = 1000
task.CUT_EDGE_PIXELS = 10
task.OUTPUT_POSTFIX = '_rpcortho.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = outDir
PRINT, 'grid_spacing = ', task.GRID_SPACING
PRINT, 'display_result = ', task.DISPLAY_RESULT
err = ''
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err $
ELSE PRINT, '正射完成'
END
成功标志:
- Console 打印
正射完成 rpcortho里出现...1246-PAN_rad_rpcortho.dat- 全色大约 6 GB,不是 0 字节
输出已存在时,这个插件会失败:
The output URI already exists: ..._rpcortho.dat
Please sent this error message to duhj@geoscene.cn
先删同名 0 字节文件,或跳过已有结果。
8.2 批量正射(一景一个任务)
不要把 10 景全色一次塞进 INPUT_RASTERS 再靠 ENVI Server 并行。全色约 6 GB/景,多进程会把磁盘打满,worker 掉线后日志是:
Job was requeued due to a worker crash or loss of communication.
IDL 里顺序跑更稳。
idl
PRO gf_rpc_batch_pan
COMPILE_OPT IDL2
e = ENVI()
inDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\need_rerun_pan_rpcortho'
outDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\rpcortho'
demFile = 'E:\ZL_data\xinjiang_12m_dem_extracted\fivecitydem_envi_4536.tif'
files = FILE_SEARCH(inDir, '*-PAN_rad.dat', COUNT=n, /FOLD_CASE)
PRINT, 'PAN count = ', n
IF n EQ 0 THEN MESSAGE, 'No PAN rad files'
dem = e.OpenRaster(demFile)
coordSys = ENVICoordSys(COORD_SYS_CODE=4536)
FOR i=0, n-1 DO BEGIN
PRINT, '==== ', i+1, ' / ', n, ' ===='
PRINT, files[i]
base = FILE_BASENAME(files[i], '.dat')
outFile = outDir + PATH_SEP() + base + '_rpcortho.dat'
IF FILE_TEST(outFile) THEN BEGIN
info = FILE_INFO(outFile)
IF info.size GT 1000000 THEN BEGIN
PRINT, '已存在,跳过'
CONTINUE
ENDIF ELSE FILE_DELETE, outFile, /ALLOW_NONEXISTENT
ENDIF
CATCH, errCode
IF errCode NE 0 THEN BEGIN
CATCH, /CANCEL
PRINT, '失败: ', !ERROR_STATE.MSG
CONTINUE
ENDIF
raster = e.OpenRaster(files[i])
task = ENVITask('RPCOrthorectificationDuBatch')
task.INPUT_RASTERS = [raster]
task.DEM_RASTER = dem
task.OUTPUT_COORDINATE_SYSTEM = coordSys
task.OUTPUT_PAN_PIXEL_SIZE = 2D
task.OUTPUT_MSS_PIXEL_SIZE = 8D
task.RESAMPLING = 'Bilinear'
task.GRID_SPACING = 1000
task.CUT_EDGE_PIXELS = 10
task.OUTPUT_POSTFIX = '_rpcortho.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = outDir
task.Execute
PRINT, '完成 ', outFile
CATCH, /CANCEL
ENDFOR
END
多光谱正射把 inDir 改成 quac,模式改成 *-MUX_rad_quac.dat(GF1 再用 *-MSS1_rad_quac.dat)。
9. 步骤 4:可选,融合
任务:PanSharpeningDuBatch
输入要同时给低分辨率多光谱正射和高分辨率全色正射。参数:
| 参数 | 推荐值 |
|---|---|
input_rasters |
[mssOrtho, panOrtho] |
method |
'NNDiffuse Pan Sharpening' 或 'Gram-Schmidt Pan Sharpening' |
output_postfix |
'_sharpening.dat' |
display_result |
0 |
output_dir |
融合输出目录 |
idl
PRO gf_pansharp_one
COMPILE_OPT IDL2
e = ENVI()
mss = e.OpenRaster('E:\xunlei\2026GF2m\need_process_data\GFbcd_result\rpcortho\' + $
'GF1C_PMS_E81.2_N44.6_20260630_L1A1022661246-MUX_rad_quac_rpcortho.dat')
pan = e.OpenRaster('E:\xunlei\2026GF2m\need_process_data\GFbcd_result\rpcortho\' + $
'GF1C_PMS_E81.2_N44.6_20260630_L1A1022661246-PAN_rad_rpcortho.dat')
task = ENVITask('PanSharpeningDuBatch')
task.INPUT_RASTERS = [mss, pan]
task.METHOD = 'NNDiffuse Pan Sharpening'
task.OUTPUT_POSTFIX = '_sharpening.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\pansharp'
err = ''
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err ELSE PRINT, '融合完成'
END
注意:PanSharpening4ServerDuBatch 不接受 DISPLAY_RESULT,走 Server 时会报:
Keyword DISPLAY_RESULT not allowed in call to: PANSHARPENING4SERVERDUBATCH
IDL 顺序调用请用 PanSharpeningDuBatch。
10. 完整流水线(一景从定标到正射)
适合 GF1B/C/D:多光谱 -MUX,全色 -PAN。
idl
PRO gf_one_scene_pipeline, productDir, productId
COMPILE_OPT IDL2
e = ENVI()
work = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result'
radDir = work
quacDir = work + PATH_SEP() + 'quac'
orthoDir = work + PATH_SEP() + 'rpcortho'
demFile = 'E:\ZL_data\xinjiang_12m_dem_extracted\fivecitydem_envi_4536.tif'
muxXml = productDir + PATH_SEP() + productId + '-MUX.xml'
panXml = productDir + PATH_SEP() + productId + '-PAN.xml'
IF ~FILE_TEST(muxXml) THEN MESSAGE, '缺少 ' + muxXml
IF ~FILE_TEST(panXml) THEN MESSAGE, '缺少 ' + panXml
; --- 1 定标 ---
cal = ENVITask('RadiometricCalibrationDuBatch')
cal.INPUT_RASTERS = [e.OpenRaster(muxXml), e.OpenRaster(panXml)]
cal.CALIBRATION_TYPE = 'Radiance'
cal.SCALE_FACTOR = 1.0D
cal.OUTPUT_DATA_TYPE = 'Float'
cal.OUTPUT_INTERLEAVE = 'BIL'
cal.APPLY_FLAASH_SETTINGS = 0
cal.OUTPUT_POSTFIX = '_rad.dat'
cal.DISPLAY_RESULT = 0
cal.OUTPUT_DIR = radDir
cal.Execute
muxRad = radDir + PATH_SEP() + productId + '-MUX_rad.dat'
panRad = radDir + PATH_SEP() + productId + '-PAN_rad.dat'
; --- 2 QUAC 只做 MUX ---
quac = ENVITask('QUACDuBatch')
quac.INPUT_RASTERS = [e.OpenRaster(muxRad)]
quac.SENSOR = 'Generic / Unknown Sensor'
quac.OUTPUT_POSTFIX = '_quac.dat'
quac.DISPLAY_RESULT = 0
quac.OUTPUT_DIR = quacDir
quac.Execute
muxQuac = quacDir + PATH_SEP() + productId + '-MUX_rad_quac.dat'
; --- 3 正射 ---
dem = e.OpenRaster(demFile)
cs = ENVICoordSys(COORD_SYS_CODE=4536)
orthoMss = ENVITask('RPCOrthorectificationDuBatch')
orthoMss.INPUT_RASTERS = [e.OpenRaster(muxQuac)]
orthoMss.DEM_RASTER = dem
orthoMss.OUTPUT_COORDINATE_SYSTEM = cs
orthoMss.OUTPUT_MSS_PIXEL_SIZE = 8D
orthoMss.OUTPUT_PAN_PIXEL_SIZE = 2D
orthoMss.RESAMPLING = 'Bilinear'
orthoMss.GRID_SPACING = 1000
orthoMss.CUT_EDGE_PIXELS = 10
orthoMss.OUTPUT_POSTFIX = '_rpcortho.dat'
orthoMss.DISPLAY_RESULT = 0
orthoMss.OUTPUT_DIR = orthoDir
orthoMss.Execute
orthoPan = ENVITask('RPCOrthorectificationDuBatch')
orthoPan.INPUT_RASTERS = [e.OpenRaster(panRad)]
orthoPan.DEM_RASTER = dem
orthoPan.OUTPUT_COORDINATE_SYSTEM = cs
orthoPan.OUTPUT_MSS_PIXEL_SIZE = 8D
orthoPan.OUTPUT_PAN_PIXEL_SIZE = 2D
orthoPan.RESAMPLING = 'Bilinear'
orthoPan.GRID_SPACING = 1000
orthoPan.CUT_EDGE_PIXELS = 10
orthoPan.OUTPUT_POSTFIX = '_rpcortho.dat'
orthoPan.DISPLAY_RESULT = 0
orthoPan.OUTPUT_DIR = orthoDir
orthoPan.Execute
PRINT, '流水线完成: ', productId
END
调用:
idl
gf_one_scene_pipeline, $
'E:\xunlei\2026GF2m\need_process_data\upfile', $
'GF1C_PMS_E81.2_N44.6_20260630_L1A1022661246'
GF1 PMS1 把 -MUX / -PAN 换成 -MSS1 / -PAN1。
11. 执行前检查清单
跑 Execute 之前至少打印这些:
idl
PRINT, task.ParameterNames()
PRINT, task.GRID_SPACING
PRINT, task.DISPLAY_RESULT
PRINT, task.OUTPUT_DIR
PRINT, raster.NBANDS, raster.NCOLUMNS, raster.NROWS
PRINT, FILE_TEST(outDir, /DIRECTORY)
| 检查 | 正常 |
|---|---|
| 提示符 | ENVI> |
| 任务名 | RPCOrthorectificationDuBatch 等带 DuBatch |
| PAN 波段数 | 1 |
| MUX 波段数 | 4 |
GRID_SPACING |
1000 |
DISPLAY_RESULT |
0 / false |
| DEM | fivecitydem_envi_4536.tif,不是 fivecitydem.tif |
| 输出同名 dat | 不存在,或大于 1 MB |
12. 常见错误
| 现象 | 原因 | 处理 |
|---|---|---|
End of file encountered before end of program |
.pro 没有 PRO/END |
按第 1.2 节改 |
No parameter or property name matches PARAMETER_NAMES |
写成了属性 | 用 task.ParameterNames() |
Task not found |
没加载 GeoScene 扩展 | 用 ENVI 6.1 + IDL 9.1 启动 |
The DEM file does not have standard projection |
DEM 带 VERTCS["unknown"] |
用 fivecitydem_envi_4536.tif |
The output URI already exists |
同名输出已在 | 跳过或删 0 字节文件 |
worker crash or loss of communication |
多进程写大 PAN 把磁盘打满 | IDL 顺序跑,并发不要 8~10 |
| 磁盘 100%、CPU 很低 | 正射后自动建 .enp 金字塔 |
Preferences → Pyramids → Never |
| 正射极慢 | grid_spacing 仍是默认 10 |
设为 1000 |
| 漏 GF1 数据 | 筛选只用了 -MUX/-PAN |
加上 -MSS1 -MSS2 -PAN1 -PAN2 |
13. 建议的实际操作顺序
- 打开 ENVI 6.1 + IDL 9.1
- Preferences → Pyramids → Create Pyramid if None Exists = Never
- 编译并运行
run_rpc_one_scene,确认一景全色能出约 6 GB 结果 - 再运行
gf_rpc_batch_pan补其余失败全色 - 新数据从
gf_radiometric_cal→gf_quac_mss→ 正射,按目录分步跑 - 不要用 IDL 去调 ENVI Server 并行正射全色
14. 官方文档位置
本机:
E:\Program Files\NV5\ENVI61\IDL91\help\online_help\Subsystems\envi\Content\ExtendCustomize\
ENVITasks\ENVITask.htm
ENVITasks\ENVITask__ParameterNames.htm
ENVITasks\ENVITask__Execute.htm
ENVI Routine\ENVI.htm
ENVICoordSys\ENVICoordSys.htm
任务 JSON:
E:\Program Files\NV5\ENVI61\custom_code\NEW_Batch_Processing\
参数名以 task.ParameterNames() 在本机打印的结果为准。换 ENVI 小版本后先再打印一遍。
| Toolbox 里的辐射定标 Batch | RadiometricCalibrationDuBatch | RadiometricCalibration |
| Toolbox 里的 QUAC Batch | QUACDuBatch | QUAC |
| Toolbox 里的 RPC 正射 Batch | RPCOrthorectificationDuBatch | RPCOrthorectification |
自带任务参数是单数 INPUT_RASTER;GeoScene Batch 是数组 INPUT_RASTERS。
1. 在哪执行
启动:开始菜单 → ENVI 6.1 → ENVI 6.1 + IDL 9.1
提示符变成 ENVI> 后,ENVI 已经在跑。此时:
idl
e = ENVI()
返回的是当前会话,不会再开一套界面。
官方说明:ENVI.HEADLESS=1 可无界面启动。已经打开 ENVI 时不必再设。
有两种跑法。
1.1 IDL Console(一行一行敲)
适合试 3~5 行。不需要 PRO / END。
idl
e = ENVI()
PRINT, e.VERSION
PRINT, e.TASK_NAMES
1.2 .pro 程序(正式处理必须用这个)
.pro 必须写成:
idl
PRO 程序名
COMPILE_OPT IDL2
; 代码
END
文件名必须和程序名一致,例如 run_rpc_one_scene.pro 里只能是 PRO run_rpc_one_scene。
常见错误:
End of file encountered before end of program.
原因:把 Console 命令直接存进 .pro,没有 PRO / END。
运行:
idl
.run_rpc_one_scene
或打开文件后点绿色运行。改过代码再跑,先:
idl
.compile run_rpc_one_scene
run_rpc_one_scene
2. 官方 ENVITask 固定写法
来自 ENVITask.htm 和 ENVITask::Execute.htm。
idl
e = ENVI()
task = ENVITask('任务名')
; 查看参数(这是方法,不是属性)
PRINT, task.ParameterNames()
PRINT, task.Parameter('input_rasters')
; 赋值后执行
task.某参数 = 值
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err
核对参数必须用:
idl
names = task.ParameterNames()
PRINT, names
不要写 task.PARAMETER_NAMES,本机 ENVI 6.1 会报:
No parameter or property name matches PARAMETER_NAMES.
路径建议:
- 字符串里用正斜杠
'E:/data/a.dat' - 或用
PATH_SEP()拼接 - 不要写
'E:\data\a.dat',\a会被 IDL 当成转义
3. 高分一号数据约定
3.1 卫星和传感器后缀
| 卫星 / 相机 | 多光谱 | 全色 |
|---|---|---|
| GF1 PMS1 | -MSS1 |
-PAN1 |
| GF1 PMS2 | -MSS2 |
-PAN2 |
| GF1B / GF1C / GF1D | -MUX |
-PAN |
| GF6 PMS | -MUX |
-PAN |
筛选元数据 XML:
*-MSS1.xml;*-MSS2.xml;*-MUX.xml;*-PAN1.xml;*-PAN2.xml;*-PAN.xml
不要只写 MSS1 / PAN1,否则 GF1B/C/D 和 GF6 会漏掉。
3.2 推荐目录
按本机实际数据:
E:\xunlei\2026GF2m\need_process_data\
upfile\ 解压后的原始产品(tiff / xml / rpb)
GFbcd_result\ 辐射定标输出 *_rad.dat
quac\ 多光谱大气校正 *_quac.dat
rpcortho\ 正射 *_rpcortho.dat
need_rerun_pan_rpcortho\ 需要补跑的全色
DEM(已转成输出坐标系 EPSG:4536):
E:\ZL_data\xinjiang_12m_dem_extracted\fivecitydem_envi_4536.tif
不要用带 VERTCS["unknown"] 的 ArcGIS 裁剪结果 fivecitydem.tif,GeoScene 正射会报:
The DEM file does not have standard projection.
3.3 处理顺序
原始 XML/TIFF
→ 辐射定标(多光谱 + 全色) *_rad.dat
→ QUAC(只做多光谱) *_rad_quac.dat
→ RPC 正射
多光谱:用 *_rad_quac.dat
全色: 用 *_rad.dat(不做 QUAC)
→ (可选)融合
输出像元:
- 多光谱 8 m
- 全色 2 m
- 坐标系 EPSG:4536(CGCS2000 3 度带,中央经线 81°E)
- Grid Spacing 用 1000(任务默认是 10,不改会极慢)
4. 通用工具程序
先把下面存成:
C:\Users\hello\IDLWorkspace\Default\gf_envi_utils.pro
idl
PRO gf_envi_utils
; 空壳,真正用的是下面的函数。
END
FUNCTION gf_get_envi
COMPILE_OPT IDL2
e = ENVI(/CURRENT)
IF ~ISA(e, 'ENVI') THEN e = ENVI()
RETURN, e
END
FUNCTION gf_open_rasters, files
COMPILE_OPT IDL2
e = gf_get_envi()
n = N_ELEMENTS(files)
rasters = OBJARR(n)
FOR i=0, n-1 DO BEGIN
rasters[i] = e.OpenRaster(files[i])
ENDFOR
RETURN, rasters
END
FUNCTION gf_list_files, dir, pattern
COMPILE_OPT IDL2
files = FILE_SEARCH(dir, pattern, COUNT=n, /FOLD_CASE)
IF n EQ 0 THEN RETURN, !NULL
RETURN, files
END
FUNCTION gf_output_exists, outDir, inFile, postfix
COMPILE_OPT IDL2
name = FILE_BASENAME(inFile)
dot = STRPOS(name, '.', /REVERSE_SEARCH)
IF dot GT 0 THEN name = STRMID(name, 0, dot)
outFile = outDir + PATH_SEP() + name + postfix
RETURN, FILE_TEST(outFile)
END
使用前先编译:
idl
.compile gf_envi_utils
5. 步骤 0:确认任务已加载
idl
PRO check_gf_tasks
COMPILE_OPT IDL2
e = ENVI()
names = e.TASK_NAMES
PRINT, 'RadiometricCalibrationDuBatch in list? ', $
MAX(STRUPCASE(names) EQ 'RADIOMETRICCALIBRATIONDUBATCH')
PRINT, 'QUACDuBatch in list? ', $
MAX(STRUPCASE(names) EQ 'QUACDUBATCH')
PRINT, 'RPCOrthorectificationDuBatch in list? ', $
MAX(STRUPCASE(names) EQ 'RPCORTHORECTIFICATIONDUBATCH')
task = ENVITask('RPCOrthorectificationDuBatch')
PRINT, task.NAME
PRINT, task.ParameterNames()
END
三个都应打印非 0。若找不到任务,说明当前 ENVI 没加载
E:\Program Files\NV5\ENVI61\custom_code\NEW_Batch_Processing
界面 Toolbox 能看到 Batch,但 IDL 找不到时,重启 ENVI 6.1 + IDL 9.1。
6. 步骤 1:辐射定标
任务:RadiometricCalibrationDuBatch
本机参数:
| 参数 | 必填 | 推荐值 |
|---|---|---|
input_rasters |
是 | 元数据 XML 数组 |
calibration_type |
是 | 'Radiance' |
scale_factor |
是 | 1.0 |
output_data_type |
是 | 'Float' |
output_interleave |
是 | 'BIL' |
apply_flaash_settings |
是 | 0 |
output_postfix |
是 | '_rad.dat' |
display_result |
是 | 0 |
output_dir |
是 | 定标输出目录 |
输入用 XML,不要只用 tiff。GF 定标系数在 *-MSS1.xml / *-MUX.xml / *-PAN.xml 里。
idl
PRO gf_radiometric_cal
COMPILE_OPT IDL2
e = ENVI()
inDir = 'E:\xunlei\2026GF2m\need_process_data\upfile'
outDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result'
xmls = FILE_SEARCH(inDir, '*-MSS1.xml', COUNT=n1, /FOLD_CASE)
xmls = [xmls, FILE_SEARCH(inDir, '*-MSS2.xml', COUNT=n2, /FOLD_CASE)]
xmls = [xmls, FILE_SEARCH(inDir, '*-MUX.xml', COUNT=n3, /FOLD_CASE)]
xmls = [xmls, FILE_SEARCH(inDir, '*-PAN1.xml', COUNT=n4, /FOLD_CASE)]
xmls = [xmls, FILE_SEARCH(inDir, '*-PAN2.xml', COUNT=n5, /FOLD_CASE)]
xmls = [xmls, FILE_SEARCH(inDir, '*-PAN.xml', COUNT=n6, /FOLD_CASE)]
xmls = xmls[WHERE(xmls NE '', /NULL)]
n = N_ELEMENTS(xmls)
PRINT, 'XML count = ', n
IF n EQ 0 THEN MESSAGE, 'No metadata XML found'
rasters = OBJARR(n)
FOR i=0, n-1 DO rasters[i] = e.OpenRaster(xmls[i])
task = ENVITask('RadiometricCalibrationDuBatch')
task.INPUT_RASTERS = rasters
task.CALIBRATION_TYPE = 'Radiance'
task.SCALE_FACTOR = 1.0D
task.OUTPUT_DATA_TYPE = 'Float'
task.OUTPUT_INTERLEAVE = 'BIL'
task.APPLY_FLAASH_SETTINGS = 0
task.OUTPUT_POSTFIX = '_rad.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = outDir
err = ''
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err ELSE PRINT, '定标完成'
END
一次塞几十景可以,但更稳的是循环,一景失败不影响后面。循环版见第 10 节。
成功标志:GFbcd_result 里出现 *-MSS1_rad.dat / *-MUX_rad.dat / *-PAN_rad.dat 以及对应 .hdr。
7. 步骤 2:QUAC(只做多光谱)
任务:QUACDuBatch
全色不要做 QUAC。
本机参数:
| 参数 | 必填 | 推荐值 |
|---|---|---|
input_rasters |
是 | *_MSS*_rad.dat 或 *_MUX_rad.dat |
sensor |
是 | 'Generic / Unknown Sensor' |
output_postfix |
是 | '_quac.dat' |
display_result |
是 | 0 |
output_dir |
是 | ...\quac |
idl
PRO gf_quac_mss
COMPILE_OPT IDL2
e = ENVI()
inDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result'
outDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\quac'
files = FILE_SEARCH(inDir, '*-MUX_rad.dat', COUNT=n1, /FOLD_CASE)
files = [files, FILE_SEARCH(inDir, '*-MSS1_rad.dat', COUNT=n2, /FOLD_CASE)]
files = [files, FILE_SEARCH(inDir, '*-MSS2_rad.dat', COUNT=n3, /FOLD_CASE)]
files = files[WHERE(files NE '', /NULL)]
n = N_ELEMENTS(files)
PRINT, 'MSS rad count = ', n
IF n EQ 0 THEN MESSAGE, 'No MSS/MUX rad files'
rasters = OBJARR(n)
FOR i=0, n-1 DO rasters[i] = e.OpenRaster(files[i])
task = ENVITask('QUACDuBatch')
task.INPUT_RASTERS = rasters
task.SENSOR = 'Generic / Unknown Sensor'
task.OUTPUT_POSTFIX = '_quac.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = outDir
err = ''
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err ELSE PRINT, 'QUAC 完成'
END
成功标志:quac 目录里出现 *-MUX_rad_quac.dat(约几百 MB)。
SENSOR 必须是任务 CHOICE_LIST 里的字符串,不能自己改成 GF1。高分多光谱用 Generic 即可。
8. 步骤 3:RPC 正射
任务:RPCOrthorectificationDuBatch
本机 ParameterNames() 实测结果:
input_rasters
dem_raster
dem_is_height_above_ellipsoid
output_coordinate_system
output_mss_pixel_size
output_pan_pixel_size
resampling
grid_spacing
cut_edge_pixels
output_postfix
display_result
output_dir
output_rasters ; 输出,不要赋值
| 参数 | 必填 | 推荐值 |
|---|---|---|
input_rasters |
是 | 多光谱用 *_rad_quac.dat;全色用 *_rad.dat |
dem_raster |
否,但必须给 | fivecitydem_envi_4536.tif |
dem_is_height_above_ellipsoid |
否 | 0 |
output_coordinate_system |
否 | ENVICoordSys(COORD_SYS_CODE=4536) |
output_mss_pixel_size |
否 | 8 |
output_pan_pixel_size |
否 | 2 |
resampling |
否 | 'Bilinear' |
grid_spacing |
是 | 1000(默认 10,必须改) |
cut_edge_pixels |
是 | 10 |
output_postfix |
是 | '_rpcortho.dat' |
display_result |
是 | 0 |
output_dir |
是 | ...\rpcortho |
坐标系官方示例(ENVICoordSys.htm):
idl
CoordSys = ENVICoordSys(COORD_SYS_CODE=20354)
这里改成 4536。
8.1 先跑一景全色(推荐)
存为 run_rpc_one_scene.pro:
idl
PRO run_rpc_one_scene
COMPILE_OPT IDL2
e = ENVI()
inFile = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\' + $
'need_rerun_pan_rpcortho\' + $
'GF1C_PMS_E81.2_N44.6_20260630_L1A1022661246-PAN_rad.dat'
demFile = 'E:\ZL_data\xinjiang_12m_dem_extracted\fivecitydem_envi_4536.tif'
outDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\rpcortho'
IF ~FILE_TEST(inFile) THEN MESSAGE, '找不到输入: ' + inFile
IF ~FILE_TEST(demFile) THEN MESSAGE, '找不到 DEM: ' + demFile
raster = e.OpenRaster(inFile)
dem = e.OpenRaster(demFile)
coordSys = ENVICoordSys(COORD_SYS_CODE=4536)
PRINT, 'bands/cols/rows = ', raster.NBANDS, raster.NCOLUMNS, raster.NROWS
PRINT, coordSys
task = ENVITask('RPCOrthorectificationDuBatch')
task.INPUT_RASTERS = [raster]
task.DEM_RASTER = dem
task.DEM_IS_HEIGHT_ABOVE_ELLIPSOID = 0
task.OUTPUT_COORDINATE_SYSTEM = coordSys
task.OUTPUT_PAN_PIXEL_SIZE = 2D
task.OUTPUT_MSS_PIXEL_SIZE = 8D
task.RESAMPLING = 'Bilinear'
task.GRID_SPACING = 1000
task.CUT_EDGE_PIXELS = 10
task.OUTPUT_POSTFIX = '_rpcortho.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = outDir
PRINT, 'grid_spacing = ', task.GRID_SPACING
PRINT, 'display_result = ', task.DISPLAY_RESULT
err = ''
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err $
ELSE PRINT, '正射完成'
END
成功标志:
- Console 打印
正射完成 rpcortho里出现...1246-PAN_rad_rpcortho.dat- 全色大约 6 GB,不是 0 字节
输出已存在时,这个插件会失败:
The output URI already exists: ..._rpcortho.dat
Please sent this error message to duhj@geoscene.cn
先删同名 0 字节文件,或跳过已有结果。
8.2 批量正射(一景一个任务)
不要把 10 景全色一次塞进 INPUT_RASTERS 再靠 ENVI Server 并行。全色约 6 GB/景,多进程会把磁盘打满,worker 掉线后日志是:
Job was requeued due to a worker crash or loss of communication.
IDL 里顺序跑更稳。
idl
PRO gf_rpc_batch_pan
COMPILE_OPT IDL2
e = ENVI()
inDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\need_rerun_pan_rpcortho'
outDir = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\rpcortho'
demFile = 'E:\ZL_data\xinjiang_12m_dem_extracted\fivecitydem_envi_4536.tif'
files = FILE_SEARCH(inDir, '*-PAN_rad.dat', COUNT=n, /FOLD_CASE)
PRINT, 'PAN count = ', n
IF n EQ 0 THEN MESSAGE, 'No PAN rad files'
dem = e.OpenRaster(demFile)
coordSys = ENVICoordSys(COORD_SYS_CODE=4536)
FOR i=0, n-1 DO BEGIN
PRINT, '==== ', i+1, ' / ', n, ' ===='
PRINT, files[i]
base = FILE_BASENAME(files[i], '.dat')
outFile = outDir + PATH_SEP() + base + '_rpcortho.dat'
IF FILE_TEST(outFile) THEN BEGIN
info = FILE_INFO(outFile)
IF info.size GT 1000000 THEN BEGIN
PRINT, '已存在,跳过'
CONTINUE
ENDIF ELSE FILE_DELETE, outFile, /ALLOW_NONEXISTENT
ENDIF
CATCH, errCode
IF errCode NE 0 THEN BEGIN
CATCH, /CANCEL
PRINT, '失败: ', !ERROR_STATE.MSG
CONTINUE
ENDIF
raster = e.OpenRaster(files[i])
task = ENVITask('RPCOrthorectificationDuBatch')
task.INPUT_RASTERS = [raster]
task.DEM_RASTER = dem
task.OUTPUT_COORDINATE_SYSTEM = coordSys
task.OUTPUT_PAN_PIXEL_SIZE = 2D
task.OUTPUT_MSS_PIXEL_SIZE = 8D
task.RESAMPLING = 'Bilinear'
task.GRID_SPACING = 1000
task.CUT_EDGE_PIXELS = 10
task.OUTPUT_POSTFIX = '_rpcortho.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = outDir
task.Execute
PRINT, '完成 ', outFile
CATCH, /CANCEL
ENDFOR
END
多光谱正射把 inDir 改成 quac,模式改成 *-MUX_rad_quac.dat(GF1 再用 *-MSS1_rad_quac.dat)。
9. 步骤 4:可选,融合
任务:PanSharpeningDuBatch
输入要同时给低分辨率多光谱正射和高分辨率全色正射。参数:
| 参数 | 推荐值 |
|---|---|
input_rasters |
[mssOrtho, panOrtho] |
method |
'NNDiffuse Pan Sharpening' 或 'Gram-Schmidt Pan Sharpening' |
output_postfix |
'_sharpening.dat' |
display_result |
0 |
output_dir |
融合输出目录 |
idl
PRO gf_pansharp_one
COMPILE_OPT IDL2
e = ENVI()
mss = e.OpenRaster('E:\xunlei\2026GF2m\need_process_data\GFbcd_result\rpcortho\' + $
'GF1C_PMS_E81.2_N44.6_20260630_L1A1022661246-MUX_rad_quac_rpcortho.dat')
pan = e.OpenRaster('E:\xunlei\2026GF2m\need_process_data\GFbcd_result\rpcortho\' + $
'GF1C_PMS_E81.2_N44.6_20260630_L1A1022661246-PAN_rad_rpcortho.dat')
task = ENVITask('PanSharpeningDuBatch')
task.INPUT_RASTERS = [mss, pan]
task.METHOD = 'NNDiffuse Pan Sharpening'
task.OUTPUT_POSTFIX = '_sharpening.dat'
task.DISPLAY_RESULT = 0
task.OUTPUT_DIR = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result\pansharp'
err = ''
task.Execute, ERROR=err
IF err NE '' THEN PRINT, '失败: ', err ELSE PRINT, '融合完成'
END
注意:PanSharpening4ServerDuBatch 不接受 DISPLAY_RESULT,走 Server 时会报:
Keyword DISPLAY_RESULT not allowed in call to: PANSHARPENING4SERVERDUBATCH
IDL 顺序调用请用 PanSharpeningDuBatch。
10. 完整流水线(一景从定标到正射)
适合 GF1B/C/D:多光谱 -MUX,全色 -PAN。
idl
PRO gf_one_scene_pipeline, productDir, productId
COMPILE_OPT IDL2
e = ENVI()
work = 'E:\xunlei\2026GF2m\need_process_data\GFbcd_result'
radDir = work
quacDir = work + PATH_SEP() + 'quac'
orthoDir = work + PATH_SEP() + 'rpcortho'
demFile = 'E:\ZL_data\xinjiang_12m_dem_extracted\fivecitydem_envi_4536.tif'
muxXml = productDir + PATH_SEP() + productId + '-MUX.xml'
panXml = productDir + PATH_SEP() + productId + '-PAN.xml'
IF ~FILE_TEST(muxXml) THEN MESSAGE, '缺少 ' + muxXml
IF ~FILE_TEST(panXml) THEN MESSAGE, '缺少 ' + panXml
; --- 1 定标 ---
cal = ENVITask('RadiometricCalibrationDuBatch')
cal.INPUT_RASTERS = [e.OpenRaster(muxXml), e.OpenRaster(panXml)]
cal.CALIBRATION_TYPE = 'Radiance'
cal.SCALE_FACTOR = 1.0D
cal.OUTPUT_DATA_TYPE = 'Float'
cal.OUTPUT_INTERLEAVE = 'BIL'
cal.APPLY_FLAASH_SETTINGS = 0
cal.OUTPUT_POSTFIX = '_rad.dat'
cal.DISPLAY_RESULT = 0
cal.OUTPUT_DIR = radDir
cal.Execute
muxRad = radDir + PATH_SEP() + productId + '-MUX_rad.dat'
panRad = radDir + PATH_SEP() + productId + '-PAN_rad.dat'
; --- 2 QUAC 只做 MUX ---
quac = ENVITask('QUACDuBatch')
quac.INPUT_RASTERS = [e.OpenRaster(muxRad)]
quac.SENSOR = 'Generic / Unknown Sensor'
quac.OUTPUT_POSTFIX = '_quac.dat'
quac.DISPLAY_RESULT = 0
quac.OUTPUT_DIR = quacDir
quac.Execute
muxQuac = quacDir + PATH_SEP() + productId + '-MUX_rad_quac.dat'
; --- 3 正射 ---
dem = e.OpenRaster(demFile)
cs = ENVICoordSys(COORD_SYS_CODE=4536)
orthoMss = ENVITask('RPCOrthorectificationDuBatch')
orthoMss.INPUT_RASTERS = [e.OpenRaster(muxQuac)]
orthoMss.DEM_RASTER = dem
orthoMss.OUTPUT_COORDINATE_SYSTEM = cs
orthoMss.OUTPUT_MSS_PIXEL_SIZE = 8D
orthoMss.OUTPUT_PAN_PIXEL_SIZE = 2D
orthoMss.RESAMPLING = 'Bilinear'
orthoMss.GRID_SPACING = 1000
orthoMss.CUT_EDGE_PIXELS = 10
orthoMss.OUTPUT_POSTFIX = '_rpcortho.dat'
orthoMss.DISPLAY_RESULT = 0
orthoMss.OUTPUT_DIR = orthoDir
orthoMss.Execute
orthoPan = ENVITask('RPCOrthorectificationDuBatch')
orthoPan.INPUT_RASTERS = [e.OpenRaster(panRad)]
orthoPan.DEM_RASTER = dem
orthoPan.OUTPUT_COORDINATE_SYSTEM = cs
orthoPan.OUTPUT_MSS_PIXEL_SIZE = 8D
orthoPan.OUTPUT_PAN_PIXEL_SIZE = 2D
orthoPan.RESAMPLING = 'Bilinear'
orthoPan.GRID_SPACING = 1000
orthoPan.CUT_EDGE_PIXELS = 10
orthoPan.OUTPUT_POSTFIX = '_rpcortho.dat'
orthoPan.DISPLAY_RESULT = 0
orthoPan.OUTPUT_DIR = orthoDir
orthoPan.Execute
PRINT, '流水线完成: ', productId
END
调用:
idl
gf_one_scene_pipeline, $
'E:\xunlei\2026GF2m\need_process_data\upfile', $
'GF1C_PMS_E81.2_N44.6_20260630_L1A1022661246'
GF1 PMS1 把 -MUX / -PAN 换成 -MSS1 / -PAN1。
11. 执行前检查清单
跑 Execute 之前至少打印这些:
idl
PRINT, task.ParameterNames()
PRINT, task.GRID_SPACING
PRINT, task.DISPLAY_RESULT
PRINT, task.OUTPUT_DIR
PRINT, raster.NBANDS, raster.NCOLUMNS, raster.NROWS
PRINT, FILE_TEST(outDir, /DIRECTORY)
| 检查 | 正常 |
|---|---|
| 提示符 | ENVI> |
| 任务名 | RPCOrthorectificationDuBatch 等带 DuBatch |
| PAN 波段数 | 1 |
| MUX 波段数 | 4 |
GRID_SPACING |
1000 |
DISPLAY_RESULT |
0 / false |
| DEM | fivecitydem_envi_4536.tif,不是 fivecitydem.tif |
| 输出同名 dat | 不存在,或大于 1 MB |
12. 常见错误
| 现象 | 原因 | 处理 |
|---|---|---|
End of file encountered before end of program |
.pro 没有 PRO/END |
按第 1.2 节改 |
No parameter or property name matches PARAMETER_NAMES |
写成了属性 | 用 task.ParameterNames() |
Task not found |
没加载 GeoScene 扩展 | 用 ENVI 6.1 + IDL 9.1 启动 |
The DEM file does not have standard projection |
DEM 带 VERTCS["unknown"] |
用 fivecitydem_envi_4536.tif |
The output URI already exists |
同名输出已在 | 跳过或删 0 字节文件 |
worker crash or loss of communication |
多进程写大 PAN 把磁盘打满 | IDL 顺序跑,并发不要 8~10 |
| 磁盘 100%、CPU 很低 | 正射后自动建 .enp 金字塔 |
Preferences → Pyramids → Never |
| 正射极慢 | grid_spacing 仍是默认 10 |
设为 1000 |
| 漏 GF1 数据 | 筛选只用了 -MUX/-PAN |
加上 -MSS1 -MSS2 -PAN1 -PAN2 |
13. 建议的实际操作顺序
- 打开 ENVI 6.1 + IDL 9.1
- Preferences → Pyramids → Create Pyramid if None Exists = Never
- 编译并运行
run_rpc_one_scene,确认一景全色能出约 6 GB 结果 - 再运行
gf_rpc_batch_pan补其余失败全色 - 新数据从
gf_radiometric_cal→gf_quac_mss→ 正射,按目录分步跑 - 不要用 IDL 去调 ENVI Server 并行正射全色
14. 官方文档位置
本机:
E:\Program Files\NV5\ENVI61\IDL91\help\online_help\Subsystems\envi\Content\ExtendCustomize\
ENVITasks\ENVITask.htm
ENVITasks\ENVITask__ParameterNames.htm
ENVITasks\ENVITask__Execute.htm
ENVI Routine\ENVI.htm
ENVICoordSys\ENVICoordSys.htm
任务 JSON:
E:\Program Files\NV5\ENVI61\custom_code\NEW_Batch_Processing\
参数名以 task.ParameterNames() 在本机打印的结果为准。换 ENVI 小版本后先再打印一遍。