| import streamlit as st |
| import cv2 |
| import numpy as np |
| import tensorflow as tf |
| from PIL import Image |
| import time |
|
|
| st.set_page_config(page_title="Lane Segmentation Dashboard", layout="wide") |
|
|
| |
| MODEL_PATH = "/app/model/1" |
|
|
|
|
| |
| @st.cache_resource |
| def load_model(): |
| model_layer = tf.keras.layers.TFSMLayer( |
| MODEL_PATH, |
| call_endpoint="serving_default" |
| ) |
|
|
| inputs = tf.keras.Input(shape=(256, 832, 3)) |
| outputs = model_layer(inputs) |
| model = tf.keras.Model(inputs=inputs, outputs=outputs) |
|
|
| return model |
|
|
| |
| def preprocess_image(image): |
| image = cv2.resize(image, (832, 256)) |
| return np.expand_dims(image.astype(np.float32) / 255.0, axis=0) |
|
|
|
|
| def process_image(image, model): |
| processed = preprocess_image(image) |
|
|
| prediction = model(processed, training=False) |
|
|
| if isinstance(prediction, dict): |
| prediction = list(prediction.values())[0] |
|
|
| prediction = prediction.numpy() |
|
|
| mask = (prediction[0] > 0.5).astype(np.uint8).squeeze() |
| mask = cv2.resize(mask, (image.shape[1], image.shape[0])) |
|
|
| return mask |
|
|
|
|
| |
| st.sidebar.header("Controls") |
|
|
| alpha = st.sidebar.slider("Overlay Intensity", 0.0, 1.0, 0.3) |
| threshold = st.sidebar.slider("Threshold", 0.1, 0.9, 0.5) |
| show_mask = st.sidebar.checkbox("Show Raw Mask") |
| show_metrics = st.sidebar.checkbox("Show Metrics", value=True) |
|
|
| |
| st.title("Lane Segmentation Dashboard") |
|
|
| model = load_model() |
|
|
| st.success("Model loaded successfully") |
|
|
|
|
| |
| uploaded_file = st.file_uploader( |
| "Upload image", |
| type=["jpg", "jpeg", "png"], |
| accept_multiple_files=False |
| ) |
|
|
| if uploaded_file is None: |
| st.info("Upload an image to begin") |
| st.stop() |
|
|
|
|
| |
| image = np.array(Image.open(uploaded_file).convert("RGB")) |
|
|
| if image.shape[0] > 1500 or image.shape[1] > 1500: |
| image = cv2.resize(image, (832, 256)) |
|
|
|
|
| |
| run = st.button("Run Lane Detection") |
|
|
| if not run: |
| st.image(image, caption="Uploaded Image", width="stretch") |
| st.stop() |
|
|
|
|
| |
| start = time.time() |
|
|
| mask = process_image(image, model) |
|
|
| end = time.time() |
| inference_time = (end - start) * 1000 |
|
|
|
|
| |
| mask = (mask > threshold).astype(np.uint8) |
|
|
| colored_mask = np.zeros_like(image) |
| colored_mask[mask == 1] = [0, 255, 0] |
|
|
| result = cv2.addWeighted(image, 1 - alpha, colored_mask, alpha, 0) |
|
|
|
|
| |
| lane_pixels = np.sum(mask) |
| total_pixels = mask.size |
| lane_coverage = (lane_pixels / total_pixels) * 100 |
| fps = 1000 / inference_time if inference_time > 0 else 0 |
|
|
|
|
| |
| col1, col2 = st.columns(2) |
|
|
| with col1: |
| st.subheader("Original") |
| st.image(image, width="stretch") |
|
|
| with col2: |
| st.subheader("Segmentation") |
| st.image(result, width="stretch") |
|
|
|
|
| |
| if show_mask: |
| st.subheader("Raw Mask") |
| st.image(mask * 255) |
|
|
|
|
| |
| if show_metrics: |
| st.subheader("Performance Metrics") |
|
|
| m1, m2, m3 = st.columns(3) |
|
|
| m1.metric("Inference Time (ms)", f"{inference_time:.2f}") |
| m2.metric("FPS", f"{fps:.2f}") |
| m3.metric("Lane Coverage (%)", f"{lane_coverage:.2f}") |