增加坡度计算

This commit is contained in:
2026-04-22 09:27:59 +08:00
parent 4fd1b0a203
commit d563a56358
20 changed files with 4891 additions and 344 deletions

View File

@ -16,265 +16,57 @@ from Flexbrdf.hytools.masks import mask_create
warnings.filterwarnings("ignore")
np.seterr(divide='ignore', invalid='ignore')
# Default configuration values
DEFAULT_CONFIG = {
'file_type': 'envi',
'num_cpus': 16,
'bad_bands': [],
'corrections': [],
'resample': False,
'resampler': {'type': 'cubic', 'out_waves': []},
'export': {
'coeffs':True,
'image': True,
'masks': False,
'subset_waves': [],
'output_dir': './output/',
'suffix': 'BRDF'
},
'brdf': {
'type': 'flex',
'grouped': True,
'geometric': 'li_dense_r',
'volume': 'ross_thick',
'b/r': 2.5,
'h/b': 2.0,
'sample_perc': 0.1,
'interp_kind': 'linear',
'calc_mask': [
['water', {'band_1': 850, 'band_2': 660,"threshold": 290}],
['kernel_finite', {}],
['ancillary', {'name': 'sensor_zn', 'min': 0.03490658503988659, 'max': 'inf'}]
],
'apply_mask': [
['water', {'band_1': 850, 'band_2': 660,"threshold": 290}]
],
'bin_type': 'dynamic',
'num_bins': 18,
'ndvi_bin_min': 0.05,
'ndvi_bin_max': 1.0,
'ndvi_perc_min': 10,
'ndvi_perc_max': 95,
'solar_zn_type': 'scene'
},
# 'topo': {
# 'type': 'scs+c',
# 'calc_mask': [
# ['ndi', {'band_1': 850, 'band_2': 660, 'min': 0.05, 'max': 1.0}],
# ['kernel_finite', {}],
# ['ancillary', {'name': 'sensor_zn', 'min': 0.03490658503988659, 'max': 'inf'}]
# ],
# 'apply_mask': [
# ['ndi', {'band_1': 850, 'band_2': 660, 'min': 0.05, 'max': 1.0}]
# ],
# 'sample_perc': 0.1,
# 'subgrouped': False,
# 'subgroup': {}
# },
# 'glint': {
# 'type': 'hochberg',
# 'correction_band': 560,
# 'deep_water_sample': {},
# 'calc_mask': [
# ['ndi', {'band_1': 550, 'band_2': 2150, 'min': -1, 'max': 0}],
# ['kernel_finite', {}]
# ],
# 'apply_mask': [
# ['ndi', {'band_1': 550, 'band_2': 2150, 'min': -1, 'max': 0}]
# ]
# }
}
def build_config_from_args(args):
"""从命令行参数构建配置字典"""
# 自动发现输入文件
input_files = []
if os.path.isdir(args.input_dir):
# 支持的文件扩展名
extensions = ['.tif', '.tiff', '.envi', '.img', '.dat']
for file in os.listdir(args.input_dir):
if any(file.lower().endswith(ext) for ext in extensions):
input_files.append(os.path.join(args.input_dir, file))
else:
input_files = [args.input_dir] if os.path.isfile(args.input_dir) else []
if not input_files:
raise ValueError(f"No input files found in {args.input_dir}")
# 自动生成anc_files
anc_files = {}
for input_file in input_files:
base_name = os.path.splitext(os.path.basename(input_file))[0]
# 根据文件名模式生成对应的angles文件路径
# 例如: 2025_9_2_3_53_45_202592_35252_0_rad_geo_corrected_reflectance.dat
# 对应的angles文件: 2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo_registered_angles.bip
parts = base_name.split('_')
if len(parts) >= 9: # 确保有足够的parts
anc_base = f"{parts[0]}_{parts[1]}_{parts[2]}_{parts[3]}_{parts[4]}_{parts[5]}_{parts[6]}_{parts[7]}_{parts[8]}_rad_rgbxyz_geo_angles_registered"
# 确保路径分隔符统一使用反斜杠Windows
anc_dir_clean = args.anc_dir.replace('/', '\\')
anc_path = os.path.join(anc_dir_clean, anc_base + ".bip")
# 确保最终路径格式正确
anc_path = os.path.normpath(anc_path)
if os.path.exists(anc_path):
# 生成完整的anc_files字典结构
anc_files[input_file] = {
"path_length": [anc_path, 0],
"sensor_az": [anc_path, 9],
"sensor_zn": [anc_path, 8],
"solar_az": [anc_path, 7],
"solar_zn": [anc_path, 6],
"phase": [anc_path, 0],
"slope": [anc_path, 0],
"aspect": [anc_path, 0],
"cosine_i": [anc_path, 0],
"utc_time": [anc_path, 0]
}
else:
# 如果找不到对应的angles文件使用默认的obs文件
obs_path = os.path.join(args.anc_dir, base_name + "_obs")
if os.path.exists(obs_path):
anc_files[input_file] = obs_path
# 构建配置字典
config_dict = DEFAULT_CONFIG.copy()
config_dict.update({
'input_files': input_files,
'anc_files': anc_files,
'file_type': 'envi', # 假设都是ENVI格式
'num_cpus': args.num_cpus,
'bad_bands': args.bad_bands if args.bad_bands else [],
'corrections': args.corrections if args.corrections else [],
'export': {
'coeffs': args.export_coeffs,
'image': args.export_image,
'masks': args.export_masks,
'subset_waves': args.subset_waves if args.subset_waves else [],
'output_dir': args.output_dir,
'suffix': args.suffix
}
})
# 根据命令行参数更新BRDF配置
if 'brdf' in args.corrections:
brdf_config = config_dict['brdf'].copy()
if hasattr(args, 'brdf_type') and args.brdf_type:
brdf_config['type'] = args.brdf_type
if hasattr(args, 'grouped') and args.grouped is not None:
brdf_config['grouped'] = args.grouped
if hasattr(args, 'geometric') and args.geometric:
brdf_config['geometric'] = args.geometric
if hasattr(args, 'volume') and args.volume:
brdf_config['volume'] = args.volume
if hasattr(args, 'num_bins') and args.num_bins:
brdf_config['num_bins'] = args.num_bins
config_dict['brdf'] = brdf_config
# 根据命令行参数更新TOPO配置
if 'topo' in args.corrections:
topo_config = config_dict['topo'].copy()
if hasattr(args, 'topo_type') and args.topo_type:
topo_config['type'] = args.topo_type
config_dict['topo'] = topo_config
# 根据命令行参数更新Glint配置
if 'glint' in args.corrections:
glint_config = config_dict['glint'].copy()
if hasattr(args, 'glint_type') and args.glint_type:
glint_config['type'] = args.glint_type
config_dict['glint'] = glint_config
return config_dict
def main():
parser = argparse.ArgumentParser(description="High-resolution image correction with automatic configuration")
parser = argparse.ArgumentParser(description="FlexBRDF - 只接受JSON配置文件输入")
parser.add_argument('config', help='JSON配置文件路径 (例如: config.json)')
args = parser.parse_args()
# 检查配置文件是否存在
if not os.path.exists(args.config):
print(f"错误: 配置文件不存在: {args.config}")
sys.exit(1)
# 检查是否为JSON文件
if not args.config.endswith('.json'):
print("错误: 只接受JSON格式的配置文件")
sys.exit(1)
# 加载JSON配置
try:
with open(args.config, 'r', encoding='utf-8') as f:
config_dict = json.load(f)
except json.JSONDecodeError as e:
print(f"错误: JSON配置文件格式错误: {e}")
sys.exit(1)
except Exception as e:
print(f"错误: 无法读取配置文件: {e}")
sys.exit(1)
# 必需参数
parser.add_argument('input_dir', help='Input directory containing image files or single image file path')
parser.add_argument('anc_dir', help='Ancillary directory containing angle/obs files')
parser.add_argument('--output-dir', required=True, help='Output directory for corrected images')
# 验证必需的配置字段
required_fields = ['input_files', 'anc_files', 'corrections', 'export']
missing_fields = [f for f in required_fields if f not in config_dict]
if missing_fields:
print(f"错误: 配置文件缺少必需字段: {', '.join(missing_fields)}")
print("必需字段包括: input_files, anc_files, corrections, export")
sys.exit(1)
# 可选参数 - 基本设置
parser.add_argument('--num-cpus', type=int, default=16, help='Number of CPUs to use (default: 4)')
parser.add_argument('--bad-bands', nargs='*', type=int, default=[], help='Bad band indices to exclude')
# 校正类型
parser.add_argument('--corrections', nargs='*', choices=['topo', 'brdf', 'glint'],
default=['brdf'], help='Correction types to apply (default: brdf)')
# BRDF参数
parser.add_argument('--brdf-type', choices=['universal', 'flex'], default='flex',
help='BRDF correction type (default: flex)')
parser.add_argument('--grouped', action='store_true', default=True,
help='Group images for BRDF correction (default: True)')
parser.add_argument('--no-grouped', action='store_false', dest='grouped',
help='Do not group images for BRDF correction')
parser.add_argument('--geometric', default='li_dense_r',
choices=['li_sparse', 'li_dense', 'li_dense_r', 'roujean'],
help='Geometric kernel type (default: li_dense_r)')
parser.add_argument('--volume', default='ross_thick',
choices=['ross_thin', 'ross_thick', 'hotspot', 'roujean'],
help='Volume kernel type (default: ross_thick)')
parser.add_argument('--num-bins', type=int, default=18,
help='Number of NDVI bins for FlexBRDF (default: 18)')
# TOPO参数
parser.add_argument('--topo-type', default='scs+c',
choices=['scs', 'scs+c', 'c', 'cosine', 'mod_minneart'],
help='TOPO correction type (default: scs+c)')
# Glint参数
parser.add_argument('--glint-type', default='hochberg',
choices=['hochberg', 'gao', 'hedley'],
help='Glint correction type (default: hochberg)')
# 输出选项
parser.add_argument('--export-coeffs', action='store_true', default=True,
help='Export correction coefficients')
parser.add_argument('--export-image', action='store_true', default=True,
help='Export corrected images (default: True)')
parser.add_argument('--export-masks', action='store_true', default=True,
help='Export correction masks (default: True)')
parser.add_argument('--subset-waves', nargs='*', type=float, default=[],
help='Subset of wavelengths to export (empty for all)')
parser.add_argument('--suffix', default='corrected',
help='Suffix for output files (default: corrected)')
parser.add_argument('--output-config', type=str, default=None,
help='Output current configuration to JSON file')
# 向后兼容如果只有一个参数且是JSON文件则使用传统模式
if len(sys.argv) == 2 and sys.argv[1].endswith('.json'):
config_file = sys.argv[1]
with open(config_file, 'r') as outfile:
config_dict = json.load(outfile)
else:
args = parser.parse_args()
config_dict = build_config_from_args(args)
# 如果指定了输出配置选项则输出配置到JSON文件
if hasattr(args, 'output_config') and args.output_config:
print(f"Outputting configuration to {args.output_config}...")
# 重新排序配置字典以匹配期望的格式
ordered_config = {
"bad_bands": config_dict.get("bad_bands", []),
"file_type": config_dict.get("file_type", "envi"),
"input_files": config_dict.get("input_files", []),
"anc_files": config_dict.get("anc_files", {}),
"num_cpus": config_dict.get("num_cpus", 4),
"export": config_dict.get("export", {}),
"corrections": config_dict.get("corrections", []),
"brdf": config_dict.get("brdf", {}),
"topo": config_dict.get("topo", {}),
"glint": config_dict.get("glint", {}),
"resample": config_dict.get("resample", False),
"resampler": config_dict.get("resampler", {"type": "cubic", "out_waves": []})
}
with open(args.output_config, 'w', encoding='utf-8') as f:
json.dump(ordered_config, f, indent=2, ensure_ascii=False)
print("Configuration output complete.")
return # 如果只是输出配置,则退出程序
# 设置默认值
config_dict.setdefault('file_type', 'envi')
config_dict.setdefault('num_cpus', 16)
config_dict.setdefault('bad_bands', [])
config_dict.setdefault('resample', False)
config_dict.setdefault('resampler', {'type': 'cubic', 'out_waves': []})
print(f"=" * 60)
print(f"FlexBRDF 图像校正工具")
print(f"=" * 60)
print(f"配置文件: {args.config}")
print(f"输入文件数量: {len(config_dict['input_files'])}")
print(f"校正类型: {', '.join(config_dict['corrections'])}")
print(f"输出目录: {config_dict['export']['output_dir']}")
print(f"=" * 60)
print("Starting image correction process...")
total_start = time.time()

View File

@ -0,0 +1,167 @@
{
"input_files": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/rad2geo/R/2025_9_2_3_53_45_202592_35252_0_rad_geo_corrected_reflectance.dat",
"D:/BaiduNetdiskDownload/20250902/_3_52_52/rad2geo/R/2025_9_2_3_53_45_202592_35252_1_rad_geo_corrected_reflectance.dat"
],
"file_type": "envi",
"bad_bands": [],
"num_cpus": 2,
"anc_files": {
"D:/BaiduNetdiskDownload/20250902/_3_52_52/rad2geo/R/2025_9_2_3_53_45_202592_35252_0_rad_geo_corrected_reflectance.dat": {
"path_length": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
0
],
"sensor_az": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
9
],
"sensor_zn": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
8
],
"solar_az": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
7
],
"solar_zn": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
6
],
"phase": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
0
],
"slope": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
0
],
"aspect": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
0
],
"cosine_i": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
0
],
"utc_time": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo.bip_with_angles.bip",
0
]
},
"D:/BaiduNetdiskDownload/20250902/_3_52_52/rad2geo/R/2025_9_2_3_53_45_202592_35252_1_rad_geo_corrected_reflectance.dat": {
"path_length": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
0
],
"sensor_az": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
9
],
"sensor_zn": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
8
],
"solar_az": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
7
],
"solar_zn": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
6
],
"phase": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
0
],
"slope": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
0
],
"aspect": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
0
],
"cosine_i": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
0
],
"utc_time": [
"D:/BaiduNetdiskDownload/20250902/_3_52_52/BRDF/angle/test/2025_9_2_3_53_45_202592_35252_1_rad_rgbxyz_geo.bip_angles.bip",
0
]
}
},
"corrections": [
"brdf"
],
"topo": {
"type": "scs+c",
"calc_mask": [],
"apply_mask": [],
"c_fit_type": "nnls"
},
"brdf": {
"type": "flex",
"grouped": true,
"geometric": "li_dense_r",
"volume": "ross_thick",
"b/r": 2.5,
"h/b": 2.0,
"sample_perc": 0.1,
"interp_kind": "linear",
"calc_mask": [
[
"water",
{
"band_1": 850,
"band_2": 660,
"threshold": 290.0
}
],
[
"kernel_finite",
{}
],
[
"ancillary",
{
"name": "sensor_zn",
"min": 0.034907,
"max": 1000000.0
}
]
],
"apply_mask": [
[
"water",
{
"band_1": 850,
"band_2": 660,
"threshold": 290.0
}
]
],
"bin_type": "dynamic",
"num_bins": 18,
"ndvi_bin_min": 0.05,
"ndvi_bin_max": 1.0,
"ndvi_perc_min": 10,
"ndvi_perc_max": 95,
"solar_zn_type": "scene"
},
"glint": {
"type": "hochberg",
"correction_wave": 2150,
"apply_mask": []
},
"export": {
"coeffs": true,
"image": true,
"masks": true,
"subset_waves": [],
"output_dir": "E:/code/hytools-master/hytools-master/data/output",
"suffix": "brdf_glint"
},
"resample": false
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 KiB

View File

@ -0,0 +1,186 @@
基于 Flexbrdf/hytools/topo 目录下的代码,我来详细解释地形校正的原理。
地形校正原理详解
地形校正Topographic Correction的目的是消除地形起伏坡度、坡向对高光谱图像反射率的影响。由于太阳光入射角度在不同坡度和坡向上的变化同一地物在不同地形位置会呈现不同的辐射亮度地形校正就是要将这种差异归一化到水平地表的条件。
一、核心概念入射角余弦cosine i
地形校正的核心是计算入射角余弦cosine of incidence angle即太阳光线与地表法线之间夹角的余弦值。
计算公式(在 topo.py:53
cosine_i = np.cos(solar_zn)*np.cos(slope) + np.sin(solar_zn)*np.sin(slope)*np.cos(relative_az)
其中:
solar_zn太阳天顶角太阳光线与垂直方向的夹角
solar_az太阳方位角
slope地面坡度
aspect地面坡向
relative_az = aspect - solar_az相对方位角
物理意义:
当 cosine_i = 1 时,太阳光垂直照射地面(正午水平地表)
当 cosine_i < 1 太阳光斜射照度降低
背阴坡 cosine_i 较小向阳坡 cosine_i 较大
支持的5种地形校正方法
1. Cosine 校正余弦校正
原理最简单的地形校正方法假设地表为朗伯体各向同性反射)。
校正公式cosine.py:50
c_factor = cos_solar_zn / cos_i
cos_solar_zn水平地表的太阳天顶角余弦
cos_i实际地表的入射角余弦
校正效果
corrected_reflectance = original_reflectance × (cos_solar_zn / cos_i)
特点
简单快速
假设地表是理想朗伯体对非朗伯体如植被校正过度
2. SCS 校正Sun-Canopy-Sensor
原理考虑森林冠层对地形影响的简化模型基于 "cosine i" 但增加坡度因子
校正公式scs.py:51
c_factor = (cos_slope × cos_solar_zn) / cos_i
Cosine 方法的区别
增加了 cos_slope 坡度余弦
考虑了坡度对观测路径的影响
适用场景森林覆盖区域
3. C 校正C-Correction
原理 Cosine 校正基础上增加一个经验系数 C用于调整非朗伯体效应
校正公式c.py:177
correction_factor = (cos_sz + C) / (cosine_i + C)
其中 C 系数的计算过程c.py:42-76
对每个波段建立反射率与 cosine_i 的线性关系
ρ = slope × cos_i + intercept
通过最小二乘拟合OLS或非负最小二乘NNLS求解
计算 C 系数Soenen et al. 2005, Eq. 8
C = intercept / slope
物理意义C 值越大表示地表越接近朗伯体校正强度越接近 Cosine 方法C 值越小校正越保守
拟合方法选择c_fit_type
ols普通最小二乘Ordinary Least Squares
nnls非负最小二乘Non-Negative Least Squares
wls加权最小二乘Weighted Least Squares
4. SCS+C 校正推荐用于森林
原理结合 SCS C 校正的优势是目前森林地形校正的主流方法Soenen et al. 2005, IEEE TGRS)。
计算步骤scsc.py
计算 c1 因子
c1 = cos(solar_zn) × cos(slope)
计算 C 系数 C 校正相同通过线性回归
综合校正因子scsc.py:115-125
correction_factor = (c1 + C × cos_slope) / (cos_i + C)
为什么有效
SCS 部分处理冠层-地形几何关系
C 部分调整非朗伯体效应
相比单独使用 SCS C 校正能更好地保持植被反射率的一致性
5. Modified Minnaert 校正改进的 Minnaert
原理基于 Minnaert 指数的半经验方法区分植被和非植被区域进行不同强度的校正Richter et al. 2009)。
算法流程modminn.py:46-83
计算调整后的太阳天顶角
if solar_zn < 45°: solar_zn_t = solar_zn + 20°
if 45° solar_zn 55°: solar_zn_t = solar_zn + 15°
if solar_zn > 55°: solar_zn_t = solar_zn + 10°
NDVI 掩膜分类:
植被区NDVI > 0.2
非植被区NDVI ≤ 0.2
计算基础校正因子:
factor = cos_i / cos(solar_zn_t)
分区应用不同指数:
区域 短波(<720nm 长波(≥720nm
非植被
factor^(1/2)
factor^(1/2)
植被
factor^(3/4)
factor^(1/3)
限幅处理
factor = np.clip(factor, 0.25, 1.0)
阈值控制当入射角小于调整后的太阳天顶角时不进行校正
特点
自适应不同地物类型
区分短波和长波有不同的散射特性
通过指数控制校正强度避免过度校正
地形校正的工作流程
topo.py:104-154 可以看出地形校正的完整流程
1. 设置地形参数set_topo
2. 生成计算掩膜calc_mask
3. 计算校正系数calc_*_coeffs
- 遍历每个波段跳过坏波段
- 根据选定的算法类型计算校正因子
4. 应用校正apply_*
- 支持多种数据切分方式line/column/band/chunk/pixels
关键配置参数
参数 类型 说明 适用算法
type
str
校正算法类型
所有
calc_mask
list
计算校正系数的掩膜条件
所有
apply_mask
list
应用校正的掩膜条件
所有
c_fit_type
str
C系数拟合方法ols/nnls/wls
c, scs+c
sample_perc
float
采样比例用于分组计算
分组计算时
算法选择建议
场景 推荐算法 理由
裸土/岩石
Cosine C
地表接近朗伯体
森林植被
SCS+C
考虑冠层几何校正效果最好
草地/灌木
SCS
简单有效
混合地物
Modified Minnaert
自适应不同地物
需要精确结果
C SCS+C + 分组计算
按NDVI分组计算C系数
参考文献
SCS+C 方法Soenen, S. A., Peddle, D. R., & Coburn, C. A. (2005). SCS+C: A Modified Sun-Canopy-Sensor Topographic Correction in Forested Terrain. IEEE TGRS, 43(9), 2148-2159.
方法比较Richter, R., Kellenberger, T., & Kaufmann, H. (2009). Comparison of topographic correction methods. Remote Sensing, 1(3), 184-196.
C 校正Teillet, P. M., Guindon, B., & Goodenough, D. G. (1982). On the slope-aspect correction of multispectral scanner data. Canadian Journal of Remote Sensing, 8(2), 84-106.