Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -19,16 +19,17 @@ def load_model():
|
|
| 19 |
|
| 20 |
model = load_model()
|
| 21 |
|
| 22 |
-
# Fault detection
|
| 23 |
-
def detect_faults(frame, results):
|
| 24 |
faults = {"Thermal Fault": False, "Dust Fault": False, "Power Generation Fault": False}
|
|
|
|
| 25 |
annotated_frame = frame.copy()
|
| 26 |
|
| 27 |
for result in results:
|
| 28 |
boxes = result.boxes
|
| 29 |
for box in boxes:
|
| 30 |
x1, y1, x2, y2 = map(int, box.xyxy[0])
|
| 31 |
-
conf = box.conf[0]
|
| 32 |
cls = int(box.cls[0])
|
| 33 |
|
| 34 |
roi = frame[y1:y2, x1:x2]
|
|
@@ -47,13 +48,20 @@ def detect_faults(frame, results):
|
|
| 47 |
else:
|
| 48 |
continue
|
| 49 |
|
| 50 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
overlay = annotated_frame.copy()
|
| 52 |
alpha = 0.3
|
| 53 |
cv2.rectangle(overlay, (x1, y1), (x2, y2), color, -1)
|
| 54 |
cv2.addWeighted(overlay, alpha, annotated_frame, 1 - alpha, 0, annotated_frame)
|
| 55 |
-
|
| 56 |
-
# Border and label
|
| 57 |
cv2.rectangle(annotated_frame, (x1, y1), (x2, y2), color, 2)
|
| 58 |
cv2.putText(annotated_frame, f"{label} ({mean_intensity:.1f})", (x1, y1 - 10),
|
| 59 |
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
|
|
@@ -61,14 +69,14 @@ def detect_faults(frame, results):
|
|
| 61 |
if faults["Thermal Fault"] or faults["Dust Fault"]:
|
| 62 |
faults["Power Generation Fault"] = True
|
| 63 |
|
| 64 |
-
return annotated_frame, faults
|
| 65 |
|
| 66 |
# Video processing
|
| 67 |
def process_video(video_path):
|
| 68 |
cap = cv2.VideoCapture(video_path)
|
| 69 |
if not cap.isOpened():
|
| 70 |
st.error("Failed to open video.")
|
| 71 |
-
return None, None
|
| 72 |
|
| 73 |
fps = int(cap.get(cv2.CAP_PROP_FPS))
|
| 74 |
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
|
@@ -80,6 +88,7 @@ def process_video(video_path):
|
|
| 80 |
|
| 81 |
frame_count = 0
|
| 82 |
video_faults = {"Thermal Fault": False, "Dust Fault": False, "Power Generation Fault": False}
|
|
|
|
| 83 |
process_every_n_frames = fps # 1 frame per second
|
| 84 |
|
| 85 |
with st.spinner("Processing video..."):
|
|
@@ -90,16 +99,17 @@ def process_video(video_path):
|
|
| 90 |
break
|
| 91 |
|
| 92 |
if frame_count % process_every_n_frames == 0:
|
| 93 |
-
resized = cv2.resize(frame, (640, 480))
|
| 94 |
frame_rgb = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)
|
| 95 |
results = model(frame_rgb, verbose=False)
|
| 96 |
|
| 97 |
-
annotated_frame, faults = detect_faults(frame, results)
|
|
|
|
| 98 |
|
| 99 |
for fault in video_faults:
|
| 100 |
video_faults[fault] |= faults[fault]
|
| 101 |
else:
|
| 102 |
-
annotated_frame = frame
|
| 103 |
|
| 104 |
out.write(annotated_frame)
|
| 105 |
frame_count += 1
|
|
@@ -107,7 +117,7 @@ def process_video(video_path):
|
|
| 107 |
|
| 108 |
cap.release()
|
| 109 |
out.release()
|
| 110 |
-
return output_path, video_faults
|
| 111 |
|
| 112 |
# File uploader
|
| 113 |
uploaded_file = st.file_uploader("Upload a thermal video", type=["mp4"])
|
|
@@ -119,7 +129,7 @@ if uploaded_file:
|
|
| 119 |
|
| 120 |
st.video(temp_input_path)
|
| 121 |
|
| 122 |
-
output_path, video_faults = process_video(temp_input_path)
|
| 123 |
|
| 124 |
if output_path:
|
| 125 |
st.subheader("Detection Results")
|
|
@@ -140,6 +150,19 @@ if uploaded_file:
|
|
| 140 |
else:
|
| 141 |
st.success("No faults detected. The system seems to be functioning properly.")
|
| 142 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
os.unlink(output_path)
|
| 144 |
os.unlink(temp_input_path)
|
| 145 |
|
|
|
|
| 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]
|
|
|
|
| 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)
|
|
|
|
| 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))
|
|
|
|
| 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..."):
|
|
|
|
| 99 |
break
|
| 100 |
|
| 101 |
if frame_count % process_every_n_frames == 0:
|
| 102 |
+
resized = cv2.resize(frame, (640, 480))
|
| 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 |
|
| 114 |
out.write(annotated_frame)
|
| 115 |
frame_count += 1
|
|
|
|
| 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"])
|
|
|
|
| 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")
|
|
|
|
| 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 |
|