#pragma once #include #include #include #include #include "camera.hpp" // ================================================================================================= using RaggedPoses2D = std::vector>>>; using NestedPoses3D = std::vector>>; // ================================================================================================= struct PoseBatch2DView { const float *data = nullptr; const uint32_t *person_counts = nullptr; size_t num_views = 0; size_t max_persons = 0; size_t num_joints = 0; const float &at(size_t view, size_t person, size_t joint, size_t coord) const; }; struct PoseBatch3DView { const float *data = nullptr; size_t num_persons = 0; size_t num_joints = 0; const float &at(size_t person, size_t joint, size_t coord) const; }; struct PoseBatch2D { std::vector data; std::vector person_counts; size_t num_views = 0; size_t max_persons = 0; size_t num_joints = 0; float &at(size_t view, size_t person, size_t joint, size_t coord); const float &at(size_t view, size_t person, size_t joint, size_t coord) const; PoseBatch2DView view() const; static PoseBatch2D from_nested(const RaggedPoses2D &poses_2d); }; struct PoseBatch3D { std::vector data; size_t num_persons = 0; size_t num_joints = 0; float &at(size_t person, size_t joint, size_t coord); const float &at(size_t person, size_t joint, size_t coord) const; PoseBatch3DView view() const; NestedPoses3D to_nested() const; static PoseBatch3D from_nested(const NestedPoses3D &poses_3d); }; // ================================================================================================= struct PairCandidate { int view1 = -1; int view2 = -1; int person1 = -1; int person2 = -1; int global_person1 = -1; int global_person2 = -1; }; struct PreviousPoseMatch { int previous_pose_index = -1; float score_view1 = 0.0f; float score_view2 = 0.0f; bool matched_view1 = false; bool matched_view2 = false; bool kept = true; std::string decision = "unfiltered"; }; struct PreviousPoseFilterDebug { bool used_previous_poses = false; std::vector matches; std::vector kept_pair_indices; std::vector kept_pairs; }; struct CoreProposalDebug { int pair_index = -1; PairCandidate pair; std::vector> pose_3d; float score = 0.0f; bool kept = false; std::string drop_reason = "uninitialized"; }; struct ProposalGroupDebug { std::array center = {0.0f, 0.0f, 0.0f}; std::vector> pose_3d; std::vector proposal_indices; }; struct GroupingDebug { std::vector initial_groups; std::vector duplicate_pair_drops; std::vector groups; }; struct FullProposalDebug { int source_core_proposal_index = -1; PairCandidate pair; std::vector> pose_3d; }; struct MergeDebug { std::vector>> merged_poses; std::vector> group_proposal_indices; }; struct TriangulationTrace { std::vector pairs; PreviousPoseFilterDebug previous_filter; std::vector core_proposals; GroupingDebug grouping; std::vector full_proposals; MergeDebug merge; PoseBatch3D final_poses; }; // ================================================================================================= struct TriangulationOptions { float min_match_score = 0.95f; size_t min_group_size = 1; }; // ================================================================================================= std::vector build_pair_candidates(const PoseBatch2DView &poses_2d); PreviousPoseFilterDebug filter_pairs_with_previous_poses( const PoseBatch2DView &poses_2d, const std::vector &cameras, const std::vector &joint_names, const PoseBatch3DView &previous_poses_3d, const TriangulationOptions &options = {}); inline PreviousPoseFilterDebug filter_pairs_with_previous_poses( const PoseBatch2D &poses_2d, const std::vector &cameras, const std::vector &joint_names, const PoseBatch3D &previous_poses_3d, const TriangulationOptions &options = {}) { return filter_pairs_with_previous_poses( poses_2d.view(), cameras, joint_names, previous_poses_3d.view(), options); } TriangulationTrace triangulate_debug( const PoseBatch2DView &poses_2d, const std::vector &cameras, const std::array, 2> &roomparams, const std::vector &joint_names, const PoseBatch3DView *previous_poses_3d = nullptr, const TriangulationOptions &options = {}); inline TriangulationTrace triangulate_debug( const PoseBatch2D &poses_2d, const std::vector &cameras, const std::array, 2> &roomparams, const std::vector &joint_names, const PoseBatch3D *previous_poses_3d = nullptr, const TriangulationOptions &options = {}) { PoseBatch3DView previous_view_storage; const PoseBatch3DView *previous_view = nullptr; if (previous_poses_3d != nullptr) { previous_view_storage = previous_poses_3d->view(); previous_view = &previous_view_storage; } return triangulate_debug( poses_2d.view(), cameras, roomparams, joint_names, previous_view, options); } // ================================================================================================= /** * Calculate a triangulation using a padded pose tensor. * * @param poses_2d Padded poses of shape [views, max_persons, joints, 3]. * @param cameras List of cameras. * @param roomparams Room parameters (room size, room center). * @param joint_names List of 2D joint names. * @param options Triangulation options. * * @return Pose tensor of shape [persons, joints, 4]. */ PoseBatch3D triangulate_poses( const PoseBatch2DView &poses_2d, const std::vector &cameras, const std::array, 2> &roomparams, const std::vector &joint_names, const PoseBatch3DView *previous_poses_3d = nullptr, const TriangulationOptions &options = {}); inline PoseBatch3D triangulate_poses( const PoseBatch2D &poses_2d, const std::vector &cameras, const std::array, 2> &roomparams, const std::vector &joint_names, const PoseBatch3D *previous_poses_3d = nullptr, const TriangulationOptions &options = {}) { PoseBatch3DView previous_view_storage; const PoseBatch3DView *previous_view = nullptr; if (previous_poses_3d != nullptr) { previous_view_storage = previous_poses_3d->view(); previous_view = &previous_view_storage; } return triangulate_poses( poses_2d.view(), cameras, roomparams, joint_names, previous_view, options); }