Spaces:
Sleeping
Sleeping
| 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() | |