Spaces:
Sleeping
Sleeping
import streamlit as st | |
from transformers import ViTForImageClassification, ViTImageProcessor | |
from PIL import Image | |
import torch | |
import time | |
import io | |
import base64 | |
# Cache the model globally | |
MODEL = None | |
PROCESSOR = None | |
# Embedded knowledge base | |
# Knowledge base | |
KNOWLEDGE_BASE = { | |
"spalling": [ | |
{ | |
"severity": "Critical", | |
"description": "Severe concrete spalling with exposed reinforcement and section loss", | |
"repair_method": ["Install temporary support", "Remove deteriorated concrete", "Clean and treat reinforcement", "Apply corrosion inhibitor", "Apply bonding agent", "High-strength repair mortar"], | |
"estimated_cost": "Very High ($15,000+)", | |
"timeframe": "3-4 weeks", | |
"location": "Primary structural elements", | |
"required_expertise": "Structural Engineer + Specialist Contractor", | |
"immediate_action": "Evacuate area, install temporary support, prevent access", | |
"prevention": "Regular inspections, waterproofing, chloride protection" | |
}, | |
{ | |
"severity": "High", | |
"description": "Surface spalling with visible reinforcement", | |
"repair_method": ["Remove damaged concrete", "Treat reinforcement", "Apply repair mortar", "Surface treatment"], | |
"estimated_cost": "High ($8,000-$15,000)", | |
"timeframe": "2-3 weeks", | |
"location": "Structural elements", | |
"required_expertise": "Structural Engineer", | |
"immediate_action": "Area isolation, temporary support assessment", | |
"prevention": "Protective coatings, drainage improvement" | |
} | |
], | |
"reinforcement_corrosion": [ | |
{ | |
"severity": "Critical", | |
"description": "Severe corrosion with >30% section loss", | |
"repair_method": ["Structural support", "Remove concrete", "Replace reinforcement", "Corrosion protection", "Concrete repair"], | |
"estimated_cost": "Critical ($20,000+)", | |
"timeframe": "4-6 weeks", | |
"location": "Load-bearing elements", | |
"required_expertise": "Senior Structural Engineer", | |
"immediate_action": "Immediate evacuation, emergency shoring", | |
"prevention": "Waterproofing, cathodic protection" | |
} | |
], | |
"structural_crack": [ | |
{ | |
"severity": "High", | |
"description": "Cracks >5mm in structural elements", | |
"repair_method": ["Structural analysis", "Epoxy injection", "Carbon fiber reinforcement", "Crack monitoring"], | |
"estimated_cost": "High ($10,000-$20,000)", | |
"timeframe": "2-4 weeks", | |
"location": "Primary structure", | |
"required_expertise": "Structural Engineer", | |
"immediate_action": "Install crack monitors, load restriction", | |
"prevention": "Load management, joint maintenance" | |
} | |
], | |
"dampness": [ | |
{ | |
"severity": "Medium", | |
"description": "Active water penetration with efflorescence", | |
"repair_method": ["Water source identification", "Drainage improvement", "Waterproof membrane", "Ventilation"], | |
"estimated_cost": "Medium ($5,000-$10,000)", | |
"timeframe": "1-2 weeks", | |
"location": "Various", | |
"required_expertise": "Waterproofing Specialist", | |
"immediate_action": "Dehumidification, efflorescence cleaning", | |
"prevention": "Proper drainage, vapor barriers" | |
} | |
], | |
"no_damage": [ | |
{ | |
"severity": "Low", | |
"description": "No significant structural issues", | |
"repair_method": ["Regular inspection", "Preventive maintenance"], | |
"estimated_cost": "Low ($500-$2,000)", | |
"timeframe": "1-2 days", | |
"location": "General", | |
"required_expertise": "Building Inspector", | |
"immediate_action": "Continue monitoring", | |
"prevention": "Regular maintenance schedule" | |
} | |
] | |
} | |
DAMAGE_TYPES = { | |
0: {'name': 'spalling', 'risk': 'High', 'color': '#ff4d4d'}, | |
1: {'name': 'reinforcement_corrosion', 'risk': 'Critical', 'color': '#800000'}, | |
2: {'name': 'structural_crack', 'risk': 'High', 'color': '#ff6b6b'}, | |
3: {'name': 'dampness', 'risk': 'Medium', 'color': '#4dabf7'}, | |
4: {'name': 'no_damage', 'risk': 'Low', 'color': '#40c057'} | |
} | |
def init_session_state(): | |
if 'history' not in st.session_state: | |
st.session_state.history = [] | |
if 'dark_mode' not in st.session_state: | |
st.session_state.dark_mode = False | |
def load_model(): | |
try: | |
model = ViTForImageClassification.from_pretrained( | |
"google/vit-base-patch16-224", | |
num_labels=len(DAMAGE_TYPES), | |
ignore_mismatched_sizes=True | |
) | |
processor = ViTImageProcessor.from_pretrained("google/vit-base-patch16-224") | |
return model, processor | |
except Exception as e: | |
st.error(f"Error loading model: {str(e)}") | |
return None, None | |
def analyze_damage(image, model, processor): | |
try: | |
image = image.convert('RGB') | |
inputs = processor(images=image, return_tensors="pt") | |
outputs = model(**inputs) | |
probs = torch.nn.functional.softmax(outputs.logits, dim=1)[0] | |
return probs | |
except Exception as e: | |
st.error(f"Error analyzing image: {str(e)}") | |
return None | |
def get_custom_css(): | |
return """ | |
<style> | |
.main { | |
padding: 2rem; | |
} | |
.stProgress > div > div > div > div { | |
background-image: linear-gradient(to right, var(--progress-color, #ff6b6b), var(--progress-color-end, #f06595)); | |
} | |
.damage-card { | |
padding: 1.5rem; | |
border-radius: 0.5rem; | |
background: var(--card-bg, #f8f9fa); | |
margin-bottom: 1rem; | |
border: 1px solid var(--border-color, #dee2e6); | |
box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
} | |
.damage-header { | |
font-size: 1.25rem; | |
font-weight: bold; | |
margin-bottom: 1rem; | |
color: var(--text-color, #212529); | |
} | |
.dark-mode { | |
background-color: #1a1a1a; | |
color: #ffffff; | |
} | |
.dark-mode .damage-card { | |
background: #2d2d2d; | |
border-color: #404040; | |
} | |
.tooltip { | |
position: relative; | |
display: inline-block; | |
border-bottom: 1px dotted #ccc; | |
} | |
.tooltip .tooltiptext { | |
visibility: hidden; | |
background-color: #555; | |
color: #fff; | |
text-align: center; | |
border-radius: 6px; | |
padding: 5px; | |
position: absolute; | |
z-index: 1; | |
bottom: 125%; | |
left: 50%; | |
margin-left: -60px; | |
opacity: 0; | |
transition: opacity 0.3s; | |
} | |
</style> | |
""" | |
def display_header(): | |
st.markdown( | |
""" | |
<div style='text-align: center; padding: 1rem;'> | |
<h1>ποΈ Smart Construction Defect Analyzer</h1> | |
<p style='font-size: 1.2rem;'>Advanced AI-powered Construction Defect tool</p> | |
</div> | |
""", | |
unsafe_allow_html=True | |
) | |
def main(): | |
init_session_state() | |
st.set_page_config( | |
page_title="Smart Construction Defect Analyzer", | |
page_icon="ποΈ", | |
layout="wide", | |
initial_sidebar_state="expanded" | |
) | |
st.markdown(get_custom_css(), unsafe_allow_html=True) | |
# Sidebar | |
with st.sidebar: | |
st.markdown("### βοΈ Settings") | |
st.session_state.dark_mode = st.toggle("Dark Mode", st.session_state.dark_mode) | |
st.markdown("### π Analysis History") | |
if st.session_state.history: | |
for item in st.session_state.history[-5:]: | |
st.markdown(f"- {item}") | |
display_header() | |
# Load model | |
global MODEL, PROCESSOR | |
if MODEL is None or PROCESSOR is None: | |
with st.spinner("Loading AI model..."): | |
MODEL, PROCESSOR = load_model() | |
if MODEL is None: | |
st.error("Failed to load model. Please refresh the page.") | |
return | |
# File upload with drag and drop | |
uploaded_file = st.file_uploader( | |
"Drag and drop or click to upload an image", | |
type=['jpg', 'jpeg', 'png'], | |
help="Supported formats: JPG, JPEG, PNG" | |
) | |
if uploaded_file: | |
try: | |
# Image display and analysis | |
image = Image.open(uploaded_file) | |
col1, col2 = st.columns([1, 1]) | |
with col1: | |
st.image(image, caption="Uploaded Structure", use_container_width =True) | |
with col2: | |
with st.spinner("π Analyzing damage..."): | |
start_time = time.time() | |
predictions = analyze_damage(image, MODEL, PROCESSOR) | |
analysis_time = time.time() - start_time | |
if predictions is not None: | |
st.markdown("### π Analysis Results") | |
st.markdown(f"*Analysis completed in {analysis_time:.2f} seconds*") | |
detected = False | |
for idx, prob in enumerate(predictions): | |
confidence = float(prob) * 100 | |
if confidence > 15: | |
detected = True | |
damage_type = DAMAGE_TYPES[idx]['name'] | |
cases = KNOWLEDGE_BASE[damage_type] | |
with st.expander(f"{damage_type.replace('_', ' ').title()} - {confidence:.1f}%", expanded=True): | |
# Progress bar with custom color | |
st.markdown( | |
f""" | |
<style> | |
.stProgress > div > div > div > div {{ | |
background-color: {DAMAGE_TYPES[idx]['color']} !important; | |
}} | |
</style> | |
""", | |
unsafe_allow_html=True | |
) | |
st.progress(confidence / 100) | |
tabs = st.tabs(["π Details", "π§ Repairs", "β οΈ Actions"]) | |
with tabs[0]: | |
for case in cases: | |
st.markdown(f""" | |
- **Severity:** {case['severity']} | |
- **Description:** {case['description']} | |
- **Location:** {case['location']} | |
- **Required Expertise:** {case['required_expertise']} | |
""") | |
with tabs[1]: | |
for step in cases[0]['repair_method']: | |
st.markdown(f"β {step}") | |
st.info(f"**Estimated Cost:** {cases[0]['estimated_cost']}") | |
st.info(f"**Timeframe:** {cases[0]['timeframe']}") | |
with tabs[2]: | |
st.warning("**Immediate Actions Required:**") | |
st.markdown(cases[0]['immediate_action']) | |
st.success("**Prevention Measures:**") | |
st.markdown(cases[0]['prevention']) | |
if not detected: | |
st.info("No significant Construction Defect detected. Regular maintenance recommended.") | |
# Add to history | |
st.session_state.history.append(f"Analyzed image: {uploaded_file.name}") | |
except Exception as e: | |
st.error(f"Error processing image: {str(e)}") | |
st.info("Please try uploading a different image.") | |
# Footer | |
st.markdown("---") | |
st.markdown( | |
""" | |
<div style='text-align: center'> | |
<p>ποΈ Smart Construction Defect Analyzer | Built with Streamlit & Transformers</p> | |
<p style='font-size: 0.8rem;'>For professional use only. Always consult with a structural engineer.</p> | |
</div> | |
""", | |
unsafe_allow_html=True | |
) | |
if __name__ == "__main__": | |
main() |