用 IDL 处理高分一号(GF-1 / GF-1B/C/D)数据

用 IDL 处理高分一号(GF-1 / GF-1B/C/D)数据

适用环境:

  • ENVI 6.1 + IDL 9.1
  • GeoScene 批处理扩展(Toolbox → Batch Processing)
  • 数据示例路径按本机实际目录书写,换机器时只改路径常量

本文代码来源:

  • NV5 官方帮助:ENVITaskENVITask::ParameterNamesENVITask::ExecuteENVICoordSysENVI()
  • 本机任务定义:
    • 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 官方帮助:ENVITaskENVITask::ParameterNamesENVITask::ExecuteENVICoordSysENVI()
  • 本机任务定义:
    • 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.htmENVITask::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. 建议的实际操作顺序

  1. 打开 ENVI 6.1 + IDL 9.1
  2. Preferences → Pyramids → Create Pyramid if None Exists = Never
  3. 编译并运行 run_rpc_one_scene,确认一景全色能出约 6 GB 结果
  4. 再运行 gf_rpc_batch_pan 补其余失败全色
  5. 新数据从 gf_radiometric_calgf_quac_mss → 正射,按目录分步跑
  6. 不要用 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.htmENVITask::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. 建议的实际操作顺序

  1. 打开 ENVI 6.1 + IDL 9.1
  2. Preferences → Pyramids → Create Pyramid if None Exists = Never
  3. 编译并运行 run_rpc_one_scene,确认一景全色能出约 6 GB 结果
  4. 再运行 gf_rpc_batch_pan 补其余失败全色
  5. 新数据从 gf_radiometric_calgf_quac_mss → 正射,按目录分步跑
  6. 不要用 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 小版本后先再打印一遍。

相关推荐
春涧草茶4 分钟前
慢就是快12-2三种访问权限|getter与setter|魔法方法
开发语言·python
無限進步D16 分钟前
Java Web 前端 简介
java·开发语言·前端·css·html·css3·web
qq_4017004136 分钟前
Qt QUrl 详解与代码示例
开发语言·数据库·qt
小灰灰搞电子1 小时前
Rust Attribute(属性标记)完整整理
开发语言·后端·rust
tedcloud1231 小时前
God‘s Eye View 怎么搭建?在云服务器上部署一个实时 3D 地球可视化平台
linux·服务器·开发语言·后端·rust
xx~t1 小时前
嵌入式——51单片机3
linux·c语言·嵌入式硬件·51单片机
Tairitsu_H2 小时前
[C++] C++11 Lambda与包装器深度解析
开发语言·c++·c++11·lambda·包装器
傲世仙尊2 小时前
从磁盘硬件到Ext文件系统-Linux磁盘级文件系统学习笔记
linux·运维·服务器·开发语言·c++
小羊没烦恼!2 小时前
Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?
java·开发语言·windows·算法·c#
黑马程序员毕设2 小时前
基于微信小程序的节目活动报名与管理系统设计与实现
java·开发语言·spring boot·后端·电脑