Spaces:
Sleeping
Sleeping
File size: 4,948 Bytes
922cc97 4a600b6 922cc97 4a600b6 922cc97 4a600b6 922cc97 4a600b6 922cc97 4a600b6 922cc97 4a600b6 922cc97 d08a8b7 4a600b6 922cc97 4a600b6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
import cv2
import mediapipe as mp
import numpy as np
from datetime import datetime
import os
import gradio as gr
# Create folder for dangerous frames
os.makedirs("dangerous_frames", exist_ok=True)
dangerous_move_count = 0
mp_pose = mp.solutions.pose
mp_drawing = mp.solutions.drawing_utils
HOLD_NECK_THRESHOLD = 0.1 # Wrist-to-neck distance threshold for hold neck
# ---------------- Detection Logic ----------------
def detect_dangerous_move(landmarks):
left_wrist = landmarks[15]
right_wrist = landmarks[16]
left_elbow = landmarks[13]
right_elbow = landmarks[14]
left_shoulder = landmarks[11]
right_shoulder = landmarks[12]
left_hip = landmarks[23]
right_hip = landmarks[24]
nose = landmarks[0]
left_ankle = landmarks[27]
right_ankle = landmarks[28]
# Neck midpoint
neck_x = (left_shoulder.x + right_shoulder.x) / 2
neck_y = (left_shoulder.y + right_shoulder.y) / 2
# Distances from wrists to neck
left_wrist_to_neck = np.sqrt((left_wrist.x - neck_x) ** 2 + (left_wrist.y - neck_y) ** 2)
right_wrist_to_neck = np.sqrt((right_wrist.x - neck_x) ** 2 + (right_wrist.y - neck_y) ** 2)
# Punch
punch_left = left_wrist.y < left_shoulder.y and left_elbow.y > left_wrist.y
punch_right = right_wrist.y < right_shoulder.y and right_elbow.y > right_wrist.y
# Kick
kick_left = left_ankle.y < left_hip.y
kick_right = right_ankle.y < right_hip.y
# Block
block_left = left_elbow.y < left_shoulder.y and abs(left_wrist.x - nose.x) < 0.15
block_right = right_elbow.y < right_shoulder.y and abs(right_wrist.x - nose.x) < 0.15
blocking = block_left and block_right
# Hold neck
hold_neck = (left_wrist_to_neck < HOLD_NECK_THRESHOLD) or (right_wrist_to_neck < HOLD_NECK_THRESHOLD)
# Weapon raise
weapon_left = (left_wrist.y < left_shoulder.y - 0.1) and (left_wrist.z < left_shoulder.z)
weapon_right = (right_wrist.y < right_shoulder.y - 0.1) and (right_wrist.z < right_shoulder.z)
if hold_neck:
return "Hold Neck (Dangerous)", True
elif punch_left or punch_right:
return "Punching (Dangerous)", True
elif kick_left or kick_right:
return "Kicking (Dangerous)", True
elif blocking:
return "Blocking (Defensive)", False
elif weapon_left or weapon_right:
return "Weapon Raised (Dangerous)", True
else:
return "Normal", False
# ---------------- Main Gradio Function ----------------
def process_video(video_path):
global dangerous_move_count
dangerous_move_count = 0
cap = cv2.VideoCapture(video_path)
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
out = cv2.VideoWriter("output.mp4", fourcc, 20.0, (640, 480))
with mp_pose.Pose(min_detection_confidence=0.5, min_tracking_confidence=0.5) as pose:
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
img_h, img_w, _ = frame.shape
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
pose_results = pose.process(rgb)
gesture = "No Person"
danger_move = False
landmarks = None
if pose_results.pose_landmarks:
landmarks = pose_results.pose_landmarks.landmark
gesture, danger_move = detect_dangerous_move(landmarks)
mp_drawing.draw_landmarks(frame, pose_results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
if landmarks:
xs = [int(lm.x * img_w) for lm in landmarks]
ys = [int(lm.y * img_h) for lm in landmarks]
x_min, x_max = min(xs), max(xs)
y_min, y_max = min(ys), max(ys)
box_color = (0, 0, 255) if danger_move else (0, 255, 0)
cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), box_color, 3)
cv2.putText(frame, gesture, (x_min, y_min - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, box_color, 2)
if danger_move:
dangerous_move_count += 1
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
cv2.imwrite(f"dangerous_frames/danger_{timestamp}.jpg", frame)
cv2.putText(frame, f"Dangerous Moves: {dangerous_move_count}", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
out.write(cv2.resize(frame, (640, 480)))
cap.release()
out.release()
return "output.mp4"
# ---------------- Gradio Interface ----------------
demo = gr.Interface(
fn=process_video,
inputs=gr.Video(), # <-- FIXED (removed type="filepath")
outputs=gr.Video(),
title="⚠️ Action Recognition System (Danger Detection)",
description="Upload a video and the system will detect dangerous actions like punching, kicking, hold-neck, blocking, and weapon raise."
)
if __name__ == "__main__":
demo.launch()
|