#include "tracker.h" #include "nn_matching.h" #include "model.h" #include "linear_assignment.h" #include using namespace std; //#define MY_inner_DEBUG #ifdef MY_inner_DEBUG #include #include #endif tracker::tracker( float max_cosine_distance, int nn_budget, float max_iou_distance, int max_age, int n_init) { this->metric = new NearNeighborDisMetric( NearNeighborDisMetric::METRIC_TYPE::cosine, max_cosine_distance, nn_budget); this->max_iou_distance = max_iou_distance; this->max_age = max_age; this->n_init = n_init; this->kf = new KalmFilter(); this->tracks.clear(); this->_next_idx = 1; } tracker::~tracker() { // delete this->metric; // delete this->kf; } void tracker::predict() { for(auto& track:tracks) { track->predit(this->kf); } } void tracker::update(std::vector> &CAMERAS_VCT, const DETECTIONS &detections, int cam_id, char* img_time) { TRACHER_MATCHD res; // for (map>::iterator iter=candidate_track_map.begin();iter!=candidate_track_map.end();iter++) // { // this->tracks.push_back(iter->second); // printf("-------------------this->tracks.size:%d\n",this->tracks.size()); // } // std::cout<< "size1:"<< detections.size() << std::endl; // if (detections.size()==2){ // for (DETECTION_ROW det : detections) // { // std::cout<< det.feature <& matches = res.matches; //#ifdef MY_inner_DEBUG // printf("res.matches size = %d:\n", matches.size()); //#endif for(MATCH_DATA& data:matches) { int track_idx = data.first; int detection_idx = data.second; //#ifdef MY_inner_DEBUG // printf("\t%d == %d;\n", track_idx, detection_idx); //#endif tracks[track_idx]->update(this->kf, detections[detection_idx], img_time); // LOG(INFO) << "=======match-track_idx::" << tracks[track_idx]->track_id; // DEBUG( "=======match-track_idx::" + to_string(tracks[track_idx]->track_id)); } vector& unmatched_tracks = res.unmatched_tracks; //#ifdef MY_inner_DEBUG // printf("res.unmatched_tracks size = %d\n", unmatched_tracks.size()); //#endif for(int& track_idx:unmatched_tracks) { this->tracks[track_idx]->mark_missed(img_time); } vector& unmatched_detections = res.unmatched_detections; //#ifdef MY_inner_DEBUG // printf("res.unmatched_detections size = %d\n", unmatched_detections.size()); //#endif for(int& detection_idx:unmatched_detections) { this->_initiate_track(detections[detection_idx], cam_id, img_time); } //#ifdef MY_inner_DEBUG // int size = tracks.size(); // printf("now track size = %d\n", size); //#endif vector>::iterator it; for(it = tracks.begin(); it != tracks.end();) { if((*it)->is_deleted()) it = tracks.erase(it); else ++it; } //#ifdef MY_inner_DEBUG // printf("update track size = %d\n", tracks.size()); //#endif /* old version: //update distance metric: FEATURESS features; vector targets; vector active_targets; int pos = 0; for(Track track:tracks) { if(track.is_confirmed() == false) continue; active_targets.push_back(track.track_id); features.row(pos) = track.features; int rows = track.features.rows(); pos += rows; for(int i = 0; i < rows; i++) targets.push_back(track.track_id); //attention!!! //track.features.clear(); track.features = Eigen::Matrix(0,128); } this->metric->partial_fit(features, targets, active_targets); */ vector active_targets; vector tid_features; for (auto& track:tracks) { if(track->is_confirmed() == false) continue; active_targets.push_back(track->track_id); tid_features.push_back(std::make_pair(track->track_id, track->features)); FEATURESS t = FEATURESS(0, 128); track->features = t; } this->metric->partial_fit(tid_features, active_targets); } void tracker::_match(const DETECTIONS &detections, TRACHER_MATCHD &res) { DEBUG("tracker.cpp _match start 147:: "); vector confirmed_tracks; vector unconfirmed_tracks; int idx = 0; for(auto& t:tracks) { if(t->is_confirmed()) confirmed_tracks.push_back(idx); else unconfirmed_tracks.push_back(idx); idx++; } TRACHER_MATCHD matcha = linear_assignment::getInstance()->matching_cascade( this, &tracker::gated_matric, this->metric->mating_threshold, this->max_age, this->tracks, detections, confirmed_tracks); vector iou_track_candidates; iou_track_candidates.assign(unconfirmed_tracks.begin(), unconfirmed_tracks.end()); vector::iterator it; for(it = matcha.unmatched_tracks.begin(); it != matcha.unmatched_tracks.end();) { int idx = *it; if(tracks[idx]->time_since_update == 1) { //push into unconfirmed iou_track_candidates.push_back(idx); it = matcha.unmatched_tracks.erase(it); continue; } ++it; } TRACHER_MATCHD matchb = linear_assignment::getInstance()->min_cost_matching( this, &tracker::iou_cost, this->max_iou_distance, this->tracks, detections, iou_track_candidates, matcha.unmatched_detections); //get result: res.matches.assign(matcha.matches.begin(), matcha.matches.end()); res.matches.insert(res.matches.end(), matchb.matches.begin(), matchb.matches.end()); //unmatched_tracks; res.unmatched_tracks.assign( matcha.unmatched_tracks.begin(), matcha.unmatched_tracks.end()); res.unmatched_tracks.insert( res.unmatched_tracks.end(), matchb.unmatched_tracks.begin(), matchb.unmatched_tracks.end()); res.unmatched_detections.assign( matchb.unmatched_detections.begin(), matchb.unmatched_detections.end()); DEBUG("tracker.cpp _match end 207:: "); } void tracker::_initiate_track(const DETECTION_ROW &detection, int cam_id, char* img_time) { KAL_DATA data = kf->initiate(detection.to_xyah()); KAL_MEAN mean = data.first; KAL_COVA covariance = data.second; uint64_t n_track_id; stringstream strValue; strValue << random_int(8); strValue >> n_track_id; // n_track_id = m_staticStruct::human_ids++; auto t = std::make_shared(mean, covariance, n_track_id, this->n_init, this->max_age, detection.feature, img_time); t->xywh = detection.tlwh; this->tracks.push_back(t); // auto t = std::make_shared(mean, covariance, this->_next_idx, this->n_init,this->max_age, detection.feature); // this->tracks.push_back(t); // // _next_idx += 1; } DYNAMICM tracker::gated_matric( std::vector> &tracks, const DETECTIONS &dets, const std::vector& track_indices, const std::vector& detection_indices) { // FEATURESS features(detection_indices.size(), 128); // int pos = 0; // for(int i:detection_indices) { // features.row(pos++) = dets[i].feature; // } vector targets; for(int i:track_indices) { targets.push_back(tracks[i]->track_id); } // DYNAMICM cost_matrix = this->metric->distance(features, targets); DYNAMICM cost_matrix = Eigen::MatrixXf::Zero(targets.size(), detection_indices.size()); DYNAMICM res = linear_assignment::getInstance()->gate_cost_matrix( this->kf, cost_matrix, tracks, dets, track_indices, detection_indices); return res; } DYNAMICM tracker::cos_matric( std::vector > &tracks, const DETECTIONS &dets, const std::vector &track_indices, const std::vector &detection_indices) { FEATURESS features(detection_indices.size(), 128); int pos = 0; for(int i : detection_indices) { features.row(pos++) = dets[i].feature; } std::map simples; for(auto i : track_indices) { simples[tracks[i]->track_id] = tracks[i]->features; } DYNAMICM res = this->metric->cos_distance(features, simples); return res; } DYNAMICM tracker::iou_cost( std::vector> &tracks, const DETECTIONS &dets, const std::vector& track_indices, const std::vector& detection_indices) { //!!!python diff: track_indices && detection_indices will never be None. // if(track_indices.empty() == true) { // for(size_t i = 0; i < tracks.size(); i++) { // track_indices.push_back(i); // } // } // if(detection_indices.empty() == true) { // for(size_t i = 0; i < dets.size(); i++) { // detection_indices.push_back(i); // } // } int rows = track_indices.size(); int cols = detection_indices.size(); DYNAMICM cost_matrix = Eigen::MatrixXf::Zero(rows, cols); for(int i = 0; i < rows; i++) { int track_idx = track_indices[i]; if(tracks[track_idx]->time_since_update > 1) { cost_matrix.row(i) = Eigen::RowVectorXf::Constant(cols, INFTY_COST); continue; } DETECTBOX bbox = tracks[track_idx]->to_tlwh(); int csize = detection_indices.size(); DETECTBOXSS candidates(csize, 4); for(int k = 0; k < csize; k++) candidates.row(k) = dets[detection_indices[k]].tlwh; Eigen::RowVectorXf rowV = (1. - iou(bbox, candidates).array()).matrix().transpose(); cost_matrix.row(i) = rowV; } return cost_matrix; } Eigen::VectorXf tracker::iou(DETECTBOX& bbox, DETECTBOXSS& candidates) { float bbox_tl_1 = bbox[0]; float bbox_tl_2 = bbox[1]; float bbox_br_1 = bbox[0] + bbox[2]; float bbox_br_2 = bbox[1] + bbox[3]; float area_bbox = bbox[2] * bbox[3]; Eigen::Matrix candidates_tl; Eigen::Matrix candidates_br; candidates_tl = candidates.leftCols(2) ; candidates_br = candidates.rightCols(2) + candidates_tl; int size = int(candidates.rows()); // Eigen::VectorXf area_intersection(size); // Eigen::VectorXf area_candidates(size); Eigen::VectorXf res(size); for(int i = 0; i < size; i++) { float tl_1 = std::max(bbox_tl_1, candidates_tl(i, 0)); float tl_2 = std::max(bbox_tl_2, candidates_tl(i, 1)); float br_1 = std::min(bbox_br_1, candidates_br(i, 0)); float br_2 = std::min(bbox_br_2, candidates_br(i, 1)); float w = br_1 - tl_1; w = (w < 0? 0: w); float h = br_2 - tl_2; h = (h < 0? 0: h); float area_intersection = w * h; float area_candidates = candidates(i, 2) * candidates(i, 3); res[i] = area_intersection/(area_bbox + area_candidates - area_intersection); } //#ifdef MY_inner_DEBUG // std::cout << res << std::endl; //#endif return res; }