vu0018 commited on
Commit
015f0f2
·
verified ·
1 Parent(s): ce5aa37

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -99
app.py CHANGED
@@ -1,117 +1,86 @@
 
1
  import cv2
2
  import mediapipe as mp
3
- import numpy as np
4
- import gradio as gr
5
  import tempfile
6
- import shutil
7
  import os
8
 
9
  # Initialize MediaPipe Pose
10
  mp_pose = mp.solutions.pose
11
- mp_drawing = mp.solutions.drawing_utils
12
- pose = mp_pose.Pose(static_image_mode=False,
13
- min_detection_confidence=0.5,
14
- min_tracking_confidence=0.5)
15
-
16
- def calculate_angle(a, b, c):
17
- a = np.array(a)
18
- b = np.array(b)
19
- c = np.array(c)
20
- ba = a - b
21
- bc = c - b
22
- cosine_angle = np.dot(ba, bc) / (np.linalg.norm(ba) * np.linalg.norm(bc))
23
- angle = np.arccos(np.clip(cosine_angle, -1.0, 1.0))
24
- return np.degrees(angle)
25
-
26
- def detect_pose_video(video_path, max_duration=10): # <- 10 seconds limit
27
- try:
28
- if not os.path.exists(video_path):
29
- return None, "Error: Video file does not exist."
30
 
31
- # Copy video to temp file
32
- temp_input = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
33
- temp_input.close()
34
- shutil.copy(video_path, temp_input.name)
 
 
 
 
 
 
 
35
 
36
- cap = cv2.VideoCapture(temp_input.name)
 
37
  if not cap.isOpened():
38
- return None, "Error: Cannot open video file."
39
-
40
- fps = cap.get(cv2.CAP_PROP_FPS) or 20.0
41
- width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH) or 640)
42
- height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) or 480)
43
- max_frames = int(fps * max_duration)
44
-
45
- temp_output = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
46
- temp_output.close()
47
- out_path = temp_output.name
48
- fourcc = cv2.VideoWriter_fourcc(*'mp4v')
49
- out = cv2.VideoWriter(out_path, fourcc, fps, (width, height))
50
-
51
- frame_count = 0
52
- while frame_count < max_frames:
53
- ret, frame = cap.read()
54
- if not ret:
55
- break
56
-
57
- # Resize if too large
58
- max_dim = 640
59
- h, w, _ = frame.shape
60
- if max(h, w) > max_dim:
61
- scale = max_dim / max(h, w)
62
- frame = cv2.resize(frame, (int(w*scale), int(h*scale)))
63
-
64
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
65
- results = pose.process(frame_rgb)
66
-
67
- if results.pose_landmarks:
68
- mp_drawing.draw_landmarks(
69
- frame,
70
- results.pose_landmarks,
71
- mp_pose.POSE_CONNECTIONS,
72
- mp_drawing.DrawingSpec(color=(0,255,0), thickness=2, circle_radius=2),
73
- mp_drawing.DrawingSpec(color=(0,0,255), thickness=2)
74
- )
75
-
76
- # Left elbow angle
77
- landmarks = results.pose_landmarks.landmark
78
- shoulder = [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x * frame.shape[1],
79
- landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y * frame.shape[0]]
80
- elbow = [landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].x * frame.shape[1],
81
- landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].y * frame.shape[0]]
82
- wrist = [landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].x * frame.shape[1],
83
- landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].y * frame.shape[0]]
84
-
85
- angle = calculate_angle(shoulder, elbow, wrist)
86
- cv2.putText(frame, f"Left Elbow: {int(angle)} deg", (20,40),
87
- cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,0), 2)
88
-
89
- out.write(frame)
90
- frame_count += 1
91
 
92
- cap.release()
93
- out.release()
94
- os.remove(temp_input.name) # Clean up input
95
 
96
- return out_path, "Video processed successfully."
 
97
 
98
- except Exception as e:
99
- return None, f"Runtime Error: {str(e)}"
100
 
101
- # Gradio interface with button enable fix
102
- with gr.Blocks() as demo:
103
- gr.Markdown("## Human Pose Estimation on Video\nUpload a video (max 10 seconds). Submit is enabled only after upload.")
 
 
 
 
104
 
105
- video_input = gr.Video(label="Upload Video")
106
- status_output = gr.Textbox(label="Status")
107
- video_output = gr.Video(label="Annotated Video")
108
- submit_btn = gr.Button("Submit", interactive=False)
109
 
110
- # Enable submit button correctly
111
- def enable_submit(video):
112
- return gr.Button.update(interactive=True) if video else gr.Button.update(interactive=False)
 
 
113
 
114
- video_input.change(enable_submit, inputs=[video_input], outputs=[submit_btn])
115
- submit_btn.click(detect_pose_video, inputs=[video_input], outputs=[video_output, status_output])
116
 
117
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
  import cv2
3
  import mediapipe as mp
 
 
4
  import tempfile
 
5
  import os
6
 
7
  # Initialize MediaPipe Pose
8
  mp_pose = mp.solutions.pose
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ def detect_pose(video_file):
11
+ """
12
+ This function takes an uploaded video file, limits it to 10 seconds,
13
+ applies human pose estimation using MediaPipe, and returns a new video
14
+ with the detected poses drawn on the frames.
15
+ """
16
+ try:
17
+ # Save uploaded video to a temporary file
18
+ temp_video = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
19
+ temp_video.write(open(video_file, "rb").read())
20
+ temp_video.close()
21
 
22
+ # Open video using OpenCV
23
+ cap = cv2.VideoCapture(temp_video.name)
24
  if not cap.isOpened():
25
+ return "Error: Could not open video file."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ fps = cap.get(cv2.CAP_PROP_FPS)
28
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
29
+ duration = total_frames / fps
30
 
31
+ # Limit processing to max 10 seconds
32
+ max_frames = int(min(duration, 10) * fps)
33
 
34
+ output_frames = []
 
35
 
36
+ # Initialize MediaPipe Pose for pose detection
37
+ with mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5) as pose:
38
+ frame_count = 0
39
+ while frame_count < max_frames:
40
+ ret, frame = cap.read()
41
+ if not ret:
42
+ break
43
 
44
+ # Convert frame to RGB for MediaPipe
45
+ image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
46
+ results = pose.process(image_rgb)
 
47
 
48
+ # Draw pose landmarks if detected
49
+ if results.pose_landmarks:
50
+ mp.solutions.drawing_utils.draw_landmarks(
51
+ frame, results.pose_landmarks, mp_pose.POSE_CONNECTIONS
52
+ )
53
 
54
+ output_frames.append(frame)
55
+ frame_count += 1
56
 
57
+ cap.release()
58
+
59
+ # Check if any frames were processed
60
+ if len(output_frames) == 0:
61
+ return "Error: No frames to process."
62
+
63
+ # Save output video
64
+ output_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
65
+ height, width, _ = output_frames[0].shape
66
+ out = cv2.VideoWriter(output_file, cv2.VideoWriter_fourcc(*'mp4v'), fps, (width, height))
67
+ for f in output_frames:
68
+ out.write(f)
69
+ out.release()
70
+
71
+ return output_file
72
+
73
+ except Exception as e:
74
+ # Catch any exceptions and return error message
75
+ return f"Error during processing: {str(e)}"
76
+
77
+ # Gradio interface
78
+ iface = gr.Interface(
79
+ fn=detect_pose,
80
+ inputs=gr.Video(label="Upload a Video (max 10s)"),
81
+ outputs=gr.Video(label="Pose Detection Output"),
82
+ title="Human Pose Estimation",
83
+ description="Upload a short video, and this app will detect human poses (max 10 seconds)."
84
+ )
85
+
86
+ iface.launch()