Fix camera capture reliability and rewrite tracking for available mediapipe/hardware
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import numpy as np
|
||||
import cv2
|
||||
import os
|
||||
from PySide6.QtCore import QObject, QTimer
|
||||
import mediapipe as mp
|
||||
from mediapipe.tasks.python import BaseOptions
|
||||
from mediapipe.tasks.python.vision import HandLandmarker, HandLandmarkerOptions, RunningMode
|
||||
from Tbd.helper import Hand2D
|
||||
from collections import defaultdict
|
||||
from Helpers.HandUdpSender import HandUdpSender
|
||||
@@ -9,6 +12,8 @@ from Helpers.HandUdpSender import HandUdpSender
|
||||
import struct
|
||||
import time
|
||||
|
||||
MODEL_PATH = os.path.join(os.path.dirname(__file__), "models", "hand_landmarker.task")
|
||||
|
||||
class TrackingController(QObject):
|
||||
def __init__(self, cameraList, P_mats, logger=None, tick_ms=30):
|
||||
super().__init__()
|
||||
@@ -25,16 +30,20 @@ class TrackingController(QObject):
|
||||
|
||||
self.running = False
|
||||
|
||||
# init mediapipe here (or inject it)
|
||||
|
||||
self.mp_hands = mp.solutions.hands
|
||||
self.hands = self.mp_hands.Hands(
|
||||
static_image_mode=False,
|
||||
max_num_hands=4,
|
||||
model_complexity=1,
|
||||
min_detection_confidence=0.5,
|
||||
# MediaPipe's legacy solutions.hands API no longer exists on the
|
||||
# installed mediapipe version, so hand detection runs on the newer
|
||||
# Tasks API instead (IMAGE mode: each camera frame is detected
|
||||
# independently, since frames from different cameras aren't a single
|
||||
# monotonic video stream that VIDEO mode requires).
|
||||
options = HandLandmarkerOptions(
|
||||
base_options=BaseOptions(model_asset_path=MODEL_PATH),
|
||||
running_mode=RunningMode.IMAGE,
|
||||
num_hands=4,
|
||||
min_hand_detection_confidence=0.5,
|
||||
min_hand_presence_confidence=0.5,
|
||||
min_tracking_confidence=0.5,
|
||||
)
|
||||
self.detector = HandLandmarker.create_from_options(options)
|
||||
|
||||
def start(self):
|
||||
# Guard: need projections
|
||||
@@ -45,6 +54,11 @@ class TrackingController(QObject):
|
||||
|
||||
if self.running:
|
||||
return
|
||||
|
||||
for camera in self.cameraList:
|
||||
if not camera.open():
|
||||
if self.logger: self.logger.log(f"[Tracking] cam{camera.index}: failed to open, will be skipped.")
|
||||
|
||||
self.running = True
|
||||
self.timer.start(self.tick_ms)
|
||||
if self.logger: self.logger.log("[Tracking] Started")
|
||||
@@ -54,6 +68,10 @@ class TrackingController(QObject):
|
||||
return
|
||||
self.running = False
|
||||
self.timer.stop()
|
||||
|
||||
for camera in self.cameraList:
|
||||
camera.close()
|
||||
|
||||
if self.logger: self.logger.log("[Tracking] Stopped")
|
||||
|
||||
def _tick(self):
|
||||
@@ -81,30 +99,33 @@ class TrackingController(QObject):
|
||||
def _detectHands_all_cameras(self):
|
||||
out = []
|
||||
for camera in self.cameraList:
|
||||
if camera.capture is None:
|
||||
continue
|
||||
|
||||
ok, frameBGR = camera.capture.read()
|
||||
if not ok or frameBGR is None:
|
||||
continue
|
||||
|
||||
h, w = frameBGR.shape[:2]
|
||||
frameRGB = cv2.cvtColor(frameBGR, cv2.COLOR_BGR2RGB)
|
||||
frameRGB.flags.writeable = False
|
||||
|
||||
hand_tracking_result = self.hands.process(frameRGB)
|
||||
if not hand_tracking_result.multi_hand_landmarks:
|
||||
mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=frameRGB)
|
||||
result = self.detector.detect(mp_image)
|
||||
|
||||
if not result.hand_landmarks:
|
||||
continue
|
||||
|
||||
handed = hand_tracking_result.multi_handedness
|
||||
for hi, lm_list in enumerate(hand_tracking_result.multi_hand_landmarks):
|
||||
for hi, lm_list in enumerate(result.hand_landmarks):
|
||||
landmarks_px = np.array(
|
||||
[[lm.x * w, lm.y * h] for lm in lm_list.landmark],
|
||||
[[lm.x * w, lm.y * h] for lm in lm_list],
|
||||
dtype=np.float32
|
||||
)
|
||||
|
||||
label, score = "Unknown", 0.0
|
||||
if hi < len(handed) and handed[hi].classification:
|
||||
label = handed[hi].classification[0].label
|
||||
score = handed[hi].classification[0].score
|
||||
|
||||
if hi < len(result.handedness) and result.handedness[hi]:
|
||||
label = result.handedness[hi][0].category_name
|
||||
score = result.handedness[hi][0].score
|
||||
|
||||
out.append(Hand2D(
|
||||
camera_id=camera.index,
|
||||
handedness=label,
|
||||
|
||||
Reference in New Issue
Block a user