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. Major cracks can compromise the integrity of the structure and require **immediate intervention**. These are typically caused by foundation settlement, excessive load, or material failure. **Professional assessment is advised.**"
elif "Moderate" in severity:
return "⚠️ This crack is classified as **Moderate**. While not immediately critical, it suggests progressive structural movement or material fatigue. **Monitoring and remedial measures**, such as crack sealing or reinforcement, should be considered."
else:
return "✅ This crack is **Minor** and likely due to **surface shrinkage or thermal expansion**. While not structurally concerning, periodic monitoring is recommended to ensure it does not propagate further."
def main():
st.set_page_config(page_title='🏗️ Structural Integrity Analyst', layout='wide', initial_sidebar_state='expanded')
# Custom Styling
st.markdown(
"""
""", unsafe_allow_html=True
)
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)
# Organize layout
col1, col2 = st.columns(2)
with col1:
st.markdown("", unsafe_allow_html=True)
st.image(uploaded_file, caption="Uploaded Image", use_column_width=True)
with col2:
st.markdown("", unsafe_allow_html=True)
fig, ax = plt.subplots()
ax.imshow(edges, cmap='gray')
ax.axis("off")
st.pyplot(fig)
# Data Analysis
data = pd.DataFrame(crack_data)
st.markdown("", unsafe_allow_html=True)
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.markdown("", unsafe_allow_html=True)
for _, row in data.iterrows():
st.markdown(f"**Crack at (X: {row['X']}, Y: {row['Y']})** - {generate_description(row['Severity'])}")
# Discussion
st.markdown("", unsafe_allow_html=True)
st.write("- 🔴 **Major:** Significant structural impact, requires **immediate repair and engineering assessment.**")
st.write("- 🟠 **Moderate:** Moderate concern, monitoring required, may need **localized reinforcement.**")
st.write("- 🟢 **Minor:** Surface-level cracks, **not structurally critical** but should be observed over time.")
# 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()