上传文件至 /
This commit is contained in:
239
chla-model.py
Normal file
239
chla-model.py
Normal file
@ -0,0 +1,239 @@
|
||||
import argparse
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
|
||||
def find_nearest_bandnumber(wavelength, wavelengths):
|
||||
differences = np.abs(wavelengths - wavelength)
|
||||
min_position = np.argmin(differences)
|
||||
return int(min_position)
|
||||
|
||||
|
||||
def deglint(wavelengths, reflectance, start_wave=730, end_wave=750):
|
||||
"""去除水表耀光"""
|
||||
s = find_nearest_bandnumber(start_wave, wavelengths)
|
||||
e = find_nearest_bandnumber(end_wave, wavelengths)
|
||||
|
||||
glint = np.mean(reflectance[s:e + 1])
|
||||
deglinted_ref = reflectance - glint
|
||||
deglinted_ref[deglinted_ref < 0] = 0
|
||||
|
||||
return deglinted_ref
|
||||
|
||||
|
||||
def replace_non_valid_number(x):
|
||||
"""检查并替换无效数字"""
|
||||
if np.isnan(x) or np.isinf(x) or x < 0 or x > 65535:
|
||||
return 0.0
|
||||
return x
|
||||
|
||||
|
||||
def safe_divide(numerator, denominator, default_value=0.0):
|
||||
"""安全除法,避免除零错误"""
|
||||
if denominator == 0 or np.isnan(denominator) or np.isinf(denominator):
|
||||
return default_value
|
||||
return numerator / denominator
|
||||
|
||||
|
||||
def chl_a(wavelengths, reflectance):
|
||||
"""计算叶绿素a"""
|
||||
r651 = reflectance[find_nearest_bandnumber(651, wavelengths)]
|
||||
r707 = reflectance[find_nearest_bandnumber(707, wavelengths)]
|
||||
r670 = reflectance[find_nearest_bandnumber(670, wavelengths)]
|
||||
|
||||
denominator = safe_divide(r707 - r670, 1, default_value=1)
|
||||
content = 5.534 + 9.809 * (r651 - r707) / denominator
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def pc(wavelengths, reflectance):
|
||||
"""计算藻蓝素"""
|
||||
r620 = reflectance[find_nearest_bandnumber(620, wavelengths)]
|
||||
r665 = reflectance[find_nearest_bandnumber(665, wavelengths)]
|
||||
r709 = reflectance[find_nearest_bandnumber(709, wavelengths)]
|
||||
r778 = reflectance[find_nearest_bandnumber(778, wavelengths)] # 修正了波段索引
|
||||
|
||||
# 计算背景值bb
|
||||
bb_denom = safe_divide(0.082 - 0.6 * r778, 1, default_value=1)
|
||||
bb = 2.71 * 0.6 * r778 / bb_denom
|
||||
|
||||
# 计算叶绿素chl
|
||||
chl_denom = safe_divide(r665, 1, default_value=1)
|
||||
chl = (r709 / chl_denom * (0.727 + bb) - bb - 0.401) * (1 / 0.68)
|
||||
|
||||
# 计算藻蓝素
|
||||
pc_denom = safe_divide(r620, 1, default_value=1)
|
||||
content = (r709 / pc_denom * (0.727 + bb) - bb - 0.281) * (1 / 0.84) - 0.24 * chl
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def nh3(wavelengths, reflectance):
|
||||
"""计算氨氮"""
|
||||
band_500 = reflectance[find_nearest_bandnumber(500, wavelengths)]
|
||||
band_600 = reflectance[find_nearest_bandnumber(600, wavelengths)]
|
||||
band_850 = reflectance[find_nearest_bandnumber(850, wavelengths)]
|
||||
|
||||
ratio1 = safe_divide(band_500, band_850, default_value=1)
|
||||
ratio2 = safe_divide(band_600, band_500, default_value=1)
|
||||
|
||||
x13 = np.log(ratio1) if ratio1 > 0 else 0
|
||||
x23 = np.exp(ratio2)
|
||||
|
||||
content = 0.139 * x23 - 0.508 * x13 - 0.672
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def tn(wavelengths, reflectance):
|
||||
"""计算总氮"""
|
||||
band_500 = reflectance[find_nearest_bandnumber(500, wavelengths)]
|
||||
band_600 = reflectance[find_nearest_bandnumber(600, wavelengths)]
|
||||
band_850 = reflectance[find_nearest_bandnumber(850, wavelengths)]
|
||||
|
||||
ratio1 = safe_divide(band_500, band_850, default_value=1)
|
||||
ratio2 = safe_divide(band_600, band_500, default_value=1)
|
||||
|
||||
x13 = np.log(ratio1) if ratio1 > 0 else 0
|
||||
x23 = np.exp(ratio2)
|
||||
|
||||
content = 0.059 * x23 - 0.089 * x13 - 0.012
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def tp(wavelengths, reflectance):
|
||||
"""计算总磷"""
|
||||
band_440 = reflectance[find_nearest_bandnumber(440, wavelengths)]
|
||||
band_500 = reflectance[find_nearest_bandnumber(500, wavelengths)]
|
||||
band_800 = reflectance[find_nearest_bandnumber(800, wavelengths)]
|
||||
|
||||
ratio1 = safe_divide(band_500, band_440, default_value=1)
|
||||
ratio2 = safe_divide(band_500, band_800, default_value=1)
|
||||
|
||||
x12 = np.log(ratio1) if ratio1 > 0 else 0
|
||||
x17 = np.exp(ratio2)
|
||||
|
||||
content = 0.066 * x12 - 0.159 * x17 - 0.012
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def mno4(wavelengths, reflectance):
|
||||
"""计算高锰酸盐"""
|
||||
band_440 = reflectance[find_nearest_bandnumber(440, wavelengths)]
|
||||
band_500 = reflectance[find_nearest_bandnumber(500, wavelengths)]
|
||||
band_610 = reflectance[find_nearest_bandnumber(610, wavelengths)]
|
||||
band_800 = reflectance[find_nearest_bandnumber(800, wavelengths)]
|
||||
|
||||
x3 = safe_divide(band_500, band_440, default_value=1)
|
||||
x6 = safe_divide(band_610, band_800, default_value=1)
|
||||
|
||||
content = 1.13 * x3 - 1.29 * x6 - 5.95
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def tss(wavelengths, reflectance):
|
||||
"""计算总悬浮物"""
|
||||
band_490 = reflectance[find_nearest_bandnumber(490, wavelengths)]
|
||||
band_555 = reflectance[find_nearest_bandnumber(555, wavelengths)]
|
||||
band_670 = reflectance[find_nearest_bandnumber(670, wavelengths)]
|
||||
|
||||
x1 = band_555 + band_670
|
||||
x2 = safe_divide(band_490, band_555, default_value=1)
|
||||
|
||||
content_tmp = 0.58213 + 23.84071 * x1 - 0.48532 * x2
|
||||
content = np.exp(content_tmp)
|
||||
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def CDOM(wavelengths, reflectance):
|
||||
"""计算有色可溶性有机物"""
|
||||
band_560 = reflectance[find_nearest_bandnumber(560, wavelengths)]
|
||||
band_660 = reflectance[find_nearest_bandnumber(660, wavelengths)]
|
||||
|
||||
x1 = band_560 + band_660
|
||||
content = 40.75 * np.exp(-2.463 * x1)
|
||||
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def SD(wavelengths, reflectance):
|
||||
"""计算透明度"""
|
||||
band_440 = reflectance[find_nearest_bandnumber(440, wavelengths)]
|
||||
band_700 = reflectance[find_nearest_bandnumber(700, wavelengths)]
|
||||
|
||||
x1 = safe_divide(band_700, band_440, default_value=1)
|
||||
content = 1.17 * x1 - 27.43
|
||||
|
||||
return replace_non_valid_number(content)
|
||||
|
||||
|
||||
def process_spectral_file(input_csv_path, output_csv_path):
|
||||
# 读取CSV文件,第一行为列名
|
||||
df = pd.read_csv(input_csv_path)
|
||||
|
||||
# 提取波长数据(假设波长在列名中)
|
||||
# 跳过前18列非光谱数据,从第19列开始是光谱数据
|
||||
wavelength_columns = df.columns[1:]
|
||||
|
||||
# 将列名转换为浮点数(波长值)
|
||||
try:
|
||||
wavelengths = np.array([float(col) for col in wavelength_columns])
|
||||
except ValueError:
|
||||
# 如果列名不是数值,尝试从第一行获取波长值
|
||||
wavelengths = df.iloc[0, 1:].astype(float).values
|
||||
# 删除第一行(波长行)
|
||||
df = df.iloc[1:]
|
||||
|
||||
# 创建结果DataFrame
|
||||
results = {
|
||||
'timestamp': df.iloc[:, 0], # 假设时间戳在第一列
|
||||
'chl-a': [],
|
||||
'pc': [],
|
||||
'nh3': [],
|
||||
'tn': [],
|
||||
'tp': [],
|
||||
'mno4': [],
|
||||
'tss': [],
|
||||
'CDOM': [],
|
||||
'SD': []
|
||||
}
|
||||
|
||||
# 逐行处理数据
|
||||
for i, row in df.iterrows():
|
||||
# 提取反射率数据(第19列到最后一列)
|
||||
reflectance = row.iloc[1:].astype(float).values
|
||||
|
||||
# 去除水表耀光
|
||||
|
||||
deglinted_ref = reflectance
|
||||
# deglinted_ref = deglint(wavelengths, reflectance)
|
||||
|
||||
# 计算各项水质参数
|
||||
results['chl-a'].append(chl_a(wavelengths, deglinted_ref))
|
||||
results['pc'].append(pc(wavelengths, deglinted_ref))
|
||||
results['nh3'].append(nh3(wavelengths, deglinted_ref))
|
||||
results['tn'].append(tn(wavelengths, deglinted_ref))
|
||||
results['tp'].append(tp(wavelengths, deglinted_ref))
|
||||
results['mno4'].append(mno4(wavelengths, deglinted_ref))
|
||||
results['tss'].append(tss(wavelengths, deglinted_ref))
|
||||
results['CDOM'].append(CDOM(wavelengths, deglinted_ref))
|
||||
results['SD'].append(SD(wavelengths, deglinted_ref))
|
||||
|
||||
# 创建结果DataFrame并保存
|
||||
result_df = pd.DataFrame(results)
|
||||
result_df.to_csv(output_csv_path, index=False)
|
||||
print(f"结果已保存到 {output_csv_path}")
|
||||
#
|
||||
|
||||
input_csv_path = r"D:\WQ\zhanghuilai\hyperspectral-inversion\data\input\一代高光谱\2025-07-11_2025-07-21\筛选.csv"
|
||||
output_csv_path = r"D:\WQ\zhanghuilai\hyperspectral-inversion\data\input\一代高光谱\2025-07-11_2025-07-21/不去耀斑index.csv"
|
||||
process_spectral_file(input_csv_path, output_csv_path)
|
||||
|
||||
|
||||
#
|
||||
# if __name__ == "__main__":
|
||||
# parser = argparse.ArgumentParser(description='高光谱水质参数反演')
|
||||
# parser.add_argument('--input', type=str, required=True, help='输入CSV文件路径')
|
||||
# parser.add_argument('--output', type=str, required=True, help='输出CSV文件路径')
|
||||
# args = parser.parse_args()
|
||||
#
|
||||
# process_spectral_file(args.input, args.output)
|
Reference in New Issue
Block a user