import streamlit as st import cv2 import numpy as np import matplotlib.pyplot as plt import pandas as pd import plotly.express as px from PIL import Image def analyze_crack(image): # Convert image to grayscale gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Edge detection edges = cv2.Canny(gray, 50, 150) # Finding contours contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Calculate crack metrics crack_data = [] for cnt in contours: length = cv2.arcLength(cnt, True) x, y, w, h = cv2.boundingRect(cnt) width = w severity = classify_crack(length, width) crack_data.append({"Length": length, "Width": width, "Severity": severity, "X": x, "Y": y}) return edges, crack_data def classify_crack(length, width): if length > 150 or width > 20: return "🔴 Major" elif length > 80 or width > 10: return "🟠 Moderate" else: return "🟢 Minor" def generate_description(severity): if "Major" in severity: return "🚨 This crack is classified as **Major**, indicating significant structural distress. Immediate intervention is required." elif "Moderate" in severity: return "⚠️ This crack is classified as **Moderate**. Monitoring and remedial measures should be considered." else: return "✅ This crack is **Minor** and likely due to surface shrinkage or thermal expansion. Periodic monitoring is recommended." def determine_structure_safety(crack_data): if not crack_data: return "✅ Structure is Safe", "green" major_count = sum(1 for crack in crack_data if "Major" in crack["Severity"]) moderate_count = sum(1 for crack in crack_data if "Moderate" in crack["Severity"]) if major_count > 0 or moderate_count > 3: return "🚨 Structure is NOT Safe", "red" return "⚠️ Structure Needs Monitoring", "orange" def main(): st.set_page_config(page_title='🏗️ Structural Integrity Analyst', layout='wide', initial_sidebar_state='expanded') st.markdown("

🏗️ Structural Integrity Analyst

", unsafe_allow_html=True) st.sidebar.header("📂 Upload Crack Image") uploaded_file = st.sidebar.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"]) if uploaded_file is not None: image = Image.open(uploaded_file) image = np.array(image) edges, crack_data = analyze_crack(image) # Determine Structural Safety structure_status, status_color = determine_structure_safety(crack_data) st.markdown(f"

{structure_status}

", unsafe_allow_html=True) # Organize layout col1, col2 = st.columns(2) with col1: st.subheader("📸 Uploaded Image") st.image(uploaded_file, caption="Uploaded Image", use_column_width=True) with col2: st.subheader("🔍 Processed Crack Detection") fig, ax = plt.subplots() ax.imshow(edges, cmap='gray') ax.axis("off") st.pyplot(fig) # Data Analysis data = pd.DataFrame(crack_data) if not data.empty: st.subheader("📊 Crack Metrics & Classification") st.dataframe(data.style.applymap(lambda val: 'background-color: #FFDDC1' if 'Major' in str(val) else ('background-color: #FFF3CD' if 'Moderate' in str(val) else 'background-color: #D4EDDA'))) # Description of Cracks st.subheader("📝 Crack Analysis & Recommendations") for _, row in data.iterrows(): st.markdown(f"**Crack at (X: {row['X']}, Y: {row['Y']})** - {generate_description(row['Severity'])}") # Visualization fig1 = px.histogram(data, x="Length", color="Severity", title="📏 Crack Length Distribution", nbins=10, color_discrete_map={"🔴 Major": "red", "🟠 Moderate": "orange", "🟢 Minor": "green"}) fig2 = px.histogram(data, x="Width", color="Severity", title="📐 Crack Width Distribution", nbins=10, color_discrete_map={"🔴 Major": "red", "🟠 Moderate": "orange", "🟢 Minor": "green"}) st.plotly_chart(fig1, use_container_width=True) st.plotly_chart(fig2, use_container_width=True) if __name__ == "__main__": main()