Files
2025-07-22 10:28:35 +08:00

239 lines
8.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)