Spaces:
Running
Running
Upload app.py
Browse files
app.py
CHANGED
@@ -2,10 +2,12 @@
|
|
2 |
# %%pip install mediapipe gradio plotly matplotlib pyttsx3 opencv-python --quiet
|
3 |
|
4 |
# Import packages
|
|
|
5 |
import gradio as gr
|
6 |
import cv2
|
7 |
import mediapipe as mp
|
8 |
from mediapipe import solutions
|
|
|
9 |
import numpy as np
|
10 |
import plotly.graph_objects as go
|
11 |
import matplotlib.pyplot as plt
|
@@ -18,20 +20,22 @@ import logging
|
|
18 |
import io
|
19 |
import torch
|
20 |
import time
|
|
|
21 |
|
22 |
# Initialize logging
|
23 |
logging.basicConfig(level=logging.INFO)
|
24 |
-
logging.getLogger(
|
25 |
logger = logging.getLogger(__name__)
|
26 |
|
27 |
# Check for GPU availability
|
28 |
device = "cuda:0" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
|
|
|
|
|
29 |
|
30 |
# Initialize MediaPipe Pose model
|
31 |
mp_drawing = mp.solutions.drawing_utils
|
32 |
mp_pose = mp.solutions.pose
|
33 |
mp_drawing_styles = solutions.drawing_styles
|
34 |
-
confidence = 0.5
|
35 |
|
36 |
pose_image = mp_pose.Pose(
|
37 |
static_image_mode=True,
|
@@ -73,9 +77,9 @@ example_videos = [os.path.join(video_folder, f) for f in os.listdir(video_folder
|
|
73 |
|
74 |
# Global constants
|
75 |
FRAMERATE = 30
|
76 |
-
frame_reduction = 5
|
77 |
-
|
78 |
reduced_FRAMERATE = int(FRAMERATE / frame_reduction)
|
|
|
79 |
repetitions = 0
|
80 |
visible_side = "right"
|
81 |
previous_knee_forward = False
|
@@ -212,10 +216,10 @@ def create_3d_skeleton(skeleton_coords):
|
|
212 |
return fig
|
213 |
|
214 |
def generate_plot_frame(data, current_frame):
|
215 |
-
global
|
216 |
|
217 |
plt.figure(figsize=(10, 5))
|
218 |
-
time_seconds = np.array(data["frame"]) /
|
219 |
plt.plot(time_seconds[:current_frame + 1], data["back_angle"][:current_frame + 1], label="Back Angle")
|
220 |
plt.plot(time_seconds[:current_frame + 1], data["head_angle"][:current_frame + 1], label="Head Angle")
|
221 |
plt.plot(time_seconds[:current_frame + 1], data["left_knee_angle"][:current_frame + 1], label="Left Knee Angle")
|
@@ -403,6 +407,7 @@ def process_video(video_path=None):
|
|
403 |
global fps, warnings_issued, repetitions, previous_knee_forward, frame_reduction, reduced_FRAMERATE
|
404 |
|
405 |
angles_data = {"frame": [], "back_angle": [], "head_angle": [], "left_knee_angle": [], "right_knee_angle": []}
|
|
|
406 |
|
407 |
repetitions = 0
|
408 |
previous_knee_forward = False
|
@@ -421,9 +426,13 @@ def process_video(video_path=None):
|
|
421 |
fps = int(cap.get(cv2.CAP_PROP_FPS))
|
422 |
reduced_FRAMERATE = int(fps / frame_reduction) # Reduce frame rate
|
423 |
|
424 |
-
|
425 |
-
|
426 |
-
|
|
|
|
|
|
|
|
|
427 |
|
428 |
try:
|
429 |
frame_idx = 0
|
@@ -443,7 +452,7 @@ def process_video(video_path=None):
|
|
443 |
# Write frame to video
|
444 |
out.write(black_frame)
|
445 |
|
446 |
-
|
447 |
|
448 |
yield (skeleton_3d, None, None)
|
449 |
|
@@ -454,8 +463,8 @@ def process_video(video_path=None):
|
|
454 |
|
455 |
# Final yield with completed video
|
456 |
yield (skeleton_3d,
|
457 |
-
gr.update(visible=True, value=
|
458 |
-
gr.update (visible=True, value=
|
459 |
)
|
460 |
|
461 |
def start_webcam():
|
@@ -612,16 +621,7 @@ def process_webcam_feed():
|
|
612 |
gr.update(visible=False),
|
613 |
repetitions
|
614 |
)
|
615 |
-
|
616 |
-
# logging.warning("No frames were captured during the webcam session.")
|
617 |
-
# yield (
|
618 |
-
# None,
|
619 |
-
# None,
|
620 |
-
# gr.update(visible=False),
|
621 |
-
# gr.update(visible=False),
|
622 |
-
# repetitions
|
623 |
-
# )
|
624 |
-
|
625 |
# Fix: Update Gradio interface to use the corrected functions
|
626 |
def build_gradio_interface():
|
627 |
"""
|
@@ -643,10 +643,10 @@ def build_gradio_interface():
|
|
643 |
gr.Markdown(
|
644 |
"<div style='text-align: center; margin-top: 2em'>"
|
645 |
"<h1 style='text-align: center;'>A Surfing Pop-Up Trainer</h1>"
|
646 |
-
"©Schmied Research And Development Pty Ltd. Dr Steven Schmied. Email [email protected]"
|
647 |
-
"<i>Seeking only peace and friendship, to teach if we are called upon, to be taught if we are fortunate</i> - Voyager Golden Record"
|
648 |
-
"To analyse your pop-up, use your webcam or upload an image or video. The analysis will take a few seconds to process
|
649 |
-
"Hold down the left mouse button and drag to rotate three dimensional Skeleton"
|
650 |
"For a good pop-up: 1. keep your hips lower than your shoulders, 2. do not look down and 3. bend your knees. A repetition counted when your knees bends to less than 100 degrees.</div>")
|
651 |
|
652 |
with gr.Tabs():
|
@@ -682,7 +682,8 @@ def build_gradio_interface():
|
|
682 |
show_share_button=True,
|
683 |
format="mp4",
|
684 |
autoplay=True,
|
685 |
-
visible=False
|
|
|
686 |
)
|
687 |
|
688 |
angle_plot = gr.Image(show_label=False, visible = False)
|
@@ -713,7 +714,8 @@ def build_gradio_interface():
|
|
713 |
show_share_button=True,
|
714 |
format="mp4",
|
715 |
autoplay=True,
|
716 |
-
visible=False
|
|
|
717 |
)
|
718 |
|
719 |
angle_plot_webcam = gr.Image(show_label=False, visible = False)
|
|
|
2 |
# %%pip install mediapipe gradio plotly matplotlib pyttsx3 opencv-python --quiet
|
3 |
|
4 |
# Import packages
|
5 |
+
import base64
|
6 |
import gradio as gr
|
7 |
import cv2
|
8 |
import mediapipe as mp
|
9 |
from mediapipe import solutions
|
10 |
+
from ultralytics import YOLO
|
11 |
import numpy as np
|
12 |
import plotly.graph_objects as go
|
13 |
import matplotlib.pyplot as plt
|
|
|
20 |
import io
|
21 |
import torch
|
22 |
import time
|
23 |
+
import tempfile
|
24 |
|
25 |
# Initialize logging
|
26 |
logging.basicConfig(level=logging.INFO)
|
27 |
+
logging.getLogger().setLevel(logging.CRITICAL + 1)
|
28 |
logger = logging.getLogger(__name__)
|
29 |
|
30 |
# Check for GPU availability
|
31 |
device = "cuda:0" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu"
|
32 |
+
model = YOLO("yolo11/yolo11n-pose.pt").to(device)
|
33 |
+
confidence = 0.5
|
34 |
|
35 |
# Initialize MediaPipe Pose model
|
36 |
mp_drawing = mp.solutions.drawing_utils
|
37 |
mp_pose = mp.solutions.pose
|
38 |
mp_drawing_styles = solutions.drawing_styles
|
|
|
39 |
|
40 |
pose_image = mp_pose.Pose(
|
41 |
static_image_mode=True,
|
|
|
77 |
|
78 |
# Global constants
|
79 |
FRAMERATE = 30
|
80 |
+
frame_reduction = 5
|
|
|
81 |
reduced_FRAMERATE = int(FRAMERATE / frame_reduction)
|
82 |
+
|
83 |
repetitions = 0
|
84 |
visible_side = "right"
|
85 |
previous_knee_forward = False
|
|
|
216 |
return fig
|
217 |
|
218 |
def generate_plot_frame(data, current_frame):
|
219 |
+
global FRAMERATE
|
220 |
|
221 |
plt.figure(figsize=(10, 5))
|
222 |
+
time_seconds = np.array(data["frame"]) / FRAMERATE
|
223 |
plt.plot(time_seconds[:current_frame + 1], data["back_angle"][:current_frame + 1], label="Back Angle")
|
224 |
plt.plot(time_seconds[:current_frame + 1], data["head_angle"][:current_frame + 1], label="Head Angle")
|
225 |
plt.plot(time_seconds[:current_frame + 1], data["left_knee_angle"][:current_frame + 1], label="Left Knee Angle")
|
|
|
407 |
global fps, warnings_issued, repetitions, previous_knee_forward, frame_reduction, reduced_FRAMERATE
|
408 |
|
409 |
angles_data = {"frame": [], "back_angle": [], "head_angle": [], "left_knee_angle": [], "right_knee_angle": []}
|
410 |
+
frames = []
|
411 |
|
412 |
repetitions = 0
|
413 |
previous_knee_forward = False
|
|
|
426 |
fps = int(cap.get(cv2.CAP_PROP_FPS))
|
427 |
reduced_FRAMERATE = int(fps / frame_reduction) # Reduce frame rate
|
428 |
|
429 |
+
fourcc = cv2.VideoWriter_fourcc(*'mp4v') # MP4 format
|
430 |
+
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
|
431 |
+
output_path = temp_file.name
|
432 |
+
|
433 |
+
|
434 |
+
# pose_video = f"output/pose_video-{datetime.now().strftime('%Y%m%d%H%M')}.mp4"
|
435 |
+
out = cv2.VideoWriter(output_path, fourcc, reduced_FRAMERATE, (original_width, original_height))
|
436 |
|
437 |
try:
|
438 |
frame_idx = 0
|
|
|
452 |
# Write frame to video
|
453 |
out.write(black_frame)
|
454 |
|
455 |
+
angle_plot = generate_plot_frame(angles_data, frame_idx)
|
456 |
|
457 |
yield (skeleton_3d, None, None)
|
458 |
|
|
|
463 |
|
464 |
# Final yield with completed video
|
465 |
yield (skeleton_3d,
|
466 |
+
gr.update(visible=True, value=output_path), # Use the in-memory buffer for video output
|
467 |
+
gr.update (visible=True, value=angle_plot) # Show the video at the end
|
468 |
)
|
469 |
|
470 |
def start_webcam():
|
|
|
621 |
gr.update(visible=False),
|
622 |
repetitions
|
623 |
)
|
624 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
625 |
# Fix: Update Gradio interface to use the corrected functions
|
626 |
def build_gradio_interface():
|
627 |
"""
|
|
|
643 |
gr.Markdown(
|
644 |
"<div style='text-align: center; margin-top: 2em'>"
|
645 |
"<h1 style='text-align: center;'>A Surfing Pop-Up Trainer</h1>"
|
646 |
+
"©Schmied Research And Development Pty Ltd. Dr Steven Schmied. Email [email protected]<br>"
|
647 |
+
"<i>Seeking only peace and friendship, to teach if we are called upon, to be taught if we are fortunate</i> - Voyager Golden Record<br>"
|
648 |
+
"To analyse your pop-up, use your webcam or upload an image or video. The analysis will take a few seconds to process.<br>"
|
649 |
+
"Hold down the left mouse button and drag to rotate three dimensional Skeleton. Scroll the mouse wheel to zoom<br>"
|
650 |
"For a good pop-up: 1. keep your hips lower than your shoulders, 2. do not look down and 3. bend your knees. A repetition counted when your knees bends to less than 100 degrees.</div>")
|
651 |
|
652 |
with gr.Tabs():
|
|
|
682 |
show_share_button=True,
|
683 |
format="mp4",
|
684 |
autoplay=True,
|
685 |
+
visible=False,
|
686 |
+
interactive=False
|
687 |
)
|
688 |
|
689 |
angle_plot = gr.Image(show_label=False, visible = False)
|
|
|
714 |
show_share_button=True,
|
715 |
format="mp4",
|
716 |
autoplay=True,
|
717 |
+
visible=False,
|
718 |
+
interactive=False
|
719 |
)
|
720 |
|
721 |
angle_plot_webcam = gr.Image(show_label=False, visible = False)
|