File size: 5,267 Bytes
15526fe
3db0aec
 
9814e5f
3db0aec
 
d9a6878
3db0aec
 
 
 
 
 
 
 
 
 
d774ee6
 
 
 
 
 
 
3db0aec
 
d774ee6
3db0aec
d774ee6
 
 
3db0aec
d774ee6
3db0aec
 
7030681
d774ee6
3db0aec
 
d604335
3db0aec
 
d774ee6
 
 
 
 
 
3db0aec
d774ee6
 
3db0aec
d774ee6
3db0aec
 
 
 
 
 
d604335
dbd2162
60dab82
3db0aec
d774ee6
3db0aec
7030681
3db0aec
d774ee6
3db0aec
7030681
3db0aec
 
 
d9a6878
d604335
 
 
d774ee6
d604335
d774ee6
3db0aec
15526fe
9814e5f
d774ee6
 
 
 
 
 
3db0aec
d774ee6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d604335
d774ee6
 
 
 
 
 
 
3db0aec
d774ee6
 
 
 
 
 
 
 
 
 
 
9814e5f
 
d604335
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import streamlit as st
from transformers import ViTForImageClassification, ViTImageProcessor
from PIL import Image
import torch
import time
import gc

# Constants
MAX_FILE_SIZE = 5 * 1024 * 1024  # 5MB
MAX_IMAGE_SIZE = 1024  # Maximum dimension for images

def cleanup_memory():
    """Clean up memory and GPU cache"""
    gc.collect()
    if torch.cuda.is_available():
        torch.cuda.empty_cache()

def init_session_state():
    """Initialize session state variables"""
    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

@st.cache_resource(show_spinner="Loading AI model...")
def load_model():
    """Load and cache the model and processor"""
    try:
        model_name = "google/vit-base-patch16-224"
        processor = ViTImageProcessor.from_pretrained(model_name)
        device = "cuda" if torch.cuda.is_available() else "cpu"
        model = ViTForImageClassification.from_pretrained(
            model_name,
            num_labels=len(DAMAGE_TYPES),
            ignore_mismatched_sizes=True,
        ).to(device)
        model.eval()
        return model, processor
    except Exception as e:
        st.error(f"Error loading model: {str(e)}")
        return None, None

def validate_image(image):
    """Validate image size and format"""
    if image.size[0] * image.size[1] > 1024 * 1024:
        st.warning("Large image detected. The image will be resized for better performance.")
    if image.format not in ['JPEG', 'PNG']:
        st.warning("Image format not optimal. Consider using JPEG or PNG for better performance.")

def preprocess_image(uploaded_file):
    """Preprocess and validate uploaded image"""
    try:
        image = Image.open(uploaded_file)
        if max(image.size) > MAX_IMAGE_SIZE:
            ratio = MAX_IMAGE_SIZE / max(image.size)
            new_size = tuple([int(dim * ratio) for dim in image.size])
            image = image.resize(new_size, Image.Resampling.LANCZOS)
        return image
    except Exception as e:
        st.error(f"Error processing image: {str(e)}")
        return None

def analyze_damage(image, model, processor):
    """Analyze structural damage in the image"""
    try:
        device = next(model.parameters()).device
        with torch.no_grad():
            image = image.convert('RGB')
            inputs = processor(images=image, return_tensors="pt")
            inputs = {k: v.to(device) for k, v in inputs.items()}
            outputs = model(**inputs)
            probs = torch.nn.functional.softmax(outputs.logits, dim=1)[0]
            cleanup_memory()
            return probs.cpu()
    except RuntimeError as e:
        if "out of memory" in str(e):
            cleanup_memory()
            st.error("Out of memory. Please try with a smaller image.")
        else:
            st.error(f"Error analyzing image: {str(e)}")
        return None

def main():
    st.set_page_config(
        page_title="Structural Damage Analyzer Pro",
        page_icon="πŸ—οΈ",
        layout="wide",
        initial_sidebar_state="expanded"
    )

    # Initialize session state
    init_session_state()

    # Display header
    st.markdown(
        """
        <div style='text-align: center; padding: 1rem;'>
            <h1>πŸ—οΈ Structural Damage Analyzer Pro</h1>
            <p style='font-size: 1.2rem;'>Advanced AI-powered structural damage assessment tool</p>
        </div>
        """,
        unsafe_allow_html=True
    )

    # Load model
    model, processor = load_model()
    if model is None:
        st.error("Failed to load model. Please refresh the page.")
        return

    # File upload
    uploaded_file = st.file_uploader(
        "Upload an image for analysis",
        type=['jpg', 'jpeg', 'png'],
        help="Supported formats: JPG, JPEG, PNG"
    )

    if uploaded_file:
        try:
            if uploaded_file.size > MAX_FILE_SIZE:
                st.error("File size too large. Please upload an image smaller than 5MB.")
                return

            image = preprocess_image(uploaded_file)
            if image is None:
                return

            validate_image(image)
            
            # Display image and analyze
            st.image(image, caption="Uploaded Structure", use_column_width=True)
            
            with st.spinner("πŸ” Analyzing damage..."):
                predictions = analyze_damage(image, model, processor)
                if predictions is not None:
                    st.success("Analysis complete!")
                    # Add analysis display logic here based on your DAMAGE_TYPES

        except Exception as e:
            cleanup_memory()
            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>πŸ—οΈ Structural Damage Analyzer Pro | 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()