azureeyemodule/app/openpose/peak.cpp
static inline void create_candidate_poses_by_limb(const size_t keypoints_number, const std::vector<cv::Mat> &pafs, const std::pair<int, int> (&limb_ids_paf)[N_PAF_LIMB_PAIRS],
                                                  const std::pair<int, int> (&limb_ids_heatmap)[N_HEATMAP_LIMB_PAIRS], const std::vector<std::vector<Peak>> &all_peaks,
                                                  const float mid_points_score_threshold, const float found_mid_points_ratio_threshold,
                                                  const std::vector<Peak> &candidates, const size_t limb_idx, std::vector<HumanPoseByPeaksIndices> &possible_poses)
{
    // A 'limb' is made up of two joints.
    // Get the heatmap indices for those two joints (the heatmaps that contain the peaks that represent those joints).
    const int idx_jointA = limb_ids_heatmap[limb_idx].first - 1;
    const int idx_jointB = limb_ids_heatmap[limb_idx].second - 1;

    // Get all the peaks (possible keypoints/joint locations) for the two joints that make up this limb
    const std::vector<Peak> &candidates_for_jointA = all_peaks[idx_jointA];
    const std::vector<Peak> &candidates_for_jointB = all_peaks[idx_jointB];

    // Get the number of joints in the two heatmaps
    const size_t njointsA = candidates_for_jointA.size();
    const size_t njointsB = candidates_for_jointB.size();

    if ((njointsA == 0) || (njointsB == 0))
    {
        maybe_create_possible_poses_from_peaks(njointsA, njointsB, possible_poses, idx_jointA, idx_jointB, candidates_for_jointA, candidates_for_jointB, keypoints_number);
    }
    else
    {
        std::vector<TwoJointsConnection> connections = form_most_promising_joint_connections(keypoints_number, pafs, limb_ids_paf, limb_idx, njointsA, njointsB, candidates_for_jointA, candidates_for_jointB, mid_points_score_threshold, found_mid_points_ratio_threshold);
        create_poses_from_connections(connections, limb_idx, possible_poses, keypoints_number, idx_jointA, idx_jointB, candidates);
    }
}
/**
 * Fills in `possible_poses`.
 *
 * We look at two heatmaps - A and B. These two heatmaps have all of joint type A (say, neck) and
 * all of joint type B (say right shoulder). The heatmaps we look at are found by looking at `limb_ids_heatmap[limb_idx]`.
 *
 * We create a giant set of all the most likely connections between possible joints in A to possible joints in B,
 * such that each possible joint in A can only be connected to at most one of the possible joints in B (and vice versa),
 * and the weight of this bipartite graph is maximized.
 *
 * The weight of each of these connections is determined by looking at the PAFs - specifically,
 * we approximate a line integral from one joint candidate to the other over the right PAF.
 * Because PAFs are vector fields made so that the vectors point along limbs, if A and B are really connected
 * (such as neck and right shoulder), we will likely get a good score when computing the line integral, as we
 * will be traveling along the vector field. If on the other hand, the joints are not connected, we will likely
 * travel over the vector field wherever there are maginitude 0 vectors or where we are perpendicular to the vector field.
 *
 * @param keypoints_number: The number of keypoints in a typical HumanPose
 * @param pafs: The PAFs
 * @param limb_ids_paf: The array of PAF joint IDs
 * @param limb_ids_heatmap: The array of joint IDs that make up the limbs
 * @param all_peaks: All the peaks by heatmap
 * @param mid_points_score_threshold:
 * @param found_mid_points_ratio_threshold:
 * @param candidates: All the candidate peaks for forming into skeletons
 * @param limb_idx: The particular limb (used as an index into the limb arrays)
 * @param possible_poses: We fill this vector with possible poses
 */


We create a giant set of all the most likely connections between possible joints in A to possible joints in B,
such that each possible joint in A can only be connected to at most one of the possible joints in B (and vice versa),
and the weight of this bipartite graph is maximized.

The weight of each of these connections is determined by looking at the PAFs - specifically,
we approximate a line integral from one joint candidate to the other over the right PAF.
Because PAFs are vector fields made so that the vectors point along limbs, if A and B are really connected
(such as neck and right shoulder), we will likely get a good score when computing the line integral, as we
will be traveling along the vector field. If on the other hand, the joints are not connected, we will likely
travel over the vector field wherever there are maginitude 0 vectors or where we are perpendicular to the vector field.


We create a giant set of all the most likely connections between possible joints in A to possible joints in B such that each possible joint in A can only be connected to at most one of the possible joints in B ( and vice versa ) and the weight of this bipartite graph is maximized . The weight of each of these connections is determined by looking at the PAFs - specifically we approximate a line integral from one joint candidate to the other over the right PAF . Because PAFs are vector fields made so that the vectors point along limbs if A and B are really connected ( such as neck and right shoulder ) we will likely get a good score when computing the line integral as we will be traveling along the vector field . If on the other hand the joints are not connected we will likely travel over the vector field wherever there are maginitude 0 vectors or where we are perpendicular to the vector field .
static inline void create_candidate_poses_by_limb(const size_t keypoints_number, const std::vector<cv::Mat> &pafs, const std::pair<int, int> (&limb_ids_paf)[N_PAF_LIMB_PAIRS],
                                                  const std::pair<int, int> (&limb_ids_heatmap)[N_HEATMAP_LIMB_PAIRS], const std::vector<std::vector<Peak>> &all_peaks,
                                                  const float mid_points_score_threshold, const float found_mid_points_ratio_threshold,
                                                  const std::vector<Peak> &candidates, const size_t limb_idx, std::vector<HumanPoseByPeaksIndices> &possible_poses)
{
    const int idx_jointA = limb_ids_heatmap[limb_idx].first - 1;
    const int idx_jointB = limb_ids_heatmap[limb_idx].second - 1;
    const std::vector<Peak> &candidates_for_jointA = all_peaks[idx_jointA];
    const std::vector<Peak> &candidates_for_jointB = all_peaks[idx_jointB];
    const size_t njointsA = candidates_for_jointA.size();
    const size_t njointsB = candidates_for_jointB.size();
    if ((njointsA == 0) || (njointsB == 0))
    {
        maybe_create_possible_poses_from_peaks(njointsA, njointsB, possible_poses, idx_jointA, idx_jointB, candidates_for_jointA, candidates_for_jointB, keypoints_number);
    }
    else
    {
        std::vector<TwoJointsConnection> connections = form_most_promising_joint_connections(keypoints_number, pafs, limb_ids_paf, limb_idx, njointsA, njointsB, candidates_for_jointA, candidates_for_jointB, mid_points_score_threshold, found_mid_points_ratio_threshold);
        create_poses_from_connections(connections, limb_idx, possible_poses, keypoints_number, idx_jointA, idx_jointB, candidates);
    }
}
static inline void create_candidate_poses_by_limb ( const size_t keypoints_number , const std :: vector < cv :: Mat > & pafs , const std :: pair < int , int > ( & limb_ids_paf ) [ N_PAF_LIMB_PAIRS ] , const std :: pair < int , int > ( & limb_ids_heatmap ) [ N_HEATMAP_LIMB_PAIRS ] , const std :: vector < std :: vector < Peak > > & all_peaks , const float mid_points_score_threshold , const float found_mid_points_ratio_threshold , const std :: vector < Peak > & candidates , const size_t limb_idx , std :: vector < HumanPoseByPeaksIndices > & possible_poses ) { const int idx_jointA = limb_ids_heatmap [ limb_idx ] . first - 1 ; const int idx_jointB = limb_ids_heatmap [ limb_idx ] . second - 1 ; const std :: vector < Peak > & candidates_for_jointA = all_peaks [ idx_jointA ] ; const std :: vector < Peak > & candidates_for_jointB = all_peaks [ idx_jointB ] ; const size_t njointsA = candidates_for_jointA . size ( ) ; const size_t njointsB = candidates_for_jointB . size ( ) ; if ( ( njointsA == 0 ) || ( njointsB == 0 ) ) { maybe_create_possible_poses_from_peaks ( njointsA , njointsB , possible_poses , idx_jointA , idx_jointB , candidates_for_jointA , candidates_for_jointB , keypoints_number ) ; } else { std :: vector < TwoJointsConnection > connections = form_most_promising_joint_connections ( keypoints_number , pafs , limb_ids_paf , limb_idx , njointsA , njointsB , candidates_for_jointA , candidates_for_jointB , mid_points_score_threshold , found_mid_points_ratio_threshold ) ; create_poses_from_connections ( connections , limb_idx , possible_poses , keypoints_number , idx_jointA , idx_jointB , candidates ) ; } }
Fills in `possible_poses`.
Fills in ` possible_poses ` .
// A 'limb' is made up of two joints. // Get the heatmap indices for those two joints (the heatmaps that contain the peaks that represent those joints). // Get all the peaks (possible keypoints/joint locations) for the two joints that make up this limb // Get the number of joints in the two heatmaps