Files
posefit-server/app/vision/pose_landmarker.py
T
wsy182 4485cbf702 Refactor into modular app structure
Split monolithic files into focused modules:
- app/core: settings, logging, lifecycle
- app/signaling: websocket server, ICE parser, message models
- app/webrtc: peer session, video receiver, frame source
- app/vision: pose landmarker wrapper, model config, pose types
- app/exercises/dead_bug: detector, metrics, rules, state machine, types
- app/rendering: skeleton renderer, status overlay, window display
- app/audio: rep announcer
- app/diagnostics: perf timer, crash handler
- configs: environment-based settings
- tests: unit tests for rules, state machine, ICE parser
- run.py: entry point
2026-06-10 10:14:43 +08:00

58 lines
2.0 KiB
Python

from __future__ import annotations
import threading
import time
from typing import Callable
import mediapipe as mp
from loguru import logger
from app.vision.pose_models import DEFAULT_MODEL_PATH
PoseLandmarker = mp.tasks.vision.PoseLandmarker
PoseLandmarkerOptions = mp.tasks.vision.PoseLandmarkerOptions
VisionRunningMode = mp.tasks.vision.RunningMode
BaseOptions = mp.tasks.BaseOptions
class PoseLandmarkerWrapper:
def __init__(
self,
*,
model_path: str | None = None,
prefer_gpu: bool = True,
result_callback: Callable | None = None,
) -> None:
self.model_path = model_path or DEFAULT_MODEL_PATH
if prefer_gpu:
try:
self.delegate = BaseOptions.Delegate.GPU
self._landmarker = self._create(PoseLandmarker.Delegate.GPU)
logger.info("MediaPipe PoseLandmarker initialized with GPU delegate")
return
except Exception as exc:
logger.warning("MediaPipe GPU delegate unavailable, falling back to CPU: {}", exc)
self.delegate = BaseOptions.Delegate.CPU
self._landmarker = self._create(PoseLandmarker.Delegate.CPU, result_callback)
logger.info("MediaPipe PoseLandmarker initialized with CPU delegate")
def _create(self, delegate, result_callback=None):
options = PoseLandmarkerOptions(
base_options=BaseOptions(model_asset_path=self.model_path, delegate=delegate),
running_mode=VisionRunningMode.LIVE_STREAM,
result_callback=result_callback,
num_poses=1,
min_pose_detection_confidence=0.5,
min_pose_presence_confidence=0.5,
min_tracking_confidence=0.5,
)
return PoseLandmarker.create_from_options(options)
def detect_async(self, mp_image, timestamp_ms: int) -> None:
return self._landmarker.detect_async(mp_image, timestamp_ms)
def close(self) -> None:
self._landmarker.close()