Step6 波长读取:spectral 解析失败时增加 .hdr 文本暴力解析兜底,消灭 band_1 fallback

This commit is contained in:
DXC
2026-06-16 11:07:30 +08:00
parent d41262aa18
commit 03c788a16c

View File

@ -223,6 +223,73 @@ def get_hdr_file_path(file_path):
return os.path.splitext(file_path)[0] + ".hdr" return os.path.splitext(file_path)[0] + ".hdr"
def load_wavelength_columns(imgpath, num_bands):
"""
加载 wavelength 列名(鲁棒版:三级回退)
优先级:
1) spectral.envi.read_envi_header标准库解析依赖 ENVI 头完整性)
2) 纯文本暴力解析 .hdr兜底绕过 spectral 对 band names / 波段数一致性的校验)
—— 解决 .hdr 中 band names 数量与 bands 不符导致的标准库解析失败问题
3) 最后回退band_1, band_2, ..., band_N
Args:
imgpath: 影像文件路径(.bsq / .bil / .bip 等)
num_bands: 影像实际波段数(用于回退列名长度 & 不一致警告)
Returns:
spectral_columns: 长度为 num_bands 的字符串列表(与原代码列名格式一致:纯数字字符串)
"""
hdr_path = get_hdr_file_path(imgpath)
# 1) 标准库解析
try:
in_hdr_dict = spectral.envi.read_envi_header(hdr_path)
wavelengths = np.array(in_hdr_dict['wavelength']).astype('float64')
spectral_columns = [str(wl) for wl in wavelengths]
print(f"[wavelength] 标准库解析成功,从 {hdr_path} 提取 {len(spectral_columns)} 个波长")
if len(spectral_columns) != num_bands:
print(f"[wavelength] 警告: 解析波长数 ({len(spectral_columns)}) 与影像波段数 ({num_bands}) 不一致,将以 num_bands 为准截断/补齐")
if len(spectral_columns) > num_bands:
spectral_columns = spectral_columns[:num_bands]
elif len(spectral_columns) < num_bands:
spectral_columns = spectral_columns + [f"band_{j+1}" for j in range(len(spectral_columns), num_bands)]
return spectral_columns
except Exception as e_std:
print(f"[wavelength] 标准库解析失败: {str(e_std)},将尝试文本兜底解析")
# 2) 兜底:纯文本暴力解析
try:
if not os.path.isfile(hdr_path):
print(f"[wavelength] 文本兜底失败: {hdr_path} 不存在")
else:
with open(hdr_path, 'r', encoding='utf-8', errors='ignore') as f:
hdr_text = f.read()
pattern = r'wavelength\s*=\s*\{([^}]+)\}'
m = re.search(pattern, hdr_text, flags=re.IGNORECASE | re.DOTALL)
if m:
inner = m.group(1)
tokens = [t.strip() for t in inner.split(',') if t.strip()]
if tokens:
if len(tokens) != num_bands:
print(f"[wavelength] 文本解析波长数 ({len(tokens)}) 与影像波段数 ({num_bands}) 不一致,将以 num_bands 为准截断/补齐")
if len(tokens) > num_bands:
tokens = tokens[:num_bands]
elif len(tokens) < num_bands:
tokens = tokens + [f"band_{j+1}" for j in range(len(tokens), num_bands)]
print(f"[wavelength] 文本暴力解析成功,从 {hdr_path} 提取 {len(tokens)} 个真实波长")
return tokens
print(f"[wavelength] 文本兜底: 已匹配到 wavelength = {{ ... }},但内部为空")
else:
print(f"[wavelength] 文本兜底: 未在 {hdr_path} 中匹配到 wavelength = {{ ... }} 字段")
except Exception as e_txt:
print(f"[wavelength] 文本兜底解析异常: {str(e_txt)}")
# 3) 全部失败,最后回退
print(f"[wavelength] 所有解析路径均失败,回退到 band_1..band_{num_bands}")
return ["band_" + str(j + 1) for j in range(num_bands)]
def calculate_utm_zone(longitude): def calculate_utm_zone(longitude):
""" """
根据经度计算UTM分区号 根据经度计算UTM分区号
@ -759,17 +826,8 @@ def get_spectral_in_coor(imgpath, coorpath, outpath, radius=0, flare_path=None,
else: else:
original_columns = [] original_columns = []
# 读取波长信息,用作光谱列名 # 读取波长信息,用作光谱列名三级回退spectral 解析 → 文本暴力解析 → band_N 兜底)
wavelengths = None spectral_columns = load_wavelength_columns(imgpath, num_bands)
try:
in_hdr_dict = spectral.envi.read_envi_header(get_hdr_file_path(imgpath))
wavelengths = np.array(in_hdr_dict['wavelength']).astype('float64')
# 将波长值转换为字符串作为列名
spectral_columns = [str(wl) for wl in wavelengths]
print(f"成功读取波长信息,共 {len(spectral_columns)} 个波段")
except Exception as e:
print(f"警告: 无法读取波长信息 ({str(e)}),使用默认列名 band_1, band_2, ...")
spectral_columns = ["band_" + str(j + 1) for j in range(num_bands)]
# 构建输出列名不包含前两列坐标列和UTM列 # 构建输出列名不包含前两列坐标列和UTM列
all_columns = original_columns + spectral_columns all_columns = original_columns + spectral_columns