Shakir60 commited on
Commit
dbd2162
·
verified ·
1 Parent(s): dd3a5aa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +259 -65
app.py CHANGED
@@ -1,79 +1,273 @@
1
  import streamlit as st
2
- from transformers import ViTForImageClassification, ViTImageProcessor
3
- from PIL import Image
 
 
 
 
4
  import torch
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- # Define damage types and remedies
7
- DAMAGE_TYPES = {
8
- 0: {'name': 'spalling', 'risk': 'High'},
9
- 1: {'name': 'reinforcement_corrosion', 'risk': 'Critical'},
10
- 2: {'name': 'structural_crack', 'risk': 'High'},
11
- 3: {'name': 'dampness', 'risk': 'Medium'},
12
- 4: {'name': 'no_damage', 'risk': 'Low'}
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- REMEDIES = {
16
- 'spalling': ['Remove loose concrete', 'Clean exposed area', 'Apply repair mortar'],
17
- 'reinforcement_corrosion': ['Remove rust', 'Apply corrosion inhibitor', 'Repair concrete cover'],
18
- 'structural_crack': ['Measure crack width', 'Epoxy injection', 'Monitor progression'],
19
- 'dampness': ['Identify water source', 'Improve drainage', 'Apply waterproofing'],
20
- 'no_damage': ['Regular maintenance', 'Periodic inspection']
21
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
- @st.cache_resource
24
- def load_model():
25
- model = ViTForImageClassification.from_pretrained(
26
- "google/vit-base-patch16-224",
27
- num_labels=len(DAMAGE_TYPES),
28
- ignore_mismatched_sizes=True
29
- )
30
- processor = ViTImageProcessor.from_pretrained("google/vit-base-patch16-224")
31
- return model, processor
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
- def analyze_damage(image, model, processor):
34
- image = image.convert('RGB')
35
- inputs = processor(images=image, return_tensors="pt")
36
- outputs = model(**inputs)
37
- probs = torch.nn.functional.softmax(outputs.logits, dim=1)[0]
38
- return probs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  def main():
41
- st.title("Structural Damage Assessment Tool")
42
-
43
- model, processor = load_model()
 
 
44
 
45
- uploaded_file = st.file_uploader("Upload structural image", type=['jpg', 'jpeg', 'png'])
 
 
 
 
 
46
 
47
- if uploaded_file:
48
- image = Image.open(uploaded_file)
49
- st.image(image, caption="Uploaded Structure", use_column_width=True)
50
 
51
- with st.spinner("Analyzing..."):
52
- predictions = analyze_damage(image, model, processor)
53
-
54
- col1, col2 = st.columns(2)
55
 
56
- with col1:
57
- st.subheader("Damage Assessment")
58
- for idx, prob in enumerate(predictions):
59
- damage_type = DAMAGE_TYPES[idx]['name']
60
- confidence = float(prob) * 100
61
- if confidence > 15:
62
- st.write(f"**{damage_type.replace('_', ' ').title()}**")
63
- st.progress(confidence / 100)
64
- st.write(f"Confidence: {confidence:.1f}%")
65
- st.write(f"Risk Level: {DAMAGE_TYPES[idx]['risk']}")
66
-
67
- with col2:
68
- st.subheader("Recommended Actions")
69
- for idx, prob in enumerate(predictions):
70
- damage_type = DAMAGE_TYPES[idx]['name']
71
- confidence = float(prob) * 100
72
- if confidence > 15:
73
- st.write(f"**For {damage_type.replace('_', ' ').title()}:**")
74
- for remedy in REMEDIES[damage_type]:
75
- st.write(f"• {remedy}")
76
- st.write("---")
 
 
 
 
 
 
 
77
 
78
  if __name__ == "__main__":
79
- main()
 
 
1
  import streamlit as st
2
+ from transformers import (
3
+ AutoModelForImageClassification,
4
+ AutoImageProcessor,
5
+ ViTForImageClassification,
6
+ ResNetForImageClassification
7
+ )
8
  import torch
9
+ import numpy as np
10
+ from PIL import Image, ImageDraw
11
+ import cv2
12
+ from langchain import FAISS
13
+ from langchain.embeddings import HuggingFaceEmbeddings
14
+ from langchain.chains import RetrievalQA
15
+ from langchain.llms import HuggingFacePipeline
16
+ import json
17
+ import os
18
+ from concurrent.futures import ThreadPoolExecutor
19
+ import pandas as pd
20
 
21
+ class DefectMeasurement:
22
+ """Handle defect measurements and severity estimation"""
23
+
24
+ @staticmethod
25
+ def measure_defect(image, defect_type):
26
+ """Measure defect dimensions using computer vision"""
27
+ img_array = np.array(image)
28
+ gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
29
+
30
+ if defect_type == "Crack":
31
+ # Crack width measurement
32
+ blur = cv2.GaussianBlur(gray, (3,3), 0)
33
+ edges = cv2.Canny(blur, 100, 200)
34
+ lines = cv2.HoughLinesP(edges, 1, np.pi/180, 50, minLineLength=100, maxLineGap=10)
35
+
36
+ if lines is not None:
37
+ max_length = 0
38
+ for line in lines:
39
+ x1, y1, x2, y2 = line[0]
40
+ length = np.sqrt((x2-x1)**2 + (y2-y1)**2)
41
+ max_length = max(max_length, length)
42
+ return {"length": max_length, "unit": "pixels"}
43
+
44
+ elif defect_type in ["Spalling", "Exposed_Bars"]:
45
+ # Area measurement
46
+ thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)[1]
47
+ contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
48
+
49
+ if contours:
50
+ max_area = max(cv2.contourArea(cnt) for cnt in contours)
51
+ return {"area": max_area, "unit": "square pixels"}
52
+
53
+ return None
54
 
55
+ class MultiModelAnalyzer:
56
+ """Handle multiple pre-trained models for defect detection"""
57
+
58
+ def __init__(self):
59
+ self.models = {
60
+ "CODEBRIM-ViT": "chanwooong/codebrim-vit-base",
61
+ "Concrete-Defect-ResNet": "nlp-waseda/concrete-defect-resnet",
62
+ "Bridge-Damage-ViT": "microsoft/bridge-damage-vit-base"
63
+ }
64
+ self.loaded_models = {}
65
+ self.loaded_processors = {}
66
+
67
+ @st.cache_resource
68
+ def load_model(self, model_name):
69
+ """Load specific model and processor"""
70
+ try:
71
+ if "vit" in model_name.lower():
72
+ model = ViTForImageClassification.from_pretrained(self.models[model_name])
73
+ else:
74
+ model = ResNetForImageClassification.from_pretrained(self.models[model_name])
75
+ processor = AutoImageProcessor.from_pretrained(self.models[model_name])
76
+ return model, processor
77
+ except Exception as e:
78
+ st.error(f"Error loading {model_name}: {str(e)}")
79
+ return None, None
80
+
81
+ def analyze_with_all_models(self, image):
82
+ """Run analysis with all available models"""
83
+ results = {}
84
+ for model_name in self.models.keys():
85
+ if model_name not in self.loaded_models:
86
+ self.loaded_models[model_name], self.loaded_processors[model_name] = self.load_model(model_name)
87
+
88
+ if self.loaded_models[model_name] is not None:
89
+ try:
90
+ inputs = self.loaded_processors[model_name](images=image, return_tensors="pt")
91
+ outputs = self.loaded_models[model_name](**inputs)
92
+ probs = torch.nn.functional.softmax(outputs.logits, dim=1)[0]
93
+ results[model_name] = probs
94
+ except Exception as e:
95
+ st.error(f"Error analyzing with {model_name}: {str(e)}")
96
+
97
+ return results
98
 
99
+ class EnhancedRAGSystem:
100
+ """Enhanced RAG system with comprehensive construction knowledge"""
101
+
102
+ def __init__(self):
103
+ self.knowledge_sources = {
104
+ "ACI_318": "concrete_design_requirements.json",
105
+ "ASTM": "testing_standards.json",
106
+ "repair_guidelines": "repair_methods.json",
107
+ "case_studies": "defect_cases.json"
108
+ }
109
+ self.embeddings = None
110
+ self.vectorstore = None
111
+ self.qa_chain = None
112
+
113
+ def load_knowledge_base(self):
114
+ """Load and combine multiple knowledge sources"""
115
+ combined_knowledge = []
116
+ for source, filename in self.knowledge_sources.items():
117
+ try:
118
+ with open(f"knowledge_base/{filename}", 'r') as f:
119
+ knowledge = json.load(f)
120
+ for item in knowledge:
121
+ item['source'] = source
122
+ combined_knowledge.extend(knowledge)
123
+ except Exception as e:
124
+ st.warning(f"Could not load {source}: {str(e)}")
125
+
126
+ return combined_knowledge
127
+
128
+ def init_rag(self):
129
+ """Initialize enhanced RAG system"""
130
+ try:
131
+ self.embeddings = HuggingFaceEmbeddings(
132
+ model_name="sentence-transformers/all-mpnet-base-v2"
133
+ )
134
+
135
+ knowledge_base = self.load_knowledge_base()
136
+ texts = [
137
+ f"{item['defect_type']} ({item['source']})\n" +
138
+ f"Description: {item['description']}\n" +
139
+ f"Repair: {item['repair_methods']}\n" +
140
+ f"Standards: {item['applicable_standards']}\n" +
141
+ f"Cases: {item['related_cases']}"
142
+ for item in knowledge_base
143
+ ]
144
+
145
+ self.vectorstore = FAISS.from_texts(texts, self.embeddings)
146
+
147
+ self.qa_chain = RetrievalQA.from_chain_type(
148
+ llm=HuggingFacePipeline.from_model_id(
149
+ model_id="google/flan-t5-large",
150
+ task="text2text-generation",
151
+ model_kwargs={"temperature": 0.7}
152
+ ),
153
+ chain_type="stuff",
154
+ retriever=self.vectorstore.as_retriever(
155
+ search_kwargs={"k": 5}
156
+ )
157
+ )
158
+
159
+ return True
160
+ except Exception as e:
161
+ st.error(f"Error initializing RAG system: {str(e)}")
162
+ return False
163
 
164
+ class ConstructionDefectAnalyzer:
165
+ """Main application class"""
166
+
167
+ def __init__(self):
168
+ self.multi_model = MultiModelAnalyzer()
169
+ self.rag_system = EnhancedRAGSystem()
170
+ self.defect_measurement = DefectMeasurement()
171
+
172
+ def analyze_multiple_images(self, images):
173
+ """Analyze multiple images in parallel"""
174
+ results = []
175
+ with ThreadPoolExecutor() as executor:
176
+ futures = []
177
+ for img in images:
178
+ future = executor.submit(self.analyze_single_image, img)
179
+ futures.append(future)
180
+
181
+ for future in futures:
182
+ result = future.result()
183
+ results.append(result)
184
+
185
+ return results
186
+
187
+ def analyze_single_image(self, image):
188
+ """Analyze a single image with all features"""
189
+ model_results = self.multi_model.analyze_with_all_models(image)
190
+ measurements = {}
191
+ recommendations = {}
192
+
193
+ # Get measurements for detected defects
194
+ for model_name, predictions in model_results.items():
195
+ for idx, prob in enumerate(predictions):
196
+ if prob > 0.15: # Confidence threshold
197
+ defect_type = self.get_defect_type(model_name, idx)
198
+ measurements[defect_type] = self.defect_measurement.measure_defect(image, defect_type)
199
+
200
+ # Get RAG recommendations
201
+ if self.rag_system.qa_chain:
202
+ query = self.generate_rag_query(defect_type, measurements.get(defect_type))
203
+ recommendations[defect_type] = self.rag_system.qa_chain.run(query)
204
+
205
+ return {
206
+ "model_results": model_results,
207
+ "measurements": measurements,
208
+ "recommendations": recommendations
209
+ }
210
+
211
+ @staticmethod
212
+ def generate_rag_query(defect_type, measurement):
213
+ """Generate detailed query for RAG system"""
214
+ query = f"What are the recommended repairs, safety measures, and applicable standards for {defect_type}"
215
+ if measurement:
216
+ if "length" in measurement:
217
+ query += f" with length {measurement['length']} {measurement['unit']}"
218
+ elif "area" in measurement:
219
+ query += f" with affected area {measurement['area']} {measurement['unit']}"
220
+ return query + "?"
221
 
222
  def main():
223
+ st.set_page_config(page_title="Advanced Construction Defect Analyzer", layout="wide")
224
+
225
+ analyzer = ConstructionDefectAnalyzer()
226
+
227
+ st.title("🏗️ Advanced Construction Defect Analyzer")
228
 
229
+ # Multiple image upload
230
+ uploaded_files = st.file_uploader(
231
+ "Upload construction images for analysis",
232
+ type=['jpg', 'jpeg', 'png'],
233
+ accept_multiple_files=True
234
+ )
235
 
236
+ if uploaded_files:
237
+ images = [Image.open(file).convert('RGB') for file in uploaded_files]
 
238
 
239
+ with st.spinner("Analyzing images..."):
240
+ results = analyzer.analyze_multiple_images(images)
 
 
241
 
242
+ for idx, (image, result) in enumerate(zip(images, results)):
243
+ st.markdown(f"### Analysis Results - Image {idx + 1}")
244
+
245
+ col1, col2 = st.columns([1, 2])
246
+
247
+ with col1:
248
+ st.image(image, caption=f"Image {idx + 1}", use_column_width=True)
249
+
250
+ with col2:
251
+ # Display model comparison
252
+ st.markdown("#### Model Predictions")
253
+ for model_name, predictions in result['model_results'].items():
254
+ st.markdown(f"**{model_name}:**")
255
+ for i, prob in enumerate(predictions):
256
+ if prob > 0.15:
257
+ defect_type = analyzer.get_defect_type(model_name, i)
258
+ st.progress(float(prob))
259
+ st.markdown(f"{defect_type}: {float(prob)*100:.1f}%")
260
+
261
+ # Display measurements
262
+ if defect_type in result['measurements']:
263
+ st.markdown("**Measurements:**")
264
+ st.json(result['measurements'][defect_type])
265
+
266
+ # Display recommendations
267
+ if defect_type in result['recommendations']:
268
+ with st.expander("📋 Detailed Analysis"):
269
+ st.markdown(result['recommendations'][defect_type])
270
 
271
  if __name__ == "__main__":
272
+ main()
273
+