Naveenkumar1546 commited on
Commit
384126b
·
verified ·
1 Parent(s): 4cd65a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -79
app.py CHANGED
@@ -1,95 +1,84 @@
 
 
 
 
 
 
1
  import streamlit as st
2
  import cv2
3
  import numpy as np
4
  import tempfile
5
  import os
6
  import torch
 
 
7
  from ultralytics import YOLO
8
 
9
- # Set page config
10
  st.set_page_config(page_title="Solar Panel Fault Detection", layout="wide")
11
- st.title("Solar Panel Fault Detection (Optimized)")
12
- st.write("Upload a thermal video (MP4) to detect thermal, dust, and power generation faults.")
13
 
14
- # Load YOLO model
15
  @st.cache_resource
16
  def load_model():
17
- model = YOLO("yolov5s.pt") # Replace with your custom-trained model if available
18
- return model
19
 
20
  model = load_model()
21
 
22
- # Fault detection with frame & location tracking
23
- def detect_faults(frame, results, frame_number):
24
- faults = {"Thermal Fault": False, "Dust Fault": False, "Power Generation Fault": False}
25
- fault_locations = []
26
  annotated_frame = frame.copy()
27
 
28
  for result in results:
29
- boxes = result.boxes
30
- for box in boxes:
31
  x1, y1, x2, y2 = map(int, box.xyxy[0])
32
- conf = float(box.conf[0])
33
- cls = int(box.cls[0])
34
-
35
  roi = frame[y1:y2, x1:x2]
36
  if roi.size == 0:
37
  continue
38
  mean_intensity = np.mean(roi)
39
 
40
  if mean_intensity > 200:
41
- faults["Thermal Fault"] = True
42
- color = (255, 0, 0)
43
  label = "Thermal Fault"
 
44
  elif mean_intensity < 100:
45
- faults["Dust Fault"] = True
46
- color = (0, 255, 0)
47
  label = "Dust Fault"
 
48
  else:
49
  continue
50
 
51
- # Track location
52
- fault_locations.append({
53
- "frame": frame_number,
54
- "label": label,
55
- "confidence": round(conf, 2),
56
- "intensity": round(mean_intensity, 2),
57
- "box": (x1, y1, x2, y2)
58
  })
59
 
60
- # Annotate
61
- overlay = annotated_frame.copy()
62
- alpha = 0.3
63
- cv2.rectangle(overlay, (x1, y1), (x2, y2), color, -1)
64
- cv2.addWeighted(overlay, alpha, annotated_frame, 1 - alpha, 0, annotated_frame)
65
  cv2.rectangle(annotated_frame, (x1, y1), (x2, y2), color, 2)
66
- cv2.putText(annotated_frame, f"{label} ({mean_intensity:.1f})", (x1, y1 - 10),
67
- cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
68
-
69
- if faults["Thermal Fault"] or faults["Dust Fault"]:
70
- faults["Power Generation Fault"] = True
71
 
72
- return annotated_frame, faults, fault_locations
73
 
74
- # Video processing
75
  def process_video(video_path):
76
  cap = cv2.VideoCapture(video_path)
77
  if not cap.isOpened():
78
  st.error("Failed to open video.")
79
- return None, None, None
80
 
81
  fps = int(cap.get(cv2.CAP_PROP_FPS))
82
  total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
83
  width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
84
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
85
 
 
 
 
86
  output_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name
87
  out = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
88
 
 
 
89
  frame_count = 0
90
- video_faults = {"Thermal Fault": False, "Dust Fault": False, "Power Generation Fault": False}
91
- all_fault_locations = []
92
- process_every_n_frames = fps # 1 frame per second
93
 
94
  with st.spinner("Processing video..."):
95
  progress = st.progress(0)
@@ -103,11 +92,16 @@ def process_video(video_path):
103
  frame_rgb = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)
104
  results = model(frame_rgb, verbose=False)
105
 
106
- annotated_frame, faults, locations = detect_faults(frame, results, frame_count)
107
- all_fault_locations.extend(locations)
108
 
109
- for fault in video_faults:
110
- video_faults[fault] |= faults[fault]
 
 
 
 
 
111
  else:
112
  annotated_frame = frame
113
 
@@ -117,11 +111,19 @@ def process_video(video_path):
117
 
118
  cap.release()
119
  out.release()
120
- return output_path, video_faults, all_fault_locations
121
 
122
- # File uploader
123
- uploaded_file = st.file_uploader("Upload a thermal video", type=["mp4"])
124
 
 
 
 
 
 
 
 
 
 
 
125
  if uploaded_file:
126
  temp_input_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
127
  with open(temp_input_path, "wb") as f:
@@ -129,42 +131,38 @@ if uploaded_file:
129
 
130
  st.video(temp_input_path)
131
 
132
- output_path, video_faults, fault_locations = process_video(temp_input_path)
133
 
134
  if output_path:
135
  st.subheader("Detection Results")
136
  st.video(output_path)
137
- st.write("### Detected Faults:")
138
- for fault, detected in video_faults.items():
139
- color = "red" if detected else "green"
140
- st.markdown(f"- **{fault}**: <span style='color:{color}'>{'Detected' if detected else 'Not Detected'}</span>", unsafe_allow_html=True)
141
-
142
- if any(video_faults.values()):
143
- st.subheader("Recommendations")
144
- if video_faults["Thermal Fault"]:
145
- st.write("- Check for overheating components.")
146
- if video_faults["Dust Fault"]:
147
- st.write("- Clean dust from solar panel surface.")
148
- if video_faults["Power Generation Fault"]:
149
- st.write("- Investigate potential efficiency issues.")
 
 
 
 
 
 
 
 
 
150
  else:
151
- st.success("No faults detected. The system seems to be functioning properly.")
152
-
153
- # Display fault locations
154
- if fault_locations:
155
- st.subheader("📍 Fault Locations in Video")
156
- st.dataframe([
157
- {
158
- "Frame": loc["frame"],
159
- "Fault Type": loc["label"],
160
- "Confidence": loc["confidence"],
161
- "Intensity": loc["intensity"],
162
- "Box": f"{loc['box']}"
163
- } for loc in fault_locations
164
- ])
165
 
166
  os.unlink(output_path)
167
- os.unlink(temp_input_path)
168
 
169
  st.markdown("---")
170
- st.caption("Built with Streamlit + YOLOv5 (Ultralytics) for fast fault detection.")
 
1
+ # Full code integrating:
2
+ # - Fault timestamps
3
+ # - CSV export
4
+ # - Clickable snapshots
5
+ # - Heatmap overlay
6
+
7
  import streamlit as st
8
  import cv2
9
  import numpy as np
10
  import tempfile
11
  import os
12
  import torch
13
+ import pandas as pd
14
+ import base64
15
  from ultralytics import YOLO
16
 
 
17
  st.set_page_config(page_title="Solar Panel Fault Detection", layout="wide")
18
+ st.title("Solar Panel Fault Detection (Enhanced)")
19
+ st.write("Upload a thermal video (MP4) to detect faults with location, snapshots, and export options.")
20
 
 
21
  @st.cache_resource
22
  def load_model():
23
+ return YOLO("yolov5s.pt")
 
24
 
25
  model = load_model()
26
 
27
+ def detect_faults(frame, results, frame_idx, fps):
28
+ faults_found = []
 
 
29
  annotated_frame = frame.copy()
30
 
31
  for result in results:
32
+ for box in result.boxes:
 
33
  x1, y1, x2, y2 = map(int, box.xyxy[0])
 
 
 
34
  roi = frame[y1:y2, x1:x2]
35
  if roi.size == 0:
36
  continue
37
  mean_intensity = np.mean(roi)
38
 
39
  if mean_intensity > 200:
 
 
40
  label = "Thermal Fault"
41
+ color = (255, 0, 0)
42
  elif mean_intensity < 100:
 
 
43
  label = "Dust Fault"
44
+ color = (0, 255, 0)
45
  else:
46
  continue
47
 
48
+ timestamp = round(frame_idx / fps, 2)
49
+ faults_found.append({
50
+ "Frame": frame_idx,
51
+ "Time (s)": timestamp,
52
+ "Fault Type": label,
53
+ "X1": x1, "Y1": y1, "X2": x2, "Y2": y2
 
54
  })
55
 
 
 
 
 
 
56
  cv2.rectangle(annotated_frame, (x1, y1), (x2, y2), color, 2)
57
+ cv2.putText(annotated_frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
 
 
 
 
58
 
59
+ return annotated_frame, faults_found
60
 
 
61
  def process_video(video_path):
62
  cap = cv2.VideoCapture(video_path)
63
  if not cap.isOpened():
64
  st.error("Failed to open video.")
65
+ return None, None, None, None
66
 
67
  fps = int(cap.get(cv2.CAP_PROP_FPS))
68
  total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
69
  width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
70
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
71
 
72
+ heatmap = np.zeros((height, width), dtype=np.float32)
73
+ snapshot_dir = tempfile.mkdtemp()
74
+
75
  output_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name
76
  out = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (width, height))
77
 
78
+ fault_log = []
79
+ snapshots = []
80
  frame_count = 0
81
+ process_every_n_frames = fps
 
 
82
 
83
  with st.spinner("Processing video..."):
84
  progress = st.progress(0)
 
92
  frame_rgb = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)
93
  results = model(frame_rgb, verbose=False)
94
 
95
+ annotated_frame, faults_found = detect_faults(frame, results, frame_count, fps)
96
+ fault_log.extend(faults_found)
97
 
98
+ if faults_found:
99
+ snapshot_path = os.path.join(snapshot_dir, f"frame_{frame_count}.jpg")
100
+ cv2.imwrite(snapshot_path, annotated_frame)
101
+ snapshots.append(snapshot_path)
102
+
103
+ for fault in faults_found:
104
+ heatmap[fault["Y1"]:fault["Y2"], fault["X1"]:fault["X2"]] += 1
105
  else:
106
  annotated_frame = frame
107
 
 
111
 
112
  cap.release()
113
  out.release()
 
114
 
115
+ return output_path, fault_log, snapshots, heatmap
 
116
 
117
+ def get_heatmap_overlay(heatmap, base_frame):
118
+ normalized = cv2.normalize(heatmap, None, 0, 255, cv2.NORM_MINMAX)
119
+ heatmap_img = cv2.applyColorMap(normalized.astype(np.uint8), cv2.COLORMAP_JET)
120
+ overlay = cv2.addWeighted(base_frame, 0.6, heatmap_img, 0.4, 0)
121
+ return overlay
122
+
123
+ def convert_df_to_csv(df):
124
+ return df.to_csv(index=False).encode('utf-8')
125
+
126
+ uploaded_file = st.file_uploader("Upload a thermal video", type=["mp4"])
127
  if uploaded_file:
128
  temp_input_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
129
  with open(temp_input_path, "wb") as f:
 
131
 
132
  st.video(temp_input_path)
133
 
134
+ output_path, fault_log, snapshots, heatmap = process_video(temp_input_path)
135
 
136
  if output_path:
137
  st.subheader("Detection Results")
138
  st.video(output_path)
139
+
140
+ if fault_log:
141
+ df = pd.DataFrame(fault_log)
142
+ st.write("### Detected Faults Table")
143
+ st.dataframe(df)
144
+
145
+ st.download_button("Download Fault Log as CSV", data=convert_df_to_csv(df), file_name="fault_log.csv", mime="text/csv")
146
+
147
+ st.write("### Snapshots of Faults")
148
+ cols = st.columns(4)
149
+ for i, path in enumerate(snapshots):
150
+ with cols[i % 4]:
151
+ st.image(path, use_column_width=True)
152
+
153
+ st.write("### Fault Location Heatmap")
154
+ cap = cv2.VideoCapture(temp_input_path)
155
+ ret, frame = cap.read()
156
+ cap.release()
157
+ if ret:
158
+ heatmap_overlay = get_heatmap_overlay(heatmap, frame)
159
+ st.image(heatmap_overlay, caption="Fault Heatmap", use_column_width=True)
160
+
161
  else:
162
+ st.success("No faults detected.")
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
  os.unlink(output_path)
165
+ os.unlink(temp_input_path)
166
 
167
  st.markdown("---")
168
+ st.caption("Built with Streamlit + YOLOv5 (Ultralytics) + OpenCV")