Document Python API and ship package stubs
This commit is contained in:
@@ -17,6 +17,7 @@ find_package(nanobind CONFIG REQUIRED)
|
||||
set(RPT_PYTHON_PACKAGE_DIR "${CMAKE_CURRENT_BINARY_DIR}/rpt")
|
||||
file(MAKE_DIRECTORY "${RPT_PYTHON_PACKAGE_DIR}")
|
||||
configure_file("${PROJECT_SOURCE_DIR}/src/rpt/__init__.py" "${RPT_PYTHON_PACKAGE_DIR}/__init__.py" COPYONLY)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/src/rpt/__init__.pyi" "${RPT_PYTHON_PACKAGE_DIR}/__init__.pyi" COPYONLY)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/src/rpt/_helpers.py" "${RPT_PYTHON_PACKAGE_DIR}/_helpers.py" COPYONLY)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/src/rpt/py.typed" "${RPT_PYTHON_PACKAGE_DIR}/py.typed" COPYONLY)
|
||||
|
||||
@@ -40,4 +41,5 @@ nanobind_add_stub(rpt_core_stub
|
||||
)
|
||||
|
||||
install(TARGETS rpt_core_ext LIBRARY DESTINATION rpt)
|
||||
install(FILES "${RPT_PYTHON_PACKAGE_DIR}/__init__.pyi" DESTINATION rpt)
|
||||
install(FILES "${RPT_PYTHON_PACKAGE_DIR}/_core.pyi" DESTINATION rpt)
|
||||
|
||||
+133
-7
@@ -21,30 +21,83 @@ from ._core import (
|
||||
PreviousPoseMatch,
|
||||
ProposalGroupDebug,
|
||||
TriangulationTrace,
|
||||
build_pair_candidates,
|
||||
filter_pairs_with_previous_poses,
|
||||
make_camera,
|
||||
triangulate_debug,
|
||||
triangulate_poses,
|
||||
triangulate_with_report,
|
||||
build_pair_candidates as _build_pair_candidates,
|
||||
filter_pairs_with_previous_poses as _filter_pairs_with_previous_poses,
|
||||
make_camera as _make_camera,
|
||||
triangulate_debug as _triangulate_debug,
|
||||
triangulate_poses as _triangulate_poses,
|
||||
triangulate_with_report as _triangulate_with_report,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ._helpers import CameraLike, PoseViewLike
|
||||
from ._helpers import CameraLike, CameraModelLike, Matrix3x3Like, PoseViewLike, VectorLike
|
||||
|
||||
PoseArray2D = npt.NDArray[np.float32]
|
||||
PoseArray3D = npt.NDArray[np.float32]
|
||||
PersonCountArray = npt.NDArray[np.uint32]
|
||||
TrackIdArray = npt.NDArray[np.int64]
|
||||
|
||||
|
||||
Camera.__doc__ = """Immutable camera calibration with precomputed projection cache fields."""
|
||||
TriangulationConfig.__doc__ = """Stable scene configuration used for triangulation."""
|
||||
TriangulationOptions.__doc__ = """Score and grouping thresholds used by triangulation."""
|
||||
TriangulationResult.__doc__ = """Tracked triangulation output containing poses and association metadata."""
|
||||
AssociationReport.__doc__ = """Track-association summary for a tracked triangulation call."""
|
||||
TriangulationTrace.__doc__ = """Full debug trace for triangulation, including pair, grouping, and association stages."""
|
||||
|
||||
|
||||
def convert_cameras(cameras: "Sequence[CameraLike]") -> list[Camera]:
|
||||
"""Normalize mapping-like camera inputs into immutable bound `Camera` instances."""
|
||||
|
||||
from ._helpers import convert_cameras as _convert_cameras
|
||||
|
||||
return _convert_cameras(cameras)
|
||||
|
||||
|
||||
def make_camera(
|
||||
name: str,
|
||||
K: "Matrix3x3Like",
|
||||
DC: "VectorLike",
|
||||
R: "Matrix3x3Like",
|
||||
T: "Sequence[Sequence[float]]",
|
||||
width: int,
|
||||
height: int,
|
||||
model: "CameraModel | CameraModelLike",
|
||||
) -> Camera:
|
||||
"""Create an immutable camera and precompute its cached projection fields."""
|
||||
|
||||
from ._helpers import _coerce_camera_model, _coerce_distortion
|
||||
|
||||
camera_model = _coerce_camera_model(model)
|
||||
return _make_camera(
|
||||
name,
|
||||
K,
|
||||
_coerce_distortion(DC, camera_model),
|
||||
R,
|
||||
T,
|
||||
width,
|
||||
height,
|
||||
camera_model,
|
||||
)
|
||||
|
||||
|
||||
def build_pair_candidates(
|
||||
poses_2d: "PoseArray2D",
|
||||
person_counts: "PersonCountArray",
|
||||
) -> list[PairCandidate]:
|
||||
"""Enumerate all cross-view person pairs implied by the padded 2D pose batch."""
|
||||
|
||||
return _build_pair_candidates(poses_2d, person_counts)
|
||||
|
||||
|
||||
def pack_poses_2d(
|
||||
views: "Sequence[PoseViewLike]", *, joint_count: int | None = None
|
||||
) -> "tuple[npt.NDArray[np.float32], npt.NDArray[np.uint32]]":
|
||||
"""Pack ragged per-view pose detections into the padded tensor expected by the core API."""
|
||||
|
||||
from ._helpers import pack_poses_2d as _pack_poses_2d
|
||||
|
||||
return _pack_poses_2d(views, joint_count=joint_count)
|
||||
@@ -58,6 +111,8 @@ def make_triangulation_config(
|
||||
min_match_score: float = 0.95,
|
||||
min_group_size: int = 1,
|
||||
) -> TriangulationConfig:
|
||||
"""Build a triangulation config from cameras, room parameters, and joint names."""
|
||||
|
||||
from ._helpers import make_triangulation_config as _make_triangulation_config
|
||||
|
||||
return _make_triangulation_config(
|
||||
@@ -69,6 +124,77 @@ def make_triangulation_config(
|
||||
)
|
||||
|
||||
|
||||
def filter_pairs_with_previous_poses(
|
||||
poses_2d: "PoseArray2D",
|
||||
person_counts: "PersonCountArray",
|
||||
config: TriangulationConfig,
|
||||
previous_poses_3d: "PoseArray3D",
|
||||
previous_track_ids: "TrackIdArray",
|
||||
) -> PreviousPoseFilterDebug:
|
||||
"""Filter raw cross-view pairs against caller-owned previous 3D tracks."""
|
||||
|
||||
return _filter_pairs_with_previous_poses(
|
||||
poses_2d,
|
||||
person_counts,
|
||||
config,
|
||||
previous_poses_3d,
|
||||
previous_track_ids,
|
||||
)
|
||||
|
||||
|
||||
def triangulate_debug(
|
||||
poses_2d: "PoseArray2D",
|
||||
person_counts: "PersonCountArray",
|
||||
config: TriangulationConfig,
|
||||
previous_poses_3d: "PoseArray3D | None" = None,
|
||||
previous_track_ids: "TrackIdArray | None" = None,
|
||||
) -> TriangulationTrace:
|
||||
"""Run triangulation and return the full debug trace.
|
||||
|
||||
If previous-frame 3D tracks are supplied, `previous_track_ids` must be supplied as an
|
||||
aligned `int64` array of the same length.
|
||||
"""
|
||||
|
||||
if previous_poses_3d is None:
|
||||
return _triangulate_debug(poses_2d, person_counts, config)
|
||||
if previous_track_ids is None:
|
||||
raise ValueError("previous_track_ids is required when previous_poses_3d is provided.")
|
||||
return _triangulate_debug(poses_2d, person_counts, config, previous_poses_3d, previous_track_ids)
|
||||
|
||||
|
||||
def triangulate_poses(
|
||||
poses_2d: "PoseArray2D",
|
||||
person_counts: "PersonCountArray",
|
||||
config: TriangulationConfig,
|
||||
) -> "PoseArray3D":
|
||||
"""Triangulate a frame into anonymous 3D poses without track association."""
|
||||
|
||||
return _triangulate_poses(poses_2d, person_counts, config)
|
||||
|
||||
|
||||
def triangulate_with_report(
|
||||
poses_2d: "PoseArray2D",
|
||||
person_counts: "PersonCountArray",
|
||||
config: TriangulationConfig,
|
||||
previous_poses_3d: "PoseArray3D",
|
||||
previous_track_ids: "TrackIdArray",
|
||||
) -> TriangulationResult:
|
||||
"""Triangulate a frame and return caller-owned track association results.
|
||||
|
||||
The previous-frame poses and IDs are treated as immutable caller state. The returned
|
||||
association report classifies each final pose as matched, new, or ambiguous, and lists
|
||||
unmatched previous tracks as deletion candidates.
|
||||
"""
|
||||
|
||||
return _triangulate_with_report(
|
||||
poses_2d,
|
||||
person_counts,
|
||||
config,
|
||||
previous_poses_3d,
|
||||
previous_track_ids,
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Camera",
|
||||
"CameraModel",
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
from collections.abc import Sequence
|
||||
from typing import TypeAlias, overload
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ._core import (
|
||||
AssociationReport,
|
||||
AssociationStatus,
|
||||
Camera,
|
||||
CameraModel,
|
||||
CoreProposalDebug,
|
||||
FinalPoseAssociationDebug,
|
||||
FullProposalDebug,
|
||||
GroupingDebug,
|
||||
MergeDebug,
|
||||
PairCandidate,
|
||||
PreviousPoseFilterDebug,
|
||||
PreviousPoseMatch,
|
||||
ProposalGroupDebug,
|
||||
TriangulationConfig,
|
||||
TriangulationOptions,
|
||||
TriangulationResult,
|
||||
TriangulationTrace,
|
||||
)
|
||||
from ._helpers import CameraLike, CameraModelLike, Matrix3x3Like, PoseViewLike, RoomParamsLike, VectorLike
|
||||
|
||||
PoseArray2D: TypeAlias = npt.NDArray[np.float32]
|
||||
PoseArray3D: TypeAlias = npt.NDArray[np.float32]
|
||||
PersonCountArray: TypeAlias = npt.NDArray[np.uint32]
|
||||
TrackIdArray: TypeAlias = npt.NDArray[np.int64]
|
||||
|
||||
|
||||
def convert_cameras(cameras: Sequence[CameraLike]) -> list[Camera]: ...
|
||||
|
||||
|
||||
def make_camera(
|
||||
name: str,
|
||||
K: Matrix3x3Like,
|
||||
DC: VectorLike,
|
||||
R: Matrix3x3Like,
|
||||
T: Sequence[Sequence[float]],
|
||||
width: int,
|
||||
height: int,
|
||||
model: CameraModel | CameraModelLike,
|
||||
) -> Camera: ...
|
||||
|
||||
|
||||
def build_pair_candidates(
|
||||
poses_2d: PoseArray2D,
|
||||
person_counts: PersonCountArray,
|
||||
) -> list[PairCandidate]: ...
|
||||
|
||||
|
||||
def pack_poses_2d(
|
||||
views: Sequence[PoseViewLike],
|
||||
*,
|
||||
joint_count: int | None = None,
|
||||
) -> tuple[npt.NDArray[np.float32], npt.NDArray[np.uint32]]: ...
|
||||
|
||||
|
||||
def make_triangulation_config(
|
||||
cameras: Sequence[CameraLike],
|
||||
roomparams: RoomParamsLike,
|
||||
joint_names: Sequence[str],
|
||||
*,
|
||||
min_match_score: float = 0.95,
|
||||
min_group_size: int = 1,
|
||||
) -> TriangulationConfig: ...
|
||||
|
||||
|
||||
def filter_pairs_with_previous_poses(
|
||||
poses_2d: PoseArray2D,
|
||||
person_counts: PersonCountArray,
|
||||
config: TriangulationConfig,
|
||||
previous_poses_3d: PoseArray3D,
|
||||
previous_track_ids: TrackIdArray,
|
||||
) -> PreviousPoseFilterDebug: ...
|
||||
|
||||
|
||||
@overload
|
||||
def triangulate_debug(
|
||||
poses_2d: PoseArray2D,
|
||||
person_counts: PersonCountArray,
|
||||
config: TriangulationConfig,
|
||||
) -> TriangulationTrace: ...
|
||||
|
||||
|
||||
@overload
|
||||
def triangulate_debug(
|
||||
poses_2d: PoseArray2D,
|
||||
person_counts: PersonCountArray,
|
||||
config: TriangulationConfig,
|
||||
previous_poses_3d: PoseArray3D,
|
||||
previous_track_ids: TrackIdArray,
|
||||
) -> TriangulationTrace: ...
|
||||
|
||||
|
||||
def triangulate_poses(
|
||||
poses_2d: PoseArray2D,
|
||||
person_counts: PersonCountArray,
|
||||
config: TriangulationConfig,
|
||||
) -> PoseArray3D: ...
|
||||
|
||||
|
||||
def triangulate_with_report(
|
||||
poses_2d: PoseArray2D,
|
||||
person_counts: PersonCountArray,
|
||||
config: TriangulationConfig,
|
||||
previous_poses_3d: PoseArray3D,
|
||||
previous_track_ids: TrackIdArray,
|
||||
) -> TriangulationResult: ...
|
||||
|
||||
|
||||
__all__: list[str]
|
||||
Reference in New Issue
Block a user