Bootstrap

改进的ICESat-2冠层高度计算方法(基于ATL03数据)

代码目的

该代码的目的是为了更准确地从ICESat-2激光雷达数据中计算出冠层高度。它通过空间分段处理、异常值过滤、稳健统计方法以及后处理优化等步骤,来提高冠层高度计算的精确度和可靠性。

使用的方法

  • 空间分段处理:将数据按照固定距离分段,确保每个分段单独处理,避免远距离点之间的干扰。
  • 异常值处理:使用DBSCAN聚类算法识别和过滤异常值,对地面点和冠层点分别进行过滤,以排除不符合数据特征的点。
  • 稳健统计方法:使用修剪平均值(trim_mean)替代简单平均值来计算冠层和地面的高度,去除每个分段中最高和最低的一定比例的值,从而减少极端值对平均值的影响。
  • 后处理优化:应用中值滤波平滑结果,减少数据中的噪声,使结果更加平滑和稳定。

----------------------------------------------------------------更--------------------------------------------------------------这个改进版本采用了以下策略:

  1. 空间分段处理
    • 将数据按照固定距离(默认20米)分段
    • 确保每个分段单独处理,避免远距离点之间的干扰
  2. 异常值处理
    • 使用DBSCAN聚类识别和过滤异常值
    • 对地面点和冠层点分别进行过滤
  3. 稳健统计方法
    • 使用修剪平均值(trim_mean)替代简单平均值
    • 去除每个分段中最高和最低的10%的值
  4. 后处理优化
    • 应用中值滤波平滑结果
    • 计算每个分段的点数统计
  5. 输出更多统计信息
    • 每个分段的地面点和冠层点数量
    • 原始高度和平滑后的高度
    • 分段的位置信息

建议你可以尝试调整以下参数来优化结果

  1. segment_size:可以尝试15-30米的不同值
  2. DBSCANeps参数:可以根据数据特征调整
  3. trim_meanproportiontocut:可以在0.05-0.2之间调整
import pandas as pd
import numpy as np
from scipy.stats import trim_mean
from sklearn.cluster import DBSCAN

def calculate_improved_canopy_height(input_file, output_path, segment_size=20):
    """
    使用空间分段和稳健统计方法计算冠层高度
    
    参数:
    input_file: 输入文件路径
    output_path: 输出路径
    segment_size: 分段大小(米)
    """
    # 读取数据
    df = pd.read_csv(input_file)
    
    # 按照x_atc进行分段
    df['segment_id'] = (df['x_atc'] // segment_size).astype(int)
    
    results = []
    
    # 对每个分段进行处理
    for segment_id in df['segment_id'].unique():
        segment_data = df[df['segment_id'] == segment_id].copy()
        
        # 确保分段中同时存在地面点和冠层点
        ground_points = segment_data[segment_data['Classification'] == 1]
        canopy_points = segment_data[segment_data['Classification'] == 2]
        
        if len(ground_points) > 0 and len(canopy_points) > 0:
            # 使用DBSCAN识别和过滤异常值
            def filter_outliers(points):
                if len(points) < 2:
                    return points
                
                clustering = DBSCAN(eps=0.5, min_samples=2).fit(points[['Height']].values)
                return points[clustering.labels_ != -1]
            
            ground_points = filter_outliers(ground_points)
            canopy_points = filter_outliers(canopy_points)
            
            # 使用修剪平均值计算高度
            if len(ground_points) > 0 and len(canopy_points) > 0:
                ground_height = trim_mean(ground_points['Height'], proportiontocut=0.1)
                canopy_height = trim_mean(canopy_points['Height'], proportiontocut=0.1)
                
                # 计算段中心位置
                segment_center = segment_data['x_atc'].mean()
                center_lat = segment_data['Latitude'].mean()
                center_lon = segment_data['Longitude'].mean()
                
                results.append({
                    'segment_id': segment_id,
                    'x_atc': segment_center,
                    'Latitude': center_lat,
                    'Longitude': center_lon,
                    'ground_height': ground_height,
                    'canopy_height': canopy_height,
                    'canopy_relative_height': canopy_height - ground_height,
                    'n_ground_points': len(ground_points),
                    'n_canopy_points': len(canopy_points)
                })
    
    results_df = pd.DataFrame(results)
    
    # 应用中值滤波平滑结果
    results_df['smoothed_height'] = results_df['canopy_relative_height'].rolling(
        window=3, center=True, min_periods=1
    ).median()
    
    # 计算统计指标
    valid_heights = results_df['smoothed_height'].dropna()
    stats = {
        'mean_canopy_height': valid_heights.mean(),
        'median_canopy_height': valid_heights.median(),
        'std_canopy_height': valid_heights.std(),
        'num_segments': len(valid_heights)
    }
    
    # 保存结果
    results_df.to_csv(f"{output_path}/improved_canopy_heights.csv", index=False)
    
    return results_df, stats

# 使用示例
input_file = r" -------------------------"
output_path = r"-------------------------"

# 运行改进的算法
results, stats = calculate_improved_canopy_height(input_file, output_path, segment_size=20)

# 打印统计信息
print("\n改进后的统计信息:")
for key, value in stats.items():
    print(f"{key}: {value:.2f}")

;