14 std::vector<ClassScore> classScores;
17double box_diagonal(
const cv::Rect_<float>& box)
19 return std::sqrt(box.width * box.width + box.height * box.height);
22double box_area(
const cv::Rect_<float>& box)
24 return std::max(0.0f, box.width) * std::max(0.0f, box.height);
27double aspect_ratio(
const cv::Rect_<float>& box)
29 if (box.width <= 0.0f || box.height <= 0.0f)
31 return static_cast<double>(box.width) /
static_cast<double>(box.height);
34bool box_shape_matches(
const cv::Rect_<float>& predicted_box,
const cv::Rect_<float>& detection_box,
double iou)
36 const double predicted_area = box_area(predicted_box);
37 const double detection_area = box_area(detection_box);
38 if (predicted_area <= 1.0 || detection_area <= 1.0)
41 const double area_ratio = detection_area / predicted_area;
42 const double predicted_aspect = aspect_ratio(predicted_box);
43 const double detection_aspect = aspect_ratio(detection_box);
44 const double aspect_ratio_delta = (predicted_aspect > 0.0 && detection_aspect > 0.0)
45 ? std::max(predicted_aspect / detection_aspect, detection_aspect / predicted_aspect)
49 return area_ratio >= 0.20 && area_ratio <= 5.00 && aspect_ratio_delta <= 4.00;
50 return area_ratio >= 0.35 && area_ratio <= 2.80 && aspect_ratio_delta <= 2.75;
53bool detection_matches_track_gate(
55 const cv::Rect_<float>& predicted_box,
56 const DetectionBox& detection,
58 double centroid_distance)
60 if (!box_shape_matches(predicted_box, detection.box, iou))
63 const double scale = std::max(box_diagonal(predicted_box), box_diagonal(detection.box));
66 if (missed_previous_frame) {
67 const double reacquire_distance = std::max(12.0, scale * 0.25);
68 return iou >= 0.35 || centroid_distance <= reacquire_distance;
71 const double local_distance = std::max(12.0, scale * 0.22);
72 return iou >= 0.20 || centroid_distance <= local_distance;
92 float in = (bb_test & bb_gt).area();
93 float un = bb_test.area() + bb_gt.area() - in;
98 return (
double)(in / un);
103 cv::Rect_<float> bb_test,
104 cv::Rect_<float> bb_gt)
106 float bb_test_centroid_x = (bb_test.x + bb_test.width / 2);
107 float bb_test_centroid_y = (bb_test.y + bb_test.height / 2);
109 float bb_gt_centroid_x = (bb_gt.x + bb_gt.width / 2);
110 float bb_gt_centroid_y = (bb_gt.y + bb_gt.height / 2);
112 double distance = (double)sqrt(pow(bb_gt_centroid_x - bb_test_centroid_x, 2) + pow(bb_gt_centroid_y - bb_test_centroid_y, 2));
118void apply_nms(vector<DetectionBox>& detections,
double nms_iou_thresh) {
119 if (detections.empty())
return;
122 std::sort(detections.begin(), detections.end(), [](
const DetectionBox& a,
const DetectionBox& b) {
123 return a.confidence > b.confidence;
126 vector<bool> suppressed(detections.size(),
false);
128 for (
size_t i = 0; i < detections.size(); ++i) {
129 if (suppressed[i])
continue;
131 for (
size_t j = i + 1; j < detections.size(); ++j) {
132 if (suppressed[j])
continue;
135 if ((detections[i].classId == detections[j].classId && iou > nms_iou_thresh) ||
137 suppressed[j] =
true;
143 vector<DetectionBox> filtered;
144 for (
size_t i = 0; i < detections.size(); ++i) {
145 if (!suppressed[i]) {
146 filtered.push_back(detections[i]);
149 detections = filtered;
152void SortTracker::update(vector<cv::Rect> detections_cv,
int frame_count,
double image_diagonal, std::vector<float> confidences, std::vector<int> classIds, std::vector<std::vector<ClassScore>> classScores)
154 vector<DetectionBox> detections;
156 if (classScores.size() != detections_cv.size())
157 classScores.resize(detections_cv.size());
162 for (
unsigned int i = 0; i < detections_cv.size(); i++)
164 if (confidences[i] <
_min_conf)
continue;
168 tb.box = cv::Rect_<float>(detections_cv[i]);
169 tb.classId = classIds[i];
170 tb.confidence = confidences[i];
171 tb.classScores = classScores[i];
172 detections.push_back(tb);
177 for (
const auto& detection : detections)
186 for (
unsigned int i = 0; i < detections_cv.size(); i++)
188 if (confidences[i] <
_min_conf)
continue;
191 tb.box = cv::Rect_<float>(detections_cv[i]);
192 tb.classId = classIds[i];
193 tb.confidence = confidences[i];
194 tb.classScores = classScores[i];
195 detections.push_back(tb);
205 for (
unsigned int i = 0; i <
trackers.size();)
207 cv::Rect_<float> pBox =
trackers[i].predict();
208 if (pBox.x >= 0 && pBox.y >= 0)
218 detNum = detections.size();
231 for (
auto& detection : detections)
239 for (
unsigned int i = 0; i <
trkNum; ++i)
245 for (
unsigned int i = 0; i <
trkNum; i++)
247 for (
unsigned int j = 0; j <
detNum; j++)
257 const double scale = std::max(1.0, std::max(box_diagonal(
predictedBoxes[i]), box_diagonal(detections[j].box)));
258 const double distance_penalty = std::min(1.0, centroid_distance / scale) * 0.35;
259 cost_matrix[i][j] = 1 - iou + distance_penalty + (1 - detections[j].confidence) * 0.1;
270 for (
unsigned int n = 0; n <
detNum; n++)
273 for (
unsigned int i = 0; i <
trkNum; ++i)
282 for (
unsigned int i = 0; i <
trkNum; ++i)
290 for (
unsigned int i = 0; i <
trkNum; ++i)
308 trackers[trkIdx].update(detections[detIdx].box);
309 trackers[trkIdx].update_class_scores(detections[detIdx].classScores, detections[detIdx].classId, detections[detIdx].confidence);
310 trackers[trkIdx].confidence = detections[detIdx].confidence;
322 for (
unsigned int i = 0; i <
trackers.size();)
334 res.
frame = frame_count;
double Solve(std::vector< std::vector< double > > &DistMatrix, std::vector< int > &Assignment)
This class represents the internel state of individual tracked objects observed as bounding box.
std::vector< int > dead_trackers_id
std::vector< TrackingBox > frameTrackingResult
std::set< int > unmatchedDetections
void update(std::vector< cv::Rect > detection, int frame_count, double image_diagonal, std::vector< float > confidences, std::vector< int > classIds, std::vector< std::vector< ClassScore > > classScores={})
std::vector< std::vector< double > > cost_matrix
std::vector< cv::Point > matchedPairs
double GetCentroidsDistance(cv::Rect_< float > bb_test, cv::Rect_< float > bb_gt)
std::vector< KalmanTracker > trackers
std::vector< cv::Rect_< float > > predictedBoxes
std::vector< int > assignment
std::set< int > matchedItems
std::set< int > unmatchedTrajectories
static double GetIOU(cv::Rect_< float > bb_test, cv::Rect_< float > bb_gt)
SortTracker(int max_age=50, int min_hits=5, int max_missed=3, double min_iou=0.1, double nms_iou_thresh=0.5, double min_conf=0.3)
void apply_nms(vector< DetectionBox > &detections, double nms_iou_thresh)