Spaces:
Configuration error
Configuration error
| import mediapipe as mp | |
| import cv2 | |
| from django.conf import settings | |
| from .plank import PlankDetection | |
| from .bicep_curl import BicepCurlDetection | |
| from .squat import SquatDetection | |
| from .lunge import LungeDetection | |
| from .utils import rescale_frame | |
| # Drawing helpers | |
| mp_drawing = mp.solutions.drawing_utils | |
| mp_pose = mp.solutions.pose | |
| EXERCISE_DETECTIONS = None | |
| def load_machine_learning_models(): | |
| """Load all machine learning models""" | |
| global EXERCISE_DETECTIONS | |
| if EXERCISE_DETECTIONS is not None: | |
| return | |
| print("Loading ML models ...") | |
| EXERCISE_DETECTIONS = { | |
| "plank": PlankDetection(), | |
| "bicep_curl": BicepCurlDetection(), | |
| "squat": SquatDetection(), | |
| "lunge": LungeDetection(), | |
| } | |
| def pose_detection( | |
| video_file_path: str, video_name_to_save: str, rescale_percent: float = 40 | |
| ): | |
| """Pose detection with MediaPipe Pose | |
| Args: | |
| video_file_path (str): path to video | |
| video_name_to_save (str): path to save analyzed video | |
| rescale_percent (float, optional): Percentage to scale back from the original video size. Defaults to 40. | |
| """ | |
| cap = cv2.VideoCapture(video_file_path) | |
| width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH) * rescale_percent / 100) | |
| height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) * rescale_percent / 100) | |
| size = (width, height) | |
| fps = int(cap.get(cv2.CAP_PROP_FPS)) | |
| fourcc = cv2.VideoWriter_fourcc(*"avc1") | |
| save_to_path = f"{settings.MEDIA_ROOT}/{video_name_to_save}" | |
| out = cv2.VideoWriter(save_to_path, fourcc, fps, size) | |
| print("PROCESSING VIDEO ...") | |
| with mp_pose.Pose( | |
| min_detection_confidence=0.8, min_tracking_confidence=0.8 | |
| ) as pose: | |
| while cap.isOpened(): | |
| ret, image = cap.read() | |
| if not ret: | |
| break | |
| image = rescale_frame(image, rescale_percent) | |
| # Recolor image from BGR to RGB for mediapipe | |
| image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
| image.flags.writeable = False | |
| results = pose.process(image) | |
| # Recolor image from BGR to RGB for mediapipe | |
| image.flags.writeable = True | |
| image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) | |
| mp_drawing.draw_landmarks( | |
| image, | |
| results.pose_landmarks, | |
| mp_pose.POSE_CONNECTIONS, | |
| mp_drawing.DrawingSpec( | |
| color=(244, 117, 66), thickness=2, circle_radius=2 | |
| ), | |
| mp_drawing.DrawingSpec( | |
| color=(245, 66, 230), thickness=2, circle_radius=1 | |
| ), | |
| ) | |
| out.write(image) | |
| print(f"PROCESSED, save to {save_to_path}.") | |
| return | |
| def exercise_detection( | |
| video_file_path: str, | |
| video_name_to_save: str, | |
| exercise_type: str, | |
| rescale_percent: float = 40, | |
| ) -> dict: | |
| """Analyzed Exercise Video | |
| Args: | |
| video_file_path (str): path to video | |
| video_name_to_save (str): path to save analyzed video | |
| exercise_type (str): exercise type | |
| rescale_percent (float, optional): Percentage to scale back from the original video size. Defaults to 40. | |
| Raises: | |
| Exception: Not supported exercise type | |
| Returns: | |
| dict: Dictionary of analyzed stats from the video | |
| """ | |
| exercise_detection = EXERCISE_DETECTIONS.get(exercise_type) | |
| if not exercise_detection: | |
| raise Exception("Not supported exercise.") | |
| cap = cv2.VideoCapture(video_file_path) | |
| width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH) * rescale_percent / 100) | |
| height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) * rescale_percent / 100) | |
| size = (width, height) | |
| fps = int(cap.get(cv2.CAP_PROP_FPS)) | |
| frame_count = 0 | |
| fourcc = cv2.VideoWriter_fourcc(*"avc1") | |
| saved_path = f"{settings.MEDIA_ROOT}/{video_name_to_save}" | |
| out = cv2.VideoWriter(saved_path, fourcc, fps, size) | |
| print("PROCESSING VIDEO ...") | |
| with mp_pose.Pose( | |
| min_detection_confidence=0.8, min_tracking_confidence=0.8 | |
| ) as pose: | |
| while cap.isOpened(): | |
| ret, image = cap.read() | |
| if not ret: | |
| break | |
| # Calculate timestamp | |
| frame_count += 1 | |
| timestamp = int(frame_count / fps) | |
| image = rescale_frame(image, rescale_percent) | |
| # Recolor image from BGR to RGB for mediapipe | |
| image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
| image.flags.writeable = False | |
| results = pose.process(image) | |
| # Recolor image from BGR to RGB for mediapipe | |
| image.flags.writeable = True | |
| image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) | |
| if results.pose_landmarks: | |
| exercise_detection.detect( | |
| mp_results=results, image=image, timestamp=timestamp | |
| ) | |
| out.write(image) | |
| print(f"PROCESSED. Save path: {saved_path}") | |
| processed_results = exercise_detection.handle_detected_results( | |
| video_name=video_name_to_save | |
| ) | |
| exercise_detection.clear_results() | |
| return processed_results | |