Migrate Python bindings from SWIG to nanobind
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Sequence
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ._core import Camera, Triangulator
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ._helpers import CameraLike, PoseViewLike
|
||||
|
||||
|
||||
def convert_cameras(cameras: "Sequence[CameraLike]") -> list[Camera]:
|
||||
from ._helpers import convert_cameras as _convert_cameras
|
||||
|
||||
return _convert_cameras(cameras)
|
||||
|
||||
|
||||
def pack_poses_2d(
|
||||
views: "Sequence[PoseViewLike]", *, joint_count: int | None = None
|
||||
) -> "tuple[npt.NDArray[np.float32], npt.NDArray[np.uint32]]":
|
||||
from ._helpers import pack_poses_2d as _pack_poses_2d
|
||||
|
||||
return _pack_poses_2d(views, joint_count=joint_count)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Camera",
|
||||
"Triangulator",
|
||||
"convert_cameras",
|
||||
"pack_poses_2d",
|
||||
]
|
||||
@@ -0,0 +1,92 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping, Sequence
|
||||
from typing import Any, TypeAlias
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ._core import Camera
|
||||
|
||||
CameraLike = Camera | Mapping[str, Any]
|
||||
PoseViewLike: TypeAlias = (
|
||||
npt.NDArray[np.generic]
|
||||
| Sequence[Sequence[Sequence[float]]]
|
||||
| Sequence[Sequence[float]]
|
||||
)
|
||||
|
||||
|
||||
def convert_cameras(cameras: Sequence[CameraLike]) -> list[Camera]:
|
||||
"""Normalize mappings or existing Camera objects into bound Camera instances."""
|
||||
|
||||
converted: list[Camera] = []
|
||||
for cam in cameras:
|
||||
if isinstance(cam, Camera):
|
||||
converted.append(cam)
|
||||
continue
|
||||
|
||||
camera = Camera()
|
||||
camera.name = str(cam["name"])
|
||||
camera.K = cam["K"]
|
||||
camera.DC = cam["DC"]
|
||||
camera.R = cam["R"]
|
||||
camera.T = cam["T"]
|
||||
camera.width = int(cam["width"])
|
||||
camera.height = int(cam["height"])
|
||||
camera.type = str(cam.get("type", "pinhole"))
|
||||
converted.append(camera)
|
||||
return converted
|
||||
|
||||
|
||||
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."""
|
||||
|
||||
normalized: list[npt.NDArray[np.float32]] = []
|
||||
inferred_joint_count = joint_count
|
||||
|
||||
for view in views:
|
||||
array = np.asarray(view, dtype=np.float32)
|
||||
|
||||
if array.size == 0:
|
||||
normalized.append(np.zeros((0, 0, 3), dtype=np.float32))
|
||||
continue
|
||||
|
||||
if array.ndim == 2:
|
||||
if array.shape[-1] != 3:
|
||||
raise ValueError("Single-person pose inputs must have shape [joints, 3].")
|
||||
array = array[np.newaxis, :, :]
|
||||
elif array.ndim != 3 or array.shape[-1] != 3:
|
||||
raise ValueError("Each view must have shape [persons, joints, 3] or [joints, 3].")
|
||||
|
||||
if inferred_joint_count is None:
|
||||
inferred_joint_count = int(array.shape[1])
|
||||
elif array.shape[1] != inferred_joint_count:
|
||||
raise ValueError("All views must use the same joint count.")
|
||||
|
||||
normalized.append(np.ascontiguousarray(array, dtype=np.float32))
|
||||
|
||||
if inferred_joint_count is None:
|
||||
raise ValueError("joint_count is required when all views are empty.")
|
||||
|
||||
fixed_views: list[npt.NDArray[np.float32]] = []
|
||||
max_persons = 0
|
||||
for array in normalized:
|
||||
if array.size == 0:
|
||||
array = np.zeros((0, inferred_joint_count, 3), dtype=np.float32)
|
||||
elif array.shape[1] != inferred_joint_count:
|
||||
raise ValueError("All views must use the same joint count.")
|
||||
max_persons = max(max_persons, int(array.shape[0]))
|
||||
fixed_views.append(array)
|
||||
|
||||
packed = np.zeros((len(fixed_views), max_persons, inferred_joint_count, 3), dtype=np.float32)
|
||||
counts = np.zeros((len(fixed_views),), dtype=np.uint32)
|
||||
|
||||
for view_idx, array in enumerate(fixed_views):
|
||||
person_count = int(array.shape[0])
|
||||
counts[view_idx] = person_count
|
||||
if person_count:
|
||||
packed[view_idx, :person_count, :, :] = array
|
||||
|
||||
return packed, counts
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user