Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -39,6 +39,7 @@ CONFIG = {
|
|
| 39 |
},
|
| 40 |
"PUBLIC_URL_BASE": "https://huggingface.co/spaces/PrashanthB461/AI_Safety_Demo1/resolve/main/static/output/",
|
| 41 |
"FRAME_SKIP": 15,
|
|
|
|
| 42 |
"CONFIDENCE_THRESHOLD": 0.5
|
| 43 |
}
|
| 44 |
|
|
@@ -209,7 +210,7 @@ def calculate_safety_score(violations):
|
|
| 209 |
score -= penalties[v["violation"]]
|
| 210 |
return max(score, 0)
|
| 211 |
|
| 212 |
-
def process_video(video_data
|
| 213 |
try:
|
| 214 |
video_path = os.path.join(CONFIG["OUTPUT_DIR"], f"temp_{int(time.time())}.mp4")
|
| 215 |
with open(video_path, "wb") as f:
|
|
@@ -220,11 +221,11 @@ def process_video(video_data, progress_callback=None):
|
|
| 220 |
if not video.isOpened():
|
| 221 |
raise ValueError("Could not open video file")
|
| 222 |
|
| 223 |
-
total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
|
| 224 |
-
fps = video.get(cv2.CAP_PROP_FPS)
|
| 225 |
-
|
| 226 |
violations, snapshots = [], []
|
| 227 |
frame_count = 0
|
|
|
|
|
|
|
|
|
|
| 228 |
snapshot_taken = {"no_helmet": False, "no_harness": False, "unsafe_posture": False}
|
| 229 |
|
| 230 |
while True:
|
|
@@ -234,10 +235,12 @@ def process_video(video_data, progress_callback=None):
|
|
| 234 |
|
| 235 |
if frame_count % CONFIG["FRAME_SKIP"] != 0:
|
| 236 |
frame_count += 1
|
| 237 |
-
if progress_callback:
|
| 238 |
-
progress_callback(min(frame_count / total_frames, 1.0))
|
| 239 |
continue
|
| 240 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
results = model(frame, device=device)
|
| 242 |
seen_violations = set()
|
| 243 |
for result in results:
|
|
@@ -252,22 +255,11 @@ def process_video(video_data, progress_callback=None):
|
|
| 252 |
continue
|
| 253 |
seen_violations.add(label)
|
| 254 |
|
| 255 |
-
xywh_array = box.xywh.cpu().numpy()
|
| 256 |
-
if xywh_array.size == 0 or xywh_array.shape[1] < 4:
|
| 257 |
-
xyxy_array = box.xyxy.cpu().numpy()
|
| 258 |
-
if xyxy_array.size == 0 or xyxy_array.shape[1] < 4:
|
| 259 |
-
logger.warning("No valid bounding box info found, skipping box")
|
| 260 |
-
continue
|
| 261 |
-
xmin, ymin, xmax, ymax = xyxy_array[0]
|
| 262 |
-
width = xmax - xmin
|
| 263 |
-
height = ymax - ymin
|
| 264 |
-
xywh_array = np.array([[xmin, ymin, width, height]])
|
| 265 |
-
|
| 266 |
violation = {
|
| 267 |
"frame": frame_count,
|
| 268 |
"violation": label,
|
| 269 |
"confidence": round(conf, 2),
|
| 270 |
-
"bounding_box": [round(x, 2) for x in
|
| 271 |
"timestamp": frame_count / fps
|
| 272 |
}
|
| 273 |
violations.append(violation)
|
|
@@ -287,9 +279,6 @@ def process_video(video_data, progress_callback=None):
|
|
| 287 |
|
| 288 |
frame_count += 1
|
| 289 |
|
| 290 |
-
if progress_callback:
|
| 291 |
-
progress_callback(min(frame_count / total_frames, 1.0))
|
| 292 |
-
|
| 293 |
video.release()
|
| 294 |
os.remove(video_path)
|
| 295 |
|
|
@@ -327,18 +316,22 @@ def process_video(video_data, progress_callback=None):
|
|
| 327 |
"message": f"Error processing video: {e}"
|
| 328 |
}
|
| 329 |
|
| 330 |
-
def gradio_interface(video_file
|
| 331 |
if not video_file:
|
| 332 |
return "No file uploaded.", "", "No file uploaded.", "", ""
|
| 333 |
-
|
| 334 |
try:
|
|
|
|
|
|
|
|
|
|
| 335 |
with open(video_file, "rb") as f:
|
| 336 |
video_data = f.read()
|
| 337 |
|
| 338 |
-
result = process_video(video_data
|
| 339 |
|
| 340 |
if result.get("message"):
|
| 341 |
-
|
|
|
|
|
|
|
| 342 |
|
| 343 |
violation_table = "No violations detected."
|
| 344 |
if result["violations"]:
|
|
@@ -360,7 +353,7 @@ def gradio_interface(video_file, progress=gr.Progress(track_tqdm=True)):
|
|
| 360 |
for s in result["snapshots"]
|
| 361 |
)
|
| 362 |
|
| 363 |
-
|
| 364 |
violation_table,
|
| 365 |
f"Safety Score: {result['score']}%",
|
| 366 |
snapshots_text,
|
|
@@ -369,7 +362,7 @@ def gradio_interface(video_file, progress=gr.Progress(track_tqdm=True)):
|
|
| 369 |
)
|
| 370 |
except Exception as e:
|
| 371 |
logger.error(f"Error in Gradio interface: {e}")
|
| 372 |
-
|
| 373 |
|
| 374 |
interface = gr.Interface(
|
| 375 |
fn=gradio_interface,
|
|
@@ -383,7 +376,7 @@ interface = gr.Interface(
|
|
| 383 |
],
|
| 384 |
title="Worksite Safety Violation Analyzer",
|
| 385 |
description="Upload site videos to detect safety violations (No Helmet Violation, No Harness Violation, Unsafe Posture Violation). Non-violations are ignored.",
|
| 386 |
-
|
| 387 |
)
|
| 388 |
|
| 389 |
if __name__ == "__main__":
|
|
|
|
| 39 |
},
|
| 40 |
"PUBLIC_URL_BASE": "https://huggingface.co/spaces/PrashanthB461/AI_Safety_Demo1/resolve/main/static/output/",
|
| 41 |
"FRAME_SKIP": 15,
|
| 42 |
+
"MAX_PROCESSING_TIME": 30, # seconds
|
| 43 |
"CONFIDENCE_THRESHOLD": 0.5
|
| 44 |
}
|
| 45 |
|
|
|
|
| 210 |
score -= penalties[v["violation"]]
|
| 211 |
return max(score, 0)
|
| 212 |
|
| 213 |
+
def process_video(video_data):
|
| 214 |
try:
|
| 215 |
video_path = os.path.join(CONFIG["OUTPUT_DIR"], f"temp_{int(time.time())}.mp4")
|
| 216 |
with open(video_path, "wb") as f:
|
|
|
|
| 221 |
if not video.isOpened():
|
| 222 |
raise ValueError("Could not open video file")
|
| 223 |
|
|
|
|
|
|
|
|
|
|
| 224 |
violations, snapshots = [], []
|
| 225 |
frame_count = 0
|
| 226 |
+
start_time = time.time()
|
| 227 |
+
fps = video.get(cv2.CAP_PROP_FPS)
|
| 228 |
+
|
| 229 |
snapshot_taken = {"no_helmet": False, "no_harness": False, "unsafe_posture": False}
|
| 230 |
|
| 231 |
while True:
|
|
|
|
| 235 |
|
| 236 |
if frame_count % CONFIG["FRAME_SKIP"] != 0:
|
| 237 |
frame_count += 1
|
|
|
|
|
|
|
| 238 |
continue
|
| 239 |
|
| 240 |
+
if time.time() - start_time > CONFIG["MAX_PROCESSING_TIME"]:
|
| 241 |
+
logger.info("Processing time limit of 30 seconds reached")
|
| 242 |
+
break
|
| 243 |
+
|
| 244 |
results = model(frame, device=device)
|
| 245 |
seen_violations = set()
|
| 246 |
for result in results:
|
|
|
|
| 255 |
continue
|
| 256 |
seen_violations.add(label)
|
| 257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
violation = {
|
| 259 |
"frame": frame_count,
|
| 260 |
"violation": label,
|
| 261 |
"confidence": round(conf, 2),
|
| 262 |
+
"bounding_box": [round(x, 2) for x in box.xywh.cpu().numpy()[0]],
|
| 263 |
"timestamp": frame_count / fps
|
| 264 |
}
|
| 265 |
violations.append(violation)
|
|
|
|
| 279 |
|
| 280 |
frame_count += 1
|
| 281 |
|
|
|
|
|
|
|
|
|
|
| 282 |
video.release()
|
| 283 |
os.remove(video_path)
|
| 284 |
|
|
|
|
| 316 |
"message": f"Error processing video: {e}"
|
| 317 |
}
|
| 318 |
|
| 319 |
+
def gradio_interface(video_file):
|
| 320 |
if not video_file:
|
| 321 |
return "No file uploaded.", "", "No file uploaded.", "", ""
|
|
|
|
| 322 |
try:
|
| 323 |
+
# Show processing message early in the UI
|
| 324 |
+
yield "Processing video... please wait.", "", "", "", ""
|
| 325 |
+
|
| 326 |
with open(video_file, "rb") as f:
|
| 327 |
video_data = f.read()
|
| 328 |
|
| 329 |
+
result = process_video(video_data)
|
| 330 |
|
| 331 |
if result.get("message"):
|
| 332 |
+
# If message present (either no violations or error), show it plainly
|
| 333 |
+
yield result["message"], "", "", "", ""
|
| 334 |
+
return
|
| 335 |
|
| 336 |
violation_table = "No violations detected."
|
| 337 |
if result["violations"]:
|
|
|
|
| 353 |
for s in result["snapshots"]
|
| 354 |
)
|
| 355 |
|
| 356 |
+
yield (
|
| 357 |
violation_table,
|
| 358 |
f"Safety Score: {result['score']}%",
|
| 359 |
snapshots_text,
|
|
|
|
| 362 |
)
|
| 363 |
except Exception as e:
|
| 364 |
logger.error(f"Error in Gradio interface: {e}")
|
| 365 |
+
yield f"Error: {str(e)}", "", "Error in processing.", "", ""
|
| 366 |
|
| 367 |
interface = gr.Interface(
|
| 368 |
fn=gradio_interface,
|
|
|
|
| 376 |
],
|
| 377 |
title="Worksite Safety Violation Analyzer",
|
| 378 |
description="Upload site videos to detect safety violations (No Helmet Violation, No Harness Violation, Unsafe Posture Violation). Non-violations are ignored.",
|
| 379 |
+
allow_flagging="never"
|
| 380 |
)
|
| 381 |
|
| 382 |
if __name__ == "__main__":
|