AdityaPatwa commited on
Commit
39d6b95
Β·
verified Β·
1 Parent(s): c10a675

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +412 -67
app.py CHANGED
@@ -4,6 +4,7 @@ from PIL import Image
4
  from torchvision import transforms
5
  import gradio as gr
6
  import cv2
 
7
 
8
 
9
  # Path to ONNX model
@@ -37,121 +38,465 @@ preprocess = transforms.Compose([
37
  )
38
  ])
39
 
40
- def get_gradcam_heatmap(pil_image, pred_idx):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  """
42
- Generate Grad-CAM-like heatmap using output patterns
43
- Since we're using ONNX, we'll use an approximation method
44
  """
45
- # Preprocess image
46
- img = preprocess(pil_image).unsqueeze(0).numpy().astype(np.float32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
- # Get prediction
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  outputs = ort_session.run(None, {"input_image": img})[0]
50
 
51
- # Create attention map based on input image variance
52
- # This is a simplified approach for ONNX models
53
  img_array = np.array(pil_image.resize((IMG_SIZE, IMG_SIZE)))
54
  if len(img_array.shape) == 2:
55
  img_array = np.stack([img_array] * 3, axis=-1)
56
 
57
- # Convert to grayscale for intensity analysis
58
  gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
59
-
60
- # Apply edge detection to highlight important regions
61
  edges = cv2.Canny(gray, 50, 150)
62
-
63
- # Blur edges to create smooth heatmap
64
  heatmap = cv2.GaussianBlur(edges.astype(np.float32), (21, 21), 0)
65
 
66
- # Normalize heatmap
67
  if heatmap.max() > 0:
68
  heatmap = heatmap / heatmap.max()
69
 
70
  return heatmap
71
 
72
  def create_heatmap_overlay(pil_image, heatmap):
73
- """
74
- Overlay heatmap on original image
75
- """
76
- # Resize original image
77
  img_array = np.array(pil_image.resize((IMG_SIZE, IMG_SIZE)))
78
  if len(img_array.shape) == 2:
79
  img_array = np.stack([img_array] * 3, axis=-1)
80
 
81
- # Convert heatmap to color (red = high attention)
82
  heatmap_colored = cv2.applyColorMap(
83
  (heatmap * 255).astype(np.uint8),
84
  cv2.COLORMAP_JET
85
  )
86
  heatmap_colored = cv2.cvtColor(heatmap_colored, cv2.COLOR_BGR2RGB)
87
-
88
- # Overlay heatmap on image with transparency
89
  overlay = cv2.addWeighted(img_array, 0.6, heatmap_colored, 0.4, 0)
90
 
91
  return Image.fromarray(overlay.astype(np.uint8))
92
 
93
  def predict_image(pil_image):
94
- """
95
- Input: PIL Image
96
- Output: (predicted_class, confidence, full_probs_dict)
97
- """
98
  img = preprocess(pil_image).unsqueeze(0).numpy().astype(np.float32)
99
-
100
- # ONNX inference
101
- outputs = ort_session.run(
102
- None,
103
- {"input_image": img}
104
- )[0]
105
-
106
- # Softmax
107
  exp_scores = np.exp(outputs)
108
  probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
109
-
110
  probs = probs[0]
111
  pred_idx = int(np.argmax(probs))
112
-
113
  predicted_class = CLASS_NAMES[pred_idx]
114
  confidence = float(probs[pred_idx])
115
-
116
  prob_dict = {CLASS_NAMES[i]: float(probs[i]) for i in range(len(CLASS_NAMES))}
117
-
118
  return predicted_class, confidence, prob_dict, pred_idx
119
 
120
-
121
  print("βœ… Inference pipeline ready")
122
 
123
-
124
- # Gradio Interface with Heatmap
125
-
126
- def gradio_predict(image):
127
- pred_class, confidence, prob_dict, pred_idx = predict_image(image)
128
 
129
- # Generate heatmap
130
  heatmap = get_gradcam_heatmap(image, pred_idx)
131
  heatmap_overlay = create_heatmap_overlay(image, heatmap)
132
 
133
- confidence_percent = f"{confidence * 100:.2f}%"
134
-
135
- return pred_class, confidence_percent, prob_dict, heatmap_overlay
136
-
137
-
138
- iface = gr.Interface(
139
- fn=gradio_predict,
140
- inputs=gr.Image(type="pil", label="Upload Solar Panel Image (Thermal / IR / RGB)"),
141
- outputs=[
142
- gr.Textbox(label="Predicted Defect Class"),
143
- gr.Textbox(label="Confidence"),
144
- gr.Label(label="All Class Probabilities"),
145
- gr.Image(type="pil", label="Attention Heatmap (Red = High Focus)")
146
- ],
147
- title="AI-Powered Solar Panel Defect Detection with Heatmap",
148
- description=(
149
- "Upload any solar panel image (thermal, infrared, or RGB). "
150
- "The AI model classifies defects such as soiling, electrical damage, "
151
- "physical damage, snow coverage, or clean panels. "
152
- "The heatmap shows which regions the model focuses on (red = high attention)."
153
- ),
154
- examples=None
155
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
  iface.launch(debug=True)
 
4
  from torchvision import transforms
5
  import gradio as gr
6
  import cv2
7
+ from datetime import datetime, timedelta
8
 
9
 
10
  # Path to ONNX model
 
38
  )
39
  ])
40
 
41
+ # Maintenance recommendations database
42
+ MAINTENANCE_RECOMMENDATIONS = {
43
+ 'Bird-drop': {
44
+ 'severity': 'Medium',
45
+ 'severity_color': '🟑',
46
+ 'urgency': 'Schedule within 1-2 weeks',
47
+ 'impact': '5-15% efficiency loss',
48
+ 'actions': [
49
+ 'Clean affected panels with soft brush and water',
50
+ 'Install bird deterrents (spikes, netting, or reflective tape)',
51
+ 'Inspect for corrosion under droppings',
52
+ 'Apply protective coating if acid damage detected'
53
+ ],
54
+ 'frequency': 'Inspect monthly in areas with high bird activity',
55
+ 'degradation_rate': 0.8
56
+ },
57
+ 'Clean': {
58
+ 'severity': 'Low',
59
+ 'severity_color': '🟒',
60
+ 'urgency': 'Routine maintenance only',
61
+ 'impact': 'Optimal performance (0-2% below peak)',
62
+ 'actions': [
63
+ 'Continue regular monitoring schedule',
64
+ 'Quarterly visual inspections recommended',
65
+ 'Annual professional inspection',
66
+ 'Maintain vegetation clearance around panels'
67
+ ],
68
+ 'frequency': 'Quarterly inspections',
69
+ 'degradation_rate': 0.5
70
+ },
71
+ 'Dusty': {
72
+ 'severity': 'Medium',
73
+ 'severity_color': '🟑',
74
+ 'urgency': 'Schedule within 2-4 weeks',
75
+ 'impact': '10-25% efficiency loss depending on dust thickness',
76
+ 'actions': [
77
+ 'Clean panels with deionized water and soft microfiber cloth',
78
+ 'Consider automated cleaning system for frequent dust',
79
+ 'Apply anti-soiling nano-coating',
80
+ 'Schedule cleaning before monsoon/rain season'
81
+ ],
82
+ 'frequency': 'Clean every 2-6 months (varies by location)',
83
+ 'degradation_rate': 1.2
84
+ },
85
+ 'Electrical-damage': {
86
+ 'severity': 'High',
87
+ 'severity_color': 'πŸ”΄',
88
+ 'urgency': 'URGENT - Address within 24-48 hours',
89
+ 'impact': '30-100% efficiency loss, fire/safety risk',
90
+ 'actions': [
91
+ '⚠️ IMMEDIATELY disconnect affected panel circuit',
92
+ 'Call certified solar technician for inspection',
93
+ 'Check for loose connections, burnt wiring, or junction box damage',
94
+ 'Perform thermographic scan of entire array',
95
+ 'Replace damaged components (bypass diodes, connectors)',
96
+ 'Test electrical continuity and insulation resistance'
97
+ ],
98
+ 'frequency': 'Emergency response, then quarterly electrical audits',
99
+ 'degradation_rate': 5.0
100
+ },
101
+ 'Physical-Damage': {
102
+ 'severity': 'High',
103
+ 'severity_color': 'πŸ”΄',
104
+ 'urgency': 'URGENT - Address within 1 week',
105
+ 'impact': '25-100% efficiency loss, water ingress risk',
106
+ 'actions': [
107
+ 'Assess crack severity (micro-cracks vs. major breaks)',
108
+ 'Seal minor cracks with UV-resistant clear sealant',
109
+ 'Replace severely damaged panels',
110
+ 'Check for moisture ingress in junction box',
111
+ 'Inspect mounting hardware and structural integrity',
112
+ 'Document damage for warranty/insurance claims'
113
+ ],
114
+ 'frequency': 'Immediate repair, then bi-annual structural inspections',
115
+ 'degradation_rate': 3.5
116
+ },
117
+ 'Snow-Covered': {
118
+ 'severity': 'Medium',
119
+ 'severity_color': '🟑',
120
+ 'urgency': 'Monitor and clear when safe',
121
+ 'impact': '80-100% temporary efficiency loss (recovers after melting)',
122
+ 'actions': [
123
+ 'Allow natural melting when possible (panels generate some heat)',
124
+ 'Use soft snow rake with non-abrasive head if necessary',
125
+ '⚠️ NEVER use hot water (thermal shock can crack panels)',
126
+ 'Adjust panel tilt angle to 45Β°+ in snowy regions',
127
+ 'Install heating cables for persistent snow areas',
128
+ 'Clear bottom panels first to enable snow sliding'
129
+ ],
130
+ 'frequency': 'As needed during winter months',
131
+ 'degradation_rate': 0.0
132
+ }
133
+ }
134
+
135
+ def predict_degradation(defect_class, current_efficiency=100, time_horizon_months=12):
136
  """
137
+ Predict solar panel efficiency degradation over time
 
138
  """
139
+ maintenance = MAINTENANCE_RECOMMENDATIONS[defect_class]
140
+ degradation_rate = maintenance['degradation_rate']
141
+
142
+ timeline = []
143
+ efficiency = current_efficiency
144
+
145
+ if defect_class in ['Electrical-damage', 'Physical-Damage']:
146
+ for week in range(0, min(time_horizon_months * 4, 52), 2):
147
+ date = datetime.now() + timedelta(weeks=week)
148
+ timeline.append({
149
+ 'date': date.strftime('%b %d, %Y'),
150
+ 'efficiency': max(0, efficiency),
151
+ 'status': 'πŸ”΄ Critical' if efficiency < 50 else '🟑 Degraded'
152
+ })
153
+ efficiency -= degradation_rate
154
+ else:
155
+ for month in range(0, time_horizon_months + 1, 2):
156
+ date = datetime.now() + timedelta(days=month * 30)
157
+ timeline.append({
158
+ 'date': date.strftime('%b %d, %Y'),
159
+ 'efficiency': max(0, efficiency),
160
+ 'status': '🟒 Good' if efficiency > 85 else '🟑 Fair' if efficiency > 70 else 'πŸ”΄ Poor'
161
+ })
162
+ efficiency -= degradation_rate
163
+
164
+ return timeline
165
+
166
+ def format_maintenance_report(defect_class, confidence):
167
+ """
168
+ Generate comprehensive maintenance report
169
+ """
170
+ maint = MAINTENANCE_RECOMMENDATIONS[defect_class]
171
+
172
+ actions_formatted = '\n'.join([f'**{i+1}.** {action}' for i, action in enumerate(maint['actions'])])
173
+
174
+ report = f"""
175
+ <div style="background: linear-gradient(135deg, #525252 0%, #404040 100%); padding: 20px; border-radius: 10px; color: #fafafa; margin-bottom: 20px; border: 1px solid #404040;">
176
+ <h2 style="margin: 0; font-size: 24px; color: #fafafa;">πŸ”§ Maintenance Report</h2>
177
+ </div>
178
+
179
+ <div style="background: #171717; padding: 20px; border-radius: 10px; margin-bottom: 15px; border: 1px solid #262626;">
180
+ <h3 style="color: #fafafa; margin-top: 0;">πŸ“‹ Detection Summary</h3>
181
+ <p style="font-size: 16px; margin: 10px 0; color: #d4d4d4;"><strong>Condition Detected:</strong> <span style="color: #a3a3a3; font-size: 18px;">{defect_class}</span></p>
182
+ <p style="font-size: 16px; margin: 10px 0; color: #d4d4d4;"><strong>Confidence Level:</strong> <span style="color: #a3a3a3; font-size: 18px;">{confidence*100:.1f}%</span></p>
183
+ <p style="font-size: 16px; margin: 10px 0; color: #d4d4d4;"><strong>Severity:</strong> {maint['severity_color']} <span style="font-weight: bold;">{maint['severity']}</span></p>
184
+ </div>
185
+
186
+ <div style="background: #422006; padding: 15px; border-left: 4px solid #f59e0b; border-radius: 5px; margin-bottom: 15px;">
187
+ <p style="margin: 0; font-size: 16px; color: #fef3c7;"><strong>⏰ Urgency:</strong> {maint['urgency']}</p>
188
+ </div>
189
+
190
+ <div style="background: #171717; padding: 20px; border-radius: 10px; margin-bottom: 15px; border: 1px solid #262626;">
191
+ <h3 style="color: #fafafa; margin-top: 0;">πŸ“Š Performance Impact</h3>
192
+ <p style="font-size: 15px; line-height: 1.6; color: #d4d4d4;">{maint['impact']}</p>
193
+ </div>
194
+
195
+ <div style="background: #022c22; padding: 20px; border-left: 4px solid #10b981; border-radius: 5px; margin-bottom: 15px;">
196
+ <h3 style="color: #d1fae5; margin-top: 0;">βœ… Recommended Actions</h3>
197
+ <div style="font-size: 15px; line-height: 1.8; color: #d1fae5;">
198
+ {actions_formatted}
199
+ </div>
200
+ </div>
201
+
202
+ <div style="background: #171717; padding: 15px; border-radius: 10px; border: 1px solid #262626;">
203
+ <p style="margin: 5px 0; font-size: 15px; color: #d4d4d4;"><strong>πŸ“… Maintenance Frequency:</strong> {maint['frequency']}</p>
204
+ <p style="margin: 5px 0; font-size: 15px; color: #d4d4d4;"><strong>⚠️ Degradation Rate:</strong> {maint['degradation_rate']}% efficiency loss per {'week' if defect_class in ['Electrical-damage'] else 'month'} if untreated</p>
205
+ </div>
206
+ """
207
+ return report
208
+
209
+ def format_degradation_prediction(timeline):
210
+ """
211
+ Format degradation prediction timeline
212
+ """
213
+ table_rows = '\n'.join([
214
+ f"<tr><td style='padding: 12px; border-bottom: 1px solid #262626; color: #d4d4d4;'>{entry['date']}</td>"
215
+ f"<td style='padding: 12px; border-bottom: 1px solid #262626; font-weight: bold; color: #fafafa;'>{entry['efficiency']:.1f}%</td>"
216
+ f"<td style='padding: 12px; border-bottom: 1px solid #262626; color: #d4d4d4;'>{entry['status']}</td></tr>"
217
+ for entry in timeline
218
+ ])
219
 
220
+ report = f"""
221
+ <div style="background: linear-gradient(135deg, #525252 0%, #404040 100%); padding: 20px; border-radius: 10px; color: #fafafa; margin-bottom: 20px; border: 1px solid #404040;">
222
+ <h2 style="margin: 0; font-size: 24px;">πŸ“‰ Degradation Forecast</h2>
223
+ <p style="margin: 5px 0 0 0; opacity: 0.9;">Projected efficiency without maintenance intervention</p>
224
+ </div>
225
+
226
+ <div style="background: #171717; padding: 20px; border-radius: 10px; border: 1px solid #262626; margin-bottom: 20px;">
227
+ <table style="width: 100%; border-collapse: collapse;">
228
+ <thead>
229
+ <tr style="background: #0a0a0a;">
230
+ <th style="padding: 12px; text-align: left; border-bottom: 2px solid #404040; color: #fafafa;">Date</th>
231
+ <th style="padding: 12px; text-align: left; border-bottom: 2px solid #404040; color: #fafafa;">Efficiency</th>
232
+ <th style="padding: 12px; text-align: left; border-bottom: 2px solid #404040; color: #fafafa;">Status</th>
233
+ </tr>
234
+ </thead>
235
+ <tbody>
236
+ {table_rows}
237
+ </tbody>
238
+ </table>
239
+ </div>
240
+
241
+ <div style="background: #022c22; padding: 20px; border-left: 4px solid #10b981; border-radius: 5px; margin-bottom: 15px;">
242
+ <h3 style="color: #d1fae5; margin-top: 0;">πŸ’‘ Prevention Strategies</h3>
243
+ <ul style="color: #d1fae5; line-height: 1.8; font-size: 15px;">
244
+ <li><strong>Regular Monitoring:</strong> Track daily energy output to detect issues early</li>
245
+ <li><strong>Scheduled Maintenance:</strong> Follow recommended cleaning and inspection schedules</li>
246
+ <li><strong>Professional Audits:</strong> Annual thermographic scans detect hidden problems</li>
247
+ <li><strong>Protective Measures:</strong> Install bird deterrents, anti-soiling coatings, and proper drainage</li>
248
+ <li><strong>Documentation:</strong> Keep maintenance records for warranty compliance</li>
249
+ </ul>
250
+ </div>
251
+
252
+ <div style="background: #422006; padding: 20px; border-radius: 10px; border-left: 4px solid #f59e0b;">
253
+ <h3 style="color: #fef3c7; margin-top: 0;">⚑ Performance Optimization Tips</h3>
254
+ <ul style="color: #fef3c7; line-height: 1.8; font-size: 15px;">
255
+ <li>Clean panels during early morning or late evening (avoid thermal shock)</li>
256
+ <li>Trim nearby vegetation to prevent shading and debris accumulation</li>
257
+ <li>Inspect wiring and connections for corrosion every 6 months</li>
258
+ <li>Keep inverter and electrical components clean and ventilated</li>
259
+ <li>Consider microinverters for better partial-shading performance</li>
260
+ </ul>
261
+ </div>
262
+ """
263
+ return report
264
+
265
+ def get_gradcam_heatmap(pil_image, pred_idx):
266
+ img = preprocess(pil_image).unsqueeze(0).numpy().astype(np.float32)
267
  outputs = ort_session.run(None, {"input_image": img})[0]
268
 
 
 
269
  img_array = np.array(pil_image.resize((IMG_SIZE, IMG_SIZE)))
270
  if len(img_array.shape) == 2:
271
  img_array = np.stack([img_array] * 3, axis=-1)
272
 
 
273
  gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
 
 
274
  edges = cv2.Canny(gray, 50, 150)
 
 
275
  heatmap = cv2.GaussianBlur(edges.astype(np.float32), (21, 21), 0)
276
 
 
277
  if heatmap.max() > 0:
278
  heatmap = heatmap / heatmap.max()
279
 
280
  return heatmap
281
 
282
  def create_heatmap_overlay(pil_image, heatmap):
 
 
 
 
283
  img_array = np.array(pil_image.resize((IMG_SIZE, IMG_SIZE)))
284
  if len(img_array.shape) == 2:
285
  img_array = np.stack([img_array] * 3, axis=-1)
286
 
 
287
  heatmap_colored = cv2.applyColorMap(
288
  (heatmap * 255).astype(np.uint8),
289
  cv2.COLORMAP_JET
290
  )
291
  heatmap_colored = cv2.cvtColor(heatmap_colored, cv2.COLOR_BGR2RGB)
 
 
292
  overlay = cv2.addWeighted(img_array, 0.6, heatmap_colored, 0.4, 0)
293
 
294
  return Image.fromarray(overlay.astype(np.uint8))
295
 
296
  def predict_image(pil_image):
 
 
 
 
297
  img = preprocess(pil_image).unsqueeze(0).numpy().astype(np.float32)
298
+ outputs = ort_session.run(None, {"input_image": img})[0]
 
 
 
 
 
 
 
299
  exp_scores = np.exp(outputs)
300
  probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
 
301
  probs = probs[0]
302
  pred_idx = int(np.argmax(probs))
 
303
  predicted_class = CLASS_NAMES[pred_idx]
304
  confidence = float(probs[pred_idx])
 
305
  prob_dict = {CLASS_NAMES[i]: float(probs[i]) for i in range(len(CLASS_NAMES))}
 
306
  return predicted_class, confidence, prob_dict, pred_idx
307
 
 
308
  print("βœ… Inference pipeline ready")
309
 
310
+ def gradio_predict(image, current_efficiency, time_horizon):
311
+ if image is None:
312
+ return None, None, None, None, "Please upload an image to analyze.", ""
 
 
313
 
314
+ pred_class, confidence, prob_dict, pred_idx = predict_image(image)
315
  heatmap = get_gradcam_heatmap(image, pred_idx)
316
  heatmap_overlay = create_heatmap_overlay(image, heatmap)
317
 
318
+ maintenance_report = format_maintenance_report(pred_class, confidence)
319
+ timeline = predict_degradation(pred_class, current_efficiency, int(time_horizon))
320
+ degradation_report = format_degradation_prediction(timeline)
321
+
322
+ return pred_class, f"{confidence * 100:.2f}%", prob_dict, heatmap_overlay, maintenance_report, degradation_report
323
+
324
+ # Custom CSS for dark neutral theme
325
+ custom_css = """
326
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
327
+
328
+ .gradio-container {
329
+ font-family: 'Inter', sans-serif !important;
330
+ background-color: #0a0a0a !important;
331
+ }
332
+
333
+ .main-header {
334
+ text-align: center;
335
+ background: linear-gradient(135deg, #525252 0%, #404040 100%);
336
+ padding: 40px;
337
+ border-radius: 15px;
338
+ color: #fafafa;
339
+ margin-bottom: 30px;
340
+ border: 1px solid #404040;
341
+ }
342
+
343
+ .upload-section {
344
+ background: #171717;
345
+ padding: 25px;
346
+ border-radius: 12px;
347
+ border: 1px solid #262626;
348
+ }
349
+
350
+ .dark {
351
+ background-color: #0a0a0a !important;
352
+ }
353
+
354
+ /* Override Gradio's default backgrounds */
355
+ .gr-box, .gr-form, .gr-panel {
356
+ background-color: #171717 !important;
357
+ border-color: #262626 !important;
358
+ }
359
+
360
+ .gr-input, .gr-text-input {
361
+ background-color: #0a0a0a !important;
362
+ border-color: #404040 !important;
363
+ color: #fafafa !important;
364
+ }
365
+
366
+ .gr-button {
367
+ background: linear-gradient(135deg, #525252 0%, #404040 100%) !important;
368
+ color: #fafafa !important;
369
+ border: 1px solid #404040 !important;
370
+ }
371
+
372
+ .gr-button:hover {
373
+ background: linear-gradient(135deg, #737373 0%, #525252 100%) !important;
374
+ }
375
+
376
+ label {
377
+ color: #d4d4d4 !important;
378
+ }
379
+
380
+ .gr-prose {
381
+ color: #d4d4d4 !important;
382
+ }
383
+ """
384
+
385
+ with gr.Blocks(css=custom_css, theme=gr.themes.Default(primary_hue="neutral", secondary_hue="neutral")) as iface:
386
+ gr.HTML("""
387
+ <div class="main-header">
388
+ <h1 style="margin: 0; font-size: 42px; font-weight: 700;">β˜€οΈ Solar Panel AI Diagnostics</h1>
389
+ <p style="margin: 10px 0 0 0; font-size: 18px; opacity: 0.95;">Intelligent defect detection, maintenance planning & performance forecasting</p>
390
+ </div>
391
+ """)
392
+
393
+ with gr.Row():
394
+ with gr.Column(scale=1):
395
+ gr.HTML('<div class="upload-section">')
396
+ input_image = gr.Image(
397
+ type="pil",
398
+ label="πŸ“Έ Upload Solar Panel Image",
399
+ height=300
400
+ )
401
+ gr.HTML('</div>')
402
+
403
+ with gr.Row():
404
+ current_eff = gr.Slider(
405
+ minimum=50,
406
+ maximum=100,
407
+ value=95,
408
+ step=1,
409
+ label="⚑ Current System Efficiency (%)",
410
+ info="Set your panel's current performance level"
411
+ )
412
+
413
+ with gr.Row():
414
+ time_horiz = gr.Slider(
415
+ minimum=3,
416
+ maximum=24,
417
+ value=12,
418
+ step=3,
419
+ label="πŸ“… Forecast Period (months)",
420
+ info="Choose prediction time horizon"
421
+ )
422
+
423
+ predict_btn = gr.Button(
424
+ "πŸ” Analyze Solar Panel",
425
+ variant="primary",
426
+ size="lg",
427
+ scale=1
428
+ )
429
+
430
+ with gr.Column(scale=1):
431
+ with gr.Group():
432
+ pred_class = gr.Textbox(
433
+ label="🎯 Detected Condition",
434
+ interactive=False,
435
+ container=True
436
+ )
437
+ confidence = gr.Textbox(
438
+ label="πŸ“Š Confidence Score",
439
+ interactive=False,
440
+ container=True
441
+ )
442
+
443
+ prob_dist = gr.Label(
444
+ label="πŸ“ˆ Classification Probabilities",
445
+ num_top_classes=6
446
+ )
447
+
448
+ heatmap_img = gr.Image(
449
+ type="pil",
450
+ label="πŸ”₯ AI Attention Heatmap",
451
+ height=300
452
+ )
453
+
454
+ with gr.Row():
455
+ with gr.Column():
456
+ maintenance_output = gr.HTML(label="Maintenance Report")
457
+
458
+ with gr.Row():
459
+ with gr.Column():
460
+ degradation_output = gr.HTML(label="Degradation Forecast")
461
+
462
+ predict_btn.click(
463
+ fn=gradio_predict,
464
+ inputs=[input_image, current_eff, time_horiz],
465
+ outputs=[pred_class, confidence, prob_dist, heatmap_img,
466
+ maintenance_output, degradation_output]
467
+ )
468
+
469
+ gr.HTML("""
470
+ <div style="background: #171717; padding: 30px; border-radius: 12px; margin-top: 30px; border: 1px solid #262626;">
471
+ <h3 style="color: #fafafa; margin-top: 0;">πŸ“– How to Use This System</h3>
472
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-top: 20px;">
473
+ <div style="background: #0a0a0a; padding: 20px; border-radius: 8px; border: 1px solid #262626;">
474
+ <h4 style="color: #a3a3a3; margin-top: 0;">1️⃣ Upload Image</h4>
475
+ <p style="color: #737373; font-size: 14px; line-height: 1.6;">Take or upload a photo of your solar panel (thermal, infrared, or RGB)</p>
476
+ </div>
477
+ <div style="background: #0a0a0a; padding: 20px; border-radius: 8px; border: 1px solid #262626;">
478
+ <h4 style="color: #a3a3a3; margin-top: 0;">2️⃣ Set Parameters</h4>
479
+ <p style="color: #737373; font-size: 14px; line-height: 1.6;">Adjust current efficiency and forecast timeframe</p>
480
+ </div>
481
+ <div style="background: #0a0a0a; padding: 20px; border-radius: 8px; border: 1px solid #262626;">
482
+ <h4 style="color: #a3a3a3; margin-top: 0;">3️⃣ Analyze</h4>
483
+ <p style="color: #737373; font-size: 14px; line-height: 1.6;">Click analyze to get comprehensive diagnostics</p>
484
+ </div>
485
+ <div style="background: #0a0a0a; padding: 20px; border-radius: 8px; border: 1px solid #262626;">
486
+ <h4 style="color: #a3a3a3; margin-top: 0;">4️⃣ Review & Act</h4>
487
+ <p style="color: #737373; font-size: 14px; line-height: 1.6;">Check maintenance actions and follow recommendations</p>
488
+ </div>
489
+ </div>
490
+
491
+ <div style="margin-top: 25px; padding: 20px; background: #0a0a0a; border-radius: 8px; border: 1px solid #262626;">
492
+ <h4 style="color: #fafafa; margin-top: 0;">⚑ Detection Capabilities</h4>
493
+ <p style="color: #a3a3a3; font-size: 14px; line-height: 1.8;">
494
+ This AI system detects <strong style="color: #d4d4d4;">6 types of solar panel conditions</strong>: Bird droppings, Clean panels,
495
+ Dust accumulation, Electrical damage, Physical damage, and Snow coverage. The attention heatmap
496
+ visualizes which areas influenced the AI's decision-making process.
497
+ </p>
498
+ </div>
499
+ </div>
500
+ """)
501
 
502
  iface.launch(debug=True)