Spaces:
Sleeping
Sleeping
import gradio as gr | |
import math | |
import numpy as np | |
import cv2 | |
def calculate_flow_direction(dtm_file): | |
# Step 1: Read the DTM data and convert it to a 2D array of elevation values | |
elevation_array = cv2.imread(dtm_file.name, cv2.IMREAD_GRAYSCALE).astype(float) | |
# Step 2: Compute the slope and aspect of each cell in the DTM | |
cell_size = 0.1 # Set the cell size in meters | |
dx = dy = cell_size | |
# Compute the x and y gradient values | |
dzdx, dzdy = np.gradient(elevation_array, dx, dy) | |
# Compute the slope angle in radians | |
slope = np.arctan(np.sqrt(dzdx**2 + dzdy**2)) | |
# Compute the aspect angle in radians | |
aspect = np.arctan2(-dzdy, dzdx) | |
# Step 3: Compute the flow direction for each cell based on the slope and aspect values | |
# Compute the x and y components of the flow direction vector | |
flow_dir_x = np.sin(aspect) | |
flow_dir_y = np.cos(aspect) | |
# Normalize the flow direction vector to unit length | |
flow_dir_length = np.sqrt(flow_dir_x**2 + flow_dir_y**2) | |
flow_dir_x /= flow_dir_length | |
flow_dir_y /= flow_dir_length | |
# Step 4: Compute the flow accumulation for each cell based on the flow direction of neighboring cells | |
def compute_flow_accumulation(flow_dir_x, flow_dir_y): | |
# Initialize the flow accumulation array to zero | |
flow_accum = np.zeros_like(elevation_array) | |
# Find the cells with no upstream flow (i.e., cells with zero slope) | |
no_upstream_flow = (slope == 0) | |
flow_accum[no_upstream_flow] = 1 | |
# Recursively accumulate flow downstream | |
rows, cols = elevation_array.shape | |
for i in range(1, rows-1): | |
for j in range(1, cols-1): | |
if no_upstream_flow[i,j]: | |
continue | |
# Find the downstream cell | |
di = int(round(flow_dir_y[i,j])) | |
dj = int(round(flow_dir_x[i,j])) | |
downstream = (i+di, j+dj) | |
# Add the flow accumulation from the downstream cell | |
flow_accum[i,j] = flow_accum[downstream] + 1 | |
return flow_accum | |
# Step 5: Compute the flow accumulation and direction maps | |
flow_accum = compute_flow_accumulation(flow_dir_x, flow_dir_y) | |
flow_accum_norm = flow_accum / np.max(flow_accum) * 255 | |
flow_accum_rgb = cv2.cvtColor(flow_accum_norm.astype(np.uint8), cv2.COLOR_GRAY2RGB) | |
flow_dir_x_norm = (flow_dir_x + 1) / 2 * 255 | |
flow_dir_y_norm = (flow_dir_y + 1) / 2 * 255 | |
flow_dir_rgb = np.zeros((elevation_array.shape[0], elevation_array.shape[1], 3), dtype=np.uint8) | |
flow_dir_rgb[:,:,0] = flow_dir_x_norm.astype(np.uint8) | |
flow_dir_rgb[:,:,1] = flow_dir_y_norm.astype(np.uint8) | |
return flow_dir_rgb, flow_accum_rgb | |
# Define the Gradio interface | |
iface = gr.Interface( | |
fn=calculate_flow_direction, | |
inputs="file", | |
outputs=["image", "image"], | |
title="DTM Flow Direction and Accumulation Calculator", | |
description="This app calculates the flow direction and accumulation maps for a digital terrain model (DTM).", | |
) | |
# Launch the interface | |
iface.launch() |