refactor: 耀斑去除算法从波段索引驱动改造为波长驱动
- Kutser/Hedley/Goodman 的 __init__ 参数从硬编码波段号改为目标波长(nm) - 内部通过 find_band_number() 从 HDR 元数据动态解析波段索引 - Goodman 消除 P0 不一致: 25/37 vs 65/91 统一为 641.93/751.49nm - 彻底解除传感器耦合,任何传感器均可自动适配
This commit is contained in:
@ -9,6 +9,8 @@ except ImportError:
|
||||
GDAL_AVAILABLE = False
|
||||
print("警告: GDAL未安装,将使用numpy处理模式")
|
||||
|
||||
from src.utils.util import find_band_number
|
||||
|
||||
try:
|
||||
from tqdm import tqdm
|
||||
TQDM_AVAILABLE = True
|
||||
@ -44,19 +46,35 @@ def _find_water_row_ranges(water_rows):
|
||||
|
||||
|
||||
class Goodman:
|
||||
def __init__(self, im_aligned, NIR_lower = 25, NIR_upper = 37, A = 0.000019, B = 0.1,
|
||||
def __init__(self, im_aligned,
|
||||
nir_lower_wavelength=641.93, nir_upper_wavelength=751.49,
|
||||
A=0.000019, B=0.1,
|
||||
use_gdal=True, chunk_size=None, water_mask=None, output_path=None):
|
||||
"""
|
||||
:param im_aligned (np.ndarray or str): band aligned and calibrated & corrected reflectance image
|
||||
可以是numpy数组或GDAL可读取的文件路径
|
||||
:param NIR_lower (int): band index which corresponds to 641.93nm, closest band to 640nm
|
||||
:param NIR_upper (int): band index which corresponds to 751.49nm, closest band to 750nm
|
||||
:param A (float): the values in Goodman et al's paper, using AVIRIS reflectance (rather than radiance) data
|
||||
:param B (float): the values in Goodman et al's paper, using AVIRIS reflectance (rather than radiance) data
|
||||
see Goodman et al, which corrects each pixel independently. The NIR radiance is subtracted from the radiance at each wavelength,
|
||||
Goodman 耀斑去除算法 — 波长驱动版。
|
||||
|
||||
★ P0 修复:原算法类硬编码 NIR_lower=25/NIR_upper=37,GUI 硬编码 65/91,
|
||||
两套魔法数字对应不同传感器但指向相同物理波长(~640nm / ~750nm)。
|
||||
现已统一为波长参数,通过 find_band_number() 动态解析波段号,
|
||||
任何传感器均可自动适配,彻底消除不一致。
|
||||
|
||||
:param im_aligned (np.ndarray or str): band aligned and calibrated & corrected
|
||||
reflectance image。可以是numpy数组或GDAL可读取的文件路径。
|
||||
当为文件路径时,通过 HDR 元数据动态解析波段索引;
|
||||
当为numpy数组时,波长参数被视为直接波段索引(无 HDR 可查)。
|
||||
:param nir_lower_wavelength (float): NIR下界目标波长(nm),默认641.93nm
|
||||
(对应 ~640nm 参考波段,原硬编码 NIR_lower=25/65 指向的物理波长)
|
||||
:param nir_upper_wavelength (float): NIR上界目标波长(nm),默认751.49nm
|
||||
(对应 ~750nm 参考波段,原硬编码 NIR_upper=37/91 指向的物理波长)
|
||||
:param A (float): the values in Goodman et al's paper, using AVIRIS
|
||||
reflectance (rather than radiance) data
|
||||
:param B (float): the values in Goodman et al's paper, using AVIRIS
|
||||
reflectance (rather than radiance) data
|
||||
see Goodman et al, which corrects each pixel independently. The NIR
|
||||
radiance is subtracted from the radiance at each wavelength,
|
||||
but a wavelength-independent offset is also added.
|
||||
it is not clear how A and B were chosen, but an optimization for a case where in situ data is
|
||||
available would enable values to be found
|
||||
it is not clear how A and B were chosen, but an optimization for a
|
||||
case where in situ data is available would enable values to be found
|
||||
:param use_gdal (bool): 是否使用GDAL加速处理(需要GDAL可用且输入为文件路径或大数组)
|
||||
:param chunk_size (int): 已废弃,不再使用分块处理,改为逐波段处理
|
||||
:param water_mask (np.ndarray or str or None): 水域掩膜,1表示水域,0表示非水域
|
||||
@ -66,8 +84,6 @@ class Goodman:
|
||||
如果为None,则不保存
|
||||
"""
|
||||
self.im_aligned = im_aligned
|
||||
self.NIR_lower = NIR_lower
|
||||
self.NIR_upper = NIR_upper
|
||||
self.A = A
|
||||
self.B = B
|
||||
self.use_gdal = use_gdal and GDAL_AVAILABLE
|
||||
@ -75,6 +91,22 @@ class Goodman:
|
||||
self.is_file_path = isinstance(im_aligned, str)
|
||||
self.output_path = output_path
|
||||
|
||||
# ── 波长驱动:通过 HDR 元数据动态解析波段索引 ──
|
||||
if self.is_file_path:
|
||||
self.NIR_lower = find_band_number(
|
||||
float(nir_lower_wavelength), im_aligned)
|
||||
self.NIR_upper = find_band_number(
|
||||
float(nir_upper_wavelength), im_aligned)
|
||||
print(f"[Goodman] 波段解析: "
|
||||
f"NIR_lower={float(nir_lower_wavelength):.1f}nm→band{self.NIR_lower}, "
|
||||
f"NIR_upper={float(nir_upper_wavelength):.1f}nm→band{self.NIR_upper}")
|
||||
else:
|
||||
# numpy 数组模式:无 HDR 可查,直接作为波段索引(向后兼容)
|
||||
self.NIR_lower = int(nir_lower_wavelength)
|
||||
self.NIR_upper = int(nir_upper_wavelength)
|
||||
print(f"[Goodman] numpy数组模式: 直接使用波段索引 "
|
||||
f"NIR_lower={self.NIR_lower}, NIR_upper={self.NIR_upper}")
|
||||
|
||||
# 获取图像信息(需要在加载掩膜之前获取尺寸)
|
||||
if self.is_file_path:
|
||||
if not self.use_gdal:
|
||||
|
||||
@ -7,16 +7,22 @@ try:
|
||||
except ImportError:
|
||||
GDAL_AVAILABLE = False
|
||||
|
||||
from src.utils.util import find_band_number
|
||||
|
||||
|
||||
class Hedley:
|
||||
def __init__(self, img_path, shp_path=None, NIR_band=47, water_mask=None,
|
||||
output_path=None, block_size=1000):
|
||||
def __init__(self, img_path, shp_path=None, nir_wavelength=842.36,
|
||||
water_mask=None, output_path=None, block_size=1000):
|
||||
"""
|
||||
Hedley 耀斑去除算法 - 分块逐波段处理版本
|
||||
|
||||
波段选择已从硬编码索引改造为波长驱动:
|
||||
- 传入目标波长(nm),算法通过 find_band_number() 从影像 HDR 元数据中
|
||||
动态解析最接近的波段号,彻底解除传感器耦合。
|
||||
|
||||
:param img_path (str): 输入影像文件路径(GDAL可读取的格式)
|
||||
:param shp_path (str, optional): 深水区域shapefile,已废弃,请使用water_mask
|
||||
:param NIR_band (int): NIR波段索引(默认47,对应842.36nm)
|
||||
:param nir_wavelength (float): NIR参考波段目标波长(nm),默认842.36nm
|
||||
:param water_mask (np.ndarray or str or None): 水域掩膜
|
||||
:param output_path (str): 输出文件路径(必须提供,用于分块写入)
|
||||
:param block_size (int): 分块大小(默认1000)
|
||||
@ -25,7 +31,9 @@ class Hedley:
|
||||
raise ImportError("GDAL未安装,无法读取影像文件")
|
||||
|
||||
self.img_path = img_path
|
||||
self.NIR_band = int(float(NIR_band))
|
||||
# 波长驱动:通过 HDR 元数据动态解析波段索引
|
||||
self.NIR_band = find_band_number(float(nir_wavelength), img_path)
|
||||
print(f"[Hedley] 波段解析: NIR={float(nir_wavelength):.1f}nm→band{self.NIR_band}")
|
||||
self.water_mask = None
|
||||
self.water_mask_path = water_mask
|
||||
self.output_path = output_path
|
||||
|
||||
@ -7,20 +7,27 @@ try:
|
||||
except ImportError:
|
||||
GDAL_AVAILABLE = False
|
||||
|
||||
from src.utils.util import find_band_number
|
||||
|
||||
|
||||
class Kutser:
|
||||
def __init__(self, img_path, shp_path=None, oxy_band=38, lower_oxy=36,
|
||||
upper_oxy=49, NIR_band=47, water_mask=None, output_path=None,
|
||||
block_size=1000):
|
||||
def __init__(self, img_path, shp_path=None,
|
||||
oxy_wavelength=760.6, lower_wavelength=742.39,
|
||||
upper_wavelength=860.48, nir_wavelength=842.36,
|
||||
water_mask=None, output_path=None, block_size=1000):
|
||||
"""
|
||||
Kutser 耀斑去除算法 - 分块逐波段处理版本
|
||||
|
||||
波段选择已从硬编码索引改造为波长驱动:
|
||||
- 传入目标波长(nm),算法通过 find_band_number() 从影像 HDR 元数据中
|
||||
动态解析最接近的波段号,彻底解除传感器耦合。
|
||||
|
||||
:param img_path (str): 输入影像文件路径(GDAL可读取的格式)
|
||||
:param shp_path (str, optional): 深水区域shapefile,已废弃,请使用water_mask
|
||||
:param oxy_band (int): 氧吸收波段索引(默认38,对应760.6nm)
|
||||
:param lower_oxy (int): 氧吸收下方波段索引(默认36,对应742.39nm)
|
||||
:param upper_oxy (int): 氧吸收上方波段索引(默认49,对应860.48nm)
|
||||
:param NIR_band (int): NIR波段索引(默认47,对应842.36nm)
|
||||
:param oxy_wavelength (float): 氧吸收波段目标波长(nm),默认760.6nm(O₂-A带)
|
||||
:param lower_wavelength (float): 氧吸收左肩目标波长(nm),默认742.39nm
|
||||
:param upper_wavelength (float): 氧吸收右肩目标波长(nm),默认860.48nm
|
||||
:param nir_wavelength (float): NIR参考波段目标波长(nm),默认842.36nm
|
||||
:param water_mask (np.ndarray or str or None): 水域掩膜
|
||||
:param output_path (str): 输出文件路径(必须提供,用于分块写入)
|
||||
:param block_size (int): 分块大小(默认1000)
|
||||
@ -29,10 +36,17 @@ class Kutser:
|
||||
raise ImportError("GDAL未安装,无法读取影像文件")
|
||||
|
||||
self.img_path = img_path
|
||||
self.oxy_band = int(float(oxy_band))
|
||||
self.lower_oxy = int(float(lower_oxy))
|
||||
self.upper_oxy = int(float(upper_oxy))
|
||||
self.NIR_band = int(float(NIR_band))
|
||||
# 波长驱动:通过 HDR 元数据动态解析波段索引
|
||||
self.oxy_band = find_band_number(float(oxy_wavelength), img_path)
|
||||
self.lower_oxy = find_band_number(float(lower_wavelength), img_path)
|
||||
self.upper_oxy = find_band_number(float(upper_wavelength), img_path)
|
||||
self.NIR_band = find_band_number(float(nir_wavelength), img_path)
|
||||
|
||||
print(f"[Kutser] 波段解析: "
|
||||
f"oxy={float(oxy_wavelength):.1f}nm→band{self.oxy_band}, "
|
||||
f"lower={float(lower_wavelength):.1f}nm→band{self.lower_oxy}, "
|
||||
f"upper={float(upper_wavelength):.1f}nm→band{self.upper_oxy}, "
|
||||
f"NIR={float(nir_wavelength):.1f}nm→band{self.NIR_band}")
|
||||
self.water_mask = None # 延迟加载,在处理前初始化
|
||||
self.water_mask_path = water_mask
|
||||
self.output_path = output_path
|
||||
|
||||
Reference in New Issue
Block a user