|
|
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): |
|
|
|
|
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) |
|
|
|
|
|
|
|
|
edges = cv2.Canny(gray, 50, 150) |
|
|
|
|
|
|
|
|
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
|
|
|
|
|
|
|
|
crack_lengths = [cv2.arcLength(cnt, True) for cnt in contours] |
|
|
crack_widths = [cv2.boundingRect(cnt)[2] for cnt in contours] |
|
|
|
|
|
return edges, crack_lengths, crack_widths |
|
|
|
|
|
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 main(): |
|
|
st.set_page_config(page_title='Structural Integrity Analyst', layout='wide', initial_sidebar_state='expanded') |
|
|
|
|
|
st.title('ποΈ Structural Integrity Analyst') |
|
|
|
|
|
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_lengths, crack_widths = analyze_crack(image) |
|
|
|
|
|
|
|
|
classifications = [classify_crack(l, w) for l, w in zip(crack_lengths, crack_widths)] |
|
|
|
|
|
|
|
|
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 = pd.DataFrame({ |
|
|
"Crack Length (pixels)": crack_lengths, |
|
|
"Crack Width (pixels)": crack_widths, |
|
|
"Severity": classifications |
|
|
}) |
|
|
|
|
|
st.subheader("Crack Metrics & Classification") |
|
|
st.dataframe(data) |
|
|
|
|
|
|
|
|
st.subheader("Discussion") |
|
|
st.write("Cracks are classified based on their length and width:") |
|
|
st.write("- **Major:** Cracks exceeding 150 pixels in length or 20 pixels in width indicate severe damage and require immediate attention.") |
|
|
st.write("- **Moderate:** Cracks between 80-150 pixels in length or 10-20 pixels in width are moderate and should be monitored closely.") |
|
|
st.write("- **Minor:** Cracks below 80 pixels in length or 10 pixels in width are minor and may not require immediate intervention but should be observed over time.") |
|
|
|
|
|
|
|
|
fig1 = px.histogram(data, x="Crack Length (pixels)", color="Severity", title="Crack Length Distribution", nbins=10) |
|
|
fig2 = px.histogram(data, x="Crack Width (pixels)", color="Severity", title="Crack Width Distribution", nbins=10) |
|
|
|
|
|
st.plotly_chart(fig1, use_container_width=True) |
|
|
st.plotly_chart(fig2, use_container_width=True) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |