Files
ANSCORE/modules/ANSMOT/ByteTrackEigen/src/EigenBoundingBoxTrackUtils.cpp

144 lines
6.2 KiB
C++

#include "EigenBoundingBoxTrackUtils.h"
namespace ByteTrackEigen {
/**
* @brief Joins two lists of KalmanBBoxTrack pointers, ensuring unique track IDs.
*
* This function combines track lists A and B. If a track ID is present in both lists,
* the track from list B is used in the final list. This ensures that each track ID is
* unique in the resulting list.
*
* @param track_list_a First list of shared pointers to KalmanBBoxTrack objects.
* @param track_list_b Second list of shared pointers to KalmanBBoxTrack objects.
* @return std::vector<std::shared_ptr<KalmanBBoxTrack>> A list with unique tracks based on track IDs.
*/
std::vector<std::shared_ptr<KalmanBBoxTrack>> join_tracks(
const std::vector<std::shared_ptr<KalmanBBoxTrack>> track_list_a,
const std::vector<std::shared_ptr<KalmanBBoxTrack>> track_list_b) {
std::map<int, std::shared_ptr<KalmanBBoxTrack>> unique_tracks;
// Populate the map with tracks from track_list_a
for (auto& track : track_list_a) {
unique_tracks[track->get_track_id()] = track;
}
// Insert or overwrite with tracks from track_list_b
for (auto& track : track_list_b) {
unique_tracks[track->get_track_id()] = track;
}
// Convert the unique tracks in the map to a vector
std::vector<std::shared_ptr<KalmanBBoxTrack>> result;
for (auto [key, value] : unique_tracks) {
result.push_back(value);
}
return result;
}
/**
* @brief Subtracts tracks in track_list_b from track_list_a based on track IDs.
*
* This function creates a new list of tracks from track_list_a excluding those
* tracks whose IDs are found in track_list_b, effectively performing a set subtraction.
*
* @param track_list_a First list of shared pointers to KalmanBBoxTrack objects.
* @param track_list_b Second list of shared pointers to KalmanBBoxTrack objects.
* @return std::vector<std::shared_ptr<KalmanBBoxTrack>> A list of tracks present in track_list_a but not in track_list_b.
*/
std::vector<std::shared_ptr<KalmanBBoxTrack>> sub_tracks(
const std::vector<std::shared_ptr<KalmanBBoxTrack>>& track_list_a,
const std::vector<std::shared_ptr<KalmanBBoxTrack>>& track_list_b) {
std::unordered_set<int> track_ids_b;
// Populate set with track IDs from track_list_b for quick lookup
for (const auto& track : track_list_b) {
track_ids_b.insert(track->get_track_id());
}
// Collect tracks from track_list_a not found in track_list_b
std::vector<std::shared_ptr<KalmanBBoxTrack>> result;
for (const auto& track : track_list_a) {
if (track_ids_b.find(track->get_track_id()) == track_ids_b.end()) {
result.push_back(track);
}
}
return result;
}
/**
* @brief Removes duplicate tracks from two lists based on IOU distance and track age.
*
* This function identifies and removes duplicate tracks between two lists based on the
* Intersection Over Union (IOU) distance. If two tracks have an IOU distance less than
* a threshold (0.15), the older track is retained.
*
* @param track_list_a First list of shared pointers to KalmanBBoxTrack objects.
* @param track_list_b Second list of shared pointers to KalmanBBoxTrack objects.
* @return Pair of vectors each containing unique tracks after removing duplicates.
*/
std::pair<std::vector<std::shared_ptr<KalmanBBoxTrack>>, std::vector<std::shared_ptr<KalmanBBoxTrack>>>
remove_duplicate_tracks(const std::vector<std::shared_ptr<KalmanBBoxTrack>> track_list_a,
const std::vector<std::shared_ptr<KalmanBBoxTrack>> track_list_b) {
// Creating instance vectors to store de-referenced shared pointers from the input lists.
// This is necessary for the IOU distance calculation.
std::vector<KalmanBBoxTrack> s_tracks_a_instances;
s_tracks_a_instances.reserve(track_list_a.size());
for (const auto& ptr : track_list_a) {
s_tracks_a_instances.push_back(*ptr);
}
std::vector<KalmanBBoxTrack> s_tracks_b_instances;
s_tracks_b_instances.reserve(track_list_b.size());
for (const auto& ptr : track_list_b) {
s_tracks_b_instances.push_back(*ptr);
}
// Calculating pairwise IOU distance between tracks in both lists.
Eigen::MatrixXd pairwise_distance = iou_distance(s_tracks_a_instances, s_tracks_b_instances);
// Sets to track indices of duplicates in both lists.
std::unordered_set<int> duplicates_a, duplicates_b;
// Loop through the matrix of pairwise distances to identify duplicates.
for (int i = 0; i < pairwise_distance.rows(); ++i) {
for (int j = 0; j < pairwise_distance.cols(); ++j) {
// If IOU distance is below the threshold, consider the tracks as duplicates.
if (pairwise_distance(i, j) < 0.15) {
// Calculate track age to determine which track to keep.
int time_a = track_list_a[i]->get_frame_id() - track_list_a[i]->get_start_frame();
int time_b = track_list_b[j]->get_frame_id() - track_list_b[j]->get_start_frame();
// Retain the older track and mark the newer one as a duplicate.
if (time_a > time_b) {
duplicates_b.insert(j);
}
else {
duplicates_a.insert(i);
}
}
}
}
// Constructing the result lists, excluding the identified duplicates.
std::vector<std::shared_ptr<KalmanBBoxTrack>> result_a, result_b;
for (int i = 0; i < track_list_a.size(); ++i) {
if (duplicates_a.find(i) == duplicates_a.end()) {
result_a.push_back(track_list_a[i]);
}
}
for (int j = 0; j < track_list_b.size(); ++j) {
if (duplicates_b.find(j) == duplicates_b.end()) {
result_b.push_back(track_list_b[j]);
}
}
return { result_a, result_b };
}
}