修复步骤3去耀斑路径断层 + UI默认路径标准化

This commit is contained in:
DXC
2026-05-10 15:11:01 +08:00
parent f96c55f361
commit 8c7c995985
3 changed files with 111 additions and 49 deletions

View File

@ -18,6 +18,35 @@ from typing import Optional, List, Union, Callable
import numpy as np import numpy as np
def _safe_rename(src_bsq: str, src_hdr: str, dest_bsq: str, dest_hdr: str) -> str:
"""将底层硬编码生成的 .bsq + .hdr 文件对重命名到用户指定的 output_path
若 dest 路径已存在(可能是之前残留文件),先删除再移动,确保返回路径始终指向用户指定的文件。
Returns:
dest_bsq 路径
"""
src_bsq_p = Path(src_bsq)
src_hdr_p = Path(src_hdr)
dest_bsq_p = Path(dest_bsq)
dest_hdr_p = Path(dest_hdr)
if str(src_bsq_p.resolve()) == str(dest_bsq_p.resolve()):
return dest_bsq
if dest_bsq_p.exists():
os.remove(dest_bsq_p)
if dest_hdr_p.exists():
os.remove(dest_hdr_p)
if src_bsq_p.exists():
os.replace(src_bsq_p, dest_bsq_p)
if src_hdr_p.exists():
os.replace(src_hdr_p, dest_hdr_p)
return dest_bsq
class GlintRemovalStep: class GlintRemovalStep:
"""去除耀斑步骤""" """去除耀斑步骤"""
@ -67,6 +96,7 @@ class GlintRemovalStep:
deglint_dir: Union[str, Path] = "./3_deglint", deglint_dir: Union[str, Path] = "./3_deglint",
water_mask_dir: Union[str, Path] = "./1_water_mask", water_mask_dir: Union[str, Path] = "./1_water_mask",
callback: Optional[Callable] = None, callback: Optional[Callable] = None,
output_path: Optional[str] = None,
) -> str: ) -> str:
""" """
执行去除耀斑处理 执行去除耀斑处理
@ -186,12 +216,20 @@ class GlintRemovalStep:
# ==================== Kutser ==================== # ==================== Kutser ====================
if method == "kutser": if method == "kutser":
print(f"使用方法: Kutser (氧吸收波段={oxy_band}, NIR波段={nir_band})") print(f"使用方法: Kutser (氧吸收波段={oxy_band}, NIR波段={nir_band})")
output_path = str(deglint_dir / "deglint_kutser.bsq") hardcoded_bsq = str(deglint_dir / "deglint_kutser.bsq")
hardcoded_hdr = hardcoded_bsq.replace(".bsq", ".hdr")
# 将用户指定的 output_path 标准化为 .bsq 路径
if output_path:
final_bsq = output_path.replace('.dat', '.bsq').replace('.tif', '.bsq')
final_hdr = final_bsq.replace(".bsq", ".hdr")
else:
final_bsq = hardcoded_bsq
final_hdr = hardcoded_hdr
if Path(output_path).exists(): if Path(hardcoded_bsq).exists():
print(f"检测到已存在的去耀斑影像文件,直接使用: {output_path}") print(f"检测到已存在的去耀斑影像文件,直接使用: {hardcoded_bsq}")
notify("skipped", f"去耀斑影像已设置: {output_path}") notify("skipped", f"去耀斑影像已设置: {hardcoded_bsq}")
return output_path return _safe_rename(hardcoded_bsq, hardcoded_hdr, final_bsq, final_hdr)
kutser = Kutser( kutser = Kutser(
img_path, img_path,
@ -201,25 +239,33 @@ class GlintRemovalStep:
upper_oxy=upper_oxy, upper_oxy=upper_oxy,
NIR_band=nir_band, NIR_band=nir_band,
water_mask=mask_for_algorithm, water_mask=mask_for_algorithm,
output_path=output_path, output_path=hardcoded_bsq,
) )
kutser.get_corrected_bands() kutser.get_corrected_bands()
if Path(output_path).exists(): if Path(hardcoded_bsq).exists():
_copy_hdr_info(img_path, output_path) _copy_hdr_info(img_path, hardcoded_bsq)
notify("completed", f"去耀斑影像已生成: {output_path}") final = _safe_rename(hardcoded_bsq, hardcoded_hdr, final_bsq, final_hdr)
return output_path notify("completed", f"去耀斑影像已生成: {final}")
raise RuntimeError(f"Kutser算法未生成输出文件: {output_path}") return final
raise RuntimeError(f"Kutser算法未生成输出文件: {hardcoded_bsq}")
# ==================== Goodman ==================== # ==================== Goodman ====================
elif method == "goodman": elif method == "goodman":
print(f"使用方法: Goodman (NIR波段范围: {nir_lower}-{nir_upper})") print(f"使用方法: Goodman (NIR波段范围: {nir_lower}-{nir_upper})")
output_path = str(deglint_dir / "deglint_goodman.bsq") hardcoded_bsq = str(deglint_dir / "deglint_goodman.bsq")
hardcoded_hdr = hardcoded_bsq.replace(".bsq", ".hdr")
if output_path:
final_bsq = output_path.replace('.dat', '.bsq').replace('.tif', '.bsq')
final_hdr = final_bsq.replace(".bsq", ".hdr")
else:
final_bsq = hardcoded_bsq
final_hdr = hardcoded_hdr
if Path(output_path).exists(): if Path(hardcoded_bsq).exists():
print(f"检测到已存在的去耀斑影像文件,直接使用: {output_path}") print(f"检测到已存在的去耀斑影像文件,直接使用: {hardcoded_bsq}")
notify("skipped", f"去耀斑影像已设置: {output_path}") notify("skipped", f"去耀斑影像已设置: {hardcoded_bsq}")
return output_path return _safe_rename(hardcoded_bsq, hardcoded_hdr, final_bsq, final_hdr)
goodman = Goodman( goodman = Goodman(
img_path, img_path,
@ -228,48 +274,54 @@ class GlintRemovalStep:
A=goodman_A, A=goodman_A,
B=goodman_B, B=goodman_B,
water_mask=mask_for_algorithm, water_mask=mask_for_algorithm,
output_path=output_path, output_path=hardcoded_bsq,
) )
corrected_bands = goodman.get_corrected_bands() corrected_bands = goodman.get_corrected_bands()
if not Path(output_path).exists(): if not Path(hardcoded_bsq).exists():
_save_bands_as_image(corrected_bands, output_path, geotransform, projection) _save_bands_as_image(corrected_bands, hardcoded_bsq, geotransform, projection)
_copy_hdr_info(img_path, output_path) _copy_hdr_info(img_path, hardcoded_bsq)
else:
_copy_hdr_info(img_path, output_path)
del corrected_bands del corrected_bands
notify("completed", f"去耀斑影像已生成: {output_path}") final = _safe_rename(hardcoded_bsq, hardcoded_hdr, final_bsq, final_hdr)
return output_path notify("completed", f"去耀斑影像已生成: {final}")
return final
# ==================== Hedley ==================== # ==================== Hedley ====================
elif method == "hedley": elif method == "hedley":
print(f"使用方法: Hedley (NIR波段={hedley_nir_band})") print(f"使用方法: Hedley (NIR波段={hedley_nir_band})")
output_path = str(deglint_dir / "deglint_hedley.bsq") hardcoded_bsq = str(deglint_dir / "deglint_hedley.bsq")
hardcoded_hdr = hardcoded_bsq.replace(".bsq", ".hdr")
if output_path:
final_bsq = output_path.replace('.dat', '.bsq').replace('.tif', '.bsq')
final_hdr = final_bsq.replace(".bsq", ".hdr")
else:
final_bsq = hardcoded_bsq
final_hdr = hardcoded_hdr
if Path(output_path).exists(): if Path(hardcoded_bsq).exists():
print(f"检测到已存在的去耀斑影像文件,直接使用: {output_path}") print(f"检测到已存在的去耀斑影像文件,直接使用: {hardcoded_bsq}")
notify("skipped", f"去耀斑影像已设置: {output_path}") notify("skipped", f"去耀斑影像已设置: {hardcoded_bsq}")
return output_path return _safe_rename(hardcoded_bsq, hardcoded_hdr, final_bsq, final_hdr)
hedley = Hedley( hedley = Hedley(
img_path, img_path,
shp_path=None, shp_path=None,
NIR_band=hedley_nir_band, NIR_band=hedley_nir_band,
water_mask=mask_for_algorithm, water_mask=mask_for_algorithm,
output_path=output_path, output_path=hardcoded_bsq,
) )
hedley.get_corrected_bands() hedley.get_corrected_bands()
if Path(output_path).exists(): if Path(hardcoded_bsq).exists():
_copy_hdr_info(img_path, output_path) _copy_hdr_info(img_path, hardcoded_bsq)
notify("completed", f"去耀斑影像已生成: {output_path}") final = _safe_rename(hardcoded_bsq, hardcoded_hdr, final_bsq, final_hdr)
return output_path notify("completed", f"去耀斑影像已生成: {final}")
raise RuntimeError(f"Hedley算法未生成输出文件: {output_path}") return final
raise RuntimeError(f"Hedley算法未生成输出文件: {hardcoded_bsq}")
# ==================== SUGAR ==================== # ==================== SUGAR ====================
elif method == "sugar": elif method == "sugar":
# 方法名标准化
glint_method_raw = str(sugar_glint_mask_method).lower() glint_method_raw = str(sugar_glint_mask_method).lower()
if "cdf" in glint_method_raw or "累积" in glint_method_raw: if "cdf" in glint_method_raw or "累积" in glint_method_raw:
sugar_glint_mask_method_fixed = "cdf" sugar_glint_mask_method_fixed = "cdf"
@ -281,12 +333,19 @@ class GlintRemovalStep:
print( print(
f"使用方法: SUGAR (迭代次数={sugar_iter}, 掩膜方法={sugar_glint_mask_method_fixed})" f"使用方法: SUGAR (迭代次数={sugar_iter}, 掩膜方法={sugar_glint_mask_method_fixed})"
) )
output_path = str(deglint_dir / "deglint_sugar.bsq") hardcoded_bsq = str(deglint_dir / "deglint_sugar.bsq")
hardcoded_hdr = hardcoded_bsq.replace(".bsq", ".hdr")
if output_path:
final_bsq = output_path.replace('.dat', '.bsq').replace('.tif', '.bsq')
final_hdr = final_bsq.replace(".bsq", ".hdr")
else:
final_bsq = hardcoded_bsq
final_hdr = hardcoded_hdr
if Path(output_path).exists(): if Path(hardcoded_bsq).exists():
print(f"检测到已存在的去耀斑影像文件,直接使用: {output_path}") print(f"检测到已存在的去耀斑影像文件,直接使用: {hardcoded_bsq}")
notify("skipped", f"去耀斑影像已设置: {output_path}") notify("skipped", f"去耀斑影像已设置: {hardcoded_bsq}")
return output_path return _safe_rename(hardcoded_bsq, hardcoded_hdr, final_bsq, final_hdr)
if sugar_bounds is None: if sugar_bounds is None:
sugar_bounds = [(1, 2)] sugar_bounds = [(1, 2)]
@ -299,14 +358,15 @@ class GlintRemovalStep:
glint_mask_method=sugar_glint_mask_method_fixed, glint_mask_method=sugar_glint_mask_method_fixed,
termination_thresh=sugar_termination_thresh, termination_thresh=sugar_termination_thresh,
water_mask=mask_for_algorithm, water_mask=mask_for_algorithm,
output_path=output_path, output_path=hardcoded_bsq,
) )
if Path(output_path).exists(): if Path(hardcoded_bsq).exists():
_copy_hdr_info(img_path, output_path) _copy_hdr_info(img_path, hardcoded_bsq)
notify("completed", f"去耀斑影像已生成: {output_path}") final = _safe_rename(hardcoded_bsq, hardcoded_hdr, final_bsq, final_hdr)
return output_path notify("completed", f"去耀斑影像已生成: {final}")
raise RuntimeError(f"SUGAR算法未生成输出文件: {output_path}") return final
raise RuntimeError(f"SUGAR算法未生成输出文件: {hardcoded_bsq}")
else: else:
raise ValueError( raise ValueError(

View File

@ -532,6 +532,7 @@ class WaterQualityInversionPipeline:
sugar_glint_mask_method: str = "cdf", sugar_glint_mask_method: str = "cdf",
sugar_iter: Optional[int] = 3, sugar_iter: Optional[int] = 3,
sugar_termination_thresh: float = 20.0, sugar_termination_thresh: float = 20.0,
output_path: Optional[str] = None,
skip_dependency_check: bool = False) -> str: skip_dependency_check: bool = False) -> str:
"""步骤3: 去除耀斑Facade""" """步骤3: 去除耀斑Facade"""
step_start_time = time.time() step_start_time = time.time()
@ -575,6 +576,7 @@ class WaterQualityInversionPipeline:
deglint_dir=str(self.deglint_dir), deglint_dir=str(self.deglint_dir),
water_mask_dir=str(self.water_mask_dir), water_mask_dir=str(self.water_mask_dir),
callback=self._notify, callback=self._notify,
output_path=output_path,
) )
self.deglint_img_path = result self.deglint_img_path = result
step_end_time = time.time() step_end_time = time.time()

View File

@ -209,7 +209,7 @@ class Step3Panel(QWidget):
"输出影像:", "输出影像:",
"Image Files (*.bsq *.dat *.tif);;All Files (*.*)" "Image Files (*.bsq *.dat *.tif);;All Files (*.*)"
) )
self.output_file.line_edit.setPlaceholderText("deglint_image.dat") self.output_file.line_edit.setPlaceholderText("deglint_image.bsq")
layout.addWidget(self.output_file) layout.addWidget(self.output_file)
# 启用步骤 # 启用步骤
@ -301,7 +301,7 @@ class Step3Panel(QWidget):
if self.work_dir: if self.work_dir:
output_dir = os.path.join(self.work_dir, "3_deglint") output_dir = os.path.join(self.work_dir, "3_deglint")
os.makedirs(output_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True)
default_output_path = os.path.join(output_dir, "deglint_image.dat").replace('\\', '/') default_output_path = os.path.join(output_dir, "deglint_image.bsq").replace('\\', '/')
self.output_file.set_path(default_output_path) self.output_file.set_path(default_output_path)
else: else:
self.output_file.set_path("") self.output_file.set_path("")