dreamzero / scripts /trex_track /sam2_cotracker_hands.py
zhicao's picture
Upload dreamzero source code (no model checkpoints)
fbd9366 verified
Raw
History Blame Contribute Delete
2.77 kB
"""Hand seeds for the canonical T-Rex 250-point CoTracker layout.
No appearance auto-repair. Tune prompts in ``sam2_prompt_hands.py``.
"""
from __future__ import annotations
import numpy as np
from trex_track.layout import NUM_HEAD_PER_HAND
NUM_HAND_POINTS = NUM_HEAD_PER_HAND
__all__ = [
"NUM_HAND_POINTS",
"wrist_hand_50",
"head_hands_50",
# Compatibility aliases for callers of the old 25-point implementation.
"wrist_hand_25",
"head_hands_25",
]
def _stable_spatial_order(points_xy: np.ndarray) -> np.ndarray:
"""Give sampled slots deterministic top-to-bottom, then left-to-right IDs."""
points = np.asarray(points_xy, dtype=np.float32).reshape(-1, 2)
order = np.lexsort((points[:, 0], points[:, 1]))
return points[order]
def wrist_hand_50(
predictor,
rgb_hwc: np.ndarray,
view: str,
*,
n_points: int = NUM_HAND_POINTS,
seed: int | None = 0,
) -> tuple[np.ndarray, np.ndarray, str]:
"""One SAM2 pass → 50 stably ordered queries on a wrist hand mask.
Background 5×5 grid is NOT produced here — callers prepend ``make_image_grid``.
"""
from trex_track.sam2_prompt_hands import sample_points_on_mask, sam2_wrist_mask
mask, tag, _meta = sam2_wrist_mask(predictor, rgb_hwc, view)
rng = np.random.default_rng(seed)
pts = sample_points_on_mask(mask, n_points, rng=rng, distal_bias=True)
h, w = rgb_hwc.shape[:2]
pts[:, 0] = np.clip(pts[:, 0], 0, w - 1)
pts[:, 1] = np.clip(pts[:, 1], 0, h - 1)
return _stable_spatial_order(pts), mask.astype(bool), tag
def head_hands_50(
predictor,
rgb_hwc: np.ndarray,
*,
n_points: int = NUM_HAND_POINTS,
seed: int | None = 0,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, str]:
"""One SAM2 pass per hand → 100 queries (left 50, then right 50)."""
from trex_track.sam2_prompt_hands import sample_points_on_mask, sam2_head_hand_mask
rng = np.random.default_rng(seed)
left, tag_l, _ = sam2_head_hand_mask(predictor, rgb_hwc, "left")
right, tag_r, _ = sam2_head_hand_mask(predictor, rgb_hwc, "right")
pts_l = _stable_spatial_order(
sample_points_on_mask(left, n_points, rng=rng, distal_bias=True)
)
pts_r = _stable_spatial_order(
sample_points_on_mask(right, n_points, rng=rng, distal_bias=True)
)
h, w = rgb_hwc.shape[:2]
queries = np.concatenate([pts_l, pts_r], axis=0).astype(np.float32)
queries[:, 0] = np.clip(queries[:, 0], 0, w - 1)
queries[:, 1] = np.clip(queries[:, 1], 0, h - 1)
tag = f"{tag_l}|{tag_r}"
return queries, left.astype(bool), right.astype(bool), tag
# Keep old imports working while making their new 50-point behavior explicit.
wrist_hand_25 = wrist_hand_50
head_hands_25 = head_hands_50