From 03c788a16cfda3728a7993a5c3bc3c2db36533be Mon Sep 17 00:00:00 2001 From: DXC Date: Tue, 16 Jun 2026 11:07:30 +0800 Subject: [PATCH] =?UTF-8?q?Step6=20=E6=B3=A2=E9=95=BF=E8=AF=BB=E5=8F=96?= =?UTF-8?q?=EF=BC=9Aspectral=20=E8=A7=A3=E6=9E=90=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E6=97=B6=E5=A2=9E=E5=8A=A0=20.hdr=20=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E6=9A=B4=E5=8A=9B=E8=A7=A3=E6=9E=90=E5=85=9C=E5=BA=95=EF=BC=8C?= =?UTF-8?q?=E6=B6=88=E7=81=AD=20band=5F1=20fallback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/glint_removal/get_spectral.py | 84 ++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 13 deletions(-) diff --git a/src/core/glint_removal/get_spectral.py b/src/core/glint_removal/get_spectral.py index b8ba79a..2edf0f2 100644 --- a/src/core/glint_removal/get_spectral.py +++ b/src/core/glint_removal/get_spectral.py @@ -213,16 +213,83 @@ def load_mask_file(mask_path): def get_hdr_file_path(file_path): """ 获取HDR文件路径 - + Args: file_path: 影像文件路径 - + Returns: 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): """ 根据经度计算UTM分区号 @@ -759,17 +826,8 @@ def get_spectral_in_coor(imgpath, coorpath, outpath, radius=0, flare_path=None, else: original_columns = [] - # 读取波长信息,用作光谱列名 - wavelengths = None - 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)] + # 读取波长信息,用作光谱列名(三级回退:spectral 解析 → 文本暴力解析 → band_N 兜底) + spectral_columns = load_wavelength_columns(imgpath, num_bands) # 构建输出列名(不包含前两列坐标列和UTM列) all_columns = original_columns + spectral_columns