import streamlit as st import numpy as np import laspy from sklearn.cluster import DBSCAN from sklearn.metrics import accuracy_score from scipy.spatial import ConvexHull from skimage.measure import profile_line st.title("Tree Analysis App") # Upload LAS file uploaded_file = st.file_uploader("Upload a LAS file", type=["las", "laz"]) if uploaded_file is not None: # Load the LAS file las_file = laspy.read(uploaded_file) height_filter = np.logical_and(las_file.z > 1, las_file.z < 30) las_file = las_file[height_filter] # Extract the x and y coordinates from the LAS file x = las_file.x y = las_file.y # Combine the x and y coordinates into a feature matrix feature_matrix = np.column_stack((x, y)) # Segment the trees using DBSCAN clustering with a specified distance threshold (e.g., 2 meters) tree_labels = DBSCAN(eps=2, min_samples=10).fit_predict(feature_matrix) # Count the number of trees num_trees = len(set(tree_labels)) - (1 if -1 in tree_labels else 0) st.write(f"Number of trees: {num_trees}") for i in range(num_trees): indices = np.where(tree_labels == i)[0] tree_x = x[indices] tree_y = y[indices] tree_mid_x = np.mean(tree_x) tree_mid_y = np.mean(tree_y) st.write(f"Tree {i+1} middle point: ({tree_mid_x:.3f}, {tree_mid_y:.3f})") def calculate_tree_data(points): height = np.max(points.z) - np.min(points.z) xy_points = np.column_stack((points.X, points.Y)) hull = ConvexHull(xy_points) crown_spread = np.sqrt(hull.area / np.pi)/10 z_trunk = np.percentile(points.z, 20) # assume trunk is the lowest 20% of the points trunk_points = points[points.z < z_trunk] dbh = 2 * np.mean(np.sqrt((trunk_points.X - np.mean(trunk_points.X)) ** 2 + (trunk_points.Y - np.mean(trunk_points.Y)) ** 2)) return height, crown_spread, dbh tree_data = [] for tree_label in range(num_trees): # Extract points for the current tree tree_points = las_file.points[tree_labels == tree_label] # Calculate tree data data = calculate_tree_data(tree_points) # Append data to list tree_data.append(data) # Print the data for each tree for i, data in enumerate(tree_data): st.write(f"Tree {i + 1} - Height: {data[0]:.3f} m, Crown Spread: {data[1]:.3f} m, DBH: {data[2]:.3f} mm")