| | |
| | | #define SOCKADDR struct sockaddr
|
| | | #define SOCKADDR_IN struct sockaddr_in
|
| | | #define ADDRPOINTER unsigned int*
|
| | | #ifndef INVALID_SOCKET |
| | | #define INVALID_SOCKET -1
|
| | | #endif |
| | | #ifndef SOCKET_ERROR |
| | | #define SOCKET_ERROR -1
|
| | | #endif |
| | | struct _IGNORE_PIPE_SIGNAL
|
| | | {
|
| | | struct sigaction new_actn, old_actn;
|
| | |
| | | void stop_timer_and_show_name(char *name) { stop_timer_and_show(); }
|
| | | void total_time() {}
|
| | | #endif // C++11
|
| | | |
| | | #include <deque> |
| | | #include <vector> |
| | | #include <iostream> |
| | | #include "blas.h" |
| | | #include "utils.h" |
| | | |
| | | struct similarity_detections_t { |
| | | int old_id, new_id; |
| | | float sim; |
| | | }; |
| | | |
| | | int check_prob(detection det, float thresh) |
| | | { |
| | | for (int i = 0; i < det.classes; ++i) { |
| | | if (det.prob[i] > thresh) return 1; |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | int check_classes_id(detection det1, detection det2, float thresh) |
| | | { |
| | | if (det1.classes != det2.classes) { |
| | | printf(" Error: det1.classes != det2.classes \n"); |
| | | getchar(); |
| | | } |
| | | |
| | | int det1_id = -1; |
| | | float det1_prob = 0; |
| | | int det2_id = -1; |
| | | float det2_prob = 0; |
| | | |
| | | for (int i = 0; i < det1.classes; ++i) { |
| | | if (det1.prob[i] > thresh && det1.prob[i] > det1_prob) { |
| | | det1_prob = det1.prob[i]; |
| | | det1_id = i; |
| | | } |
| | | if (det2.prob[i] > thresh && det2.prob[i] > det2_prob) { |
| | | det2_prob = det2.prob[i]; |
| | | det2_id = i; |
| | | } |
| | | } |
| | | |
| | | if (det1_id == det2_id && det2_id != -1) return 1; |
| | | |
| | | //for (int i = 0; i < det1.classes; ++i) { |
| | | // if (det1.prob[i] > thresh && det2.prob[i] > thresh) return 1; |
| | | //} |
| | | return 0; |
| | | } |
| | | |
| | | int fill_remaining_id(detection *new_dets, int new_dets_num, int new_track_id, float thresh, int detection_count) |
| | | { |
| | | for (int i = 0; i < new_dets_num; ++i) { |
| | | if (new_dets[i].track_id == 0 && check_prob(new_dets[i], thresh)) { |
| | | //printf(" old_tid = %d, new_tid = %d, sim = %f \n", new_dets[i].track_id, new_track_id, new_dets[i].sim); |
| | | if (new_dets[i].sort_class > detection_count) { |
| | | new_dets[i].track_id = new_track_id; |
| | | new_track_id++; |
| | | } |
| | | } |
| | | } |
| | | return new_track_id; |
| | | } |
| | | |
| | | float *make_float_array(float* src, size_t size) |
| | | { |
| | | float *dst = (float*)xcalloc(size, sizeof(float)); |
| | | memcpy(dst, src, size*sizeof(float)); |
| | | return dst; |
| | | } |
| | | |
| | | struct detection_t : detection { |
| | | int det_count; |
| | | detection_t(detection det) : detection(det), det_count(0) |
| | | { |
| | | if (embeddings) embeddings = make_float_array(det.embeddings, embedding_size); |
| | | if (prob) prob = make_float_array(det.prob, classes); |
| | | if (uc) uc = make_float_array(det.uc, 4); |
| | | } |
| | | |
| | | detection_t(detection_t const& det) : detection(det) |
| | | { |
| | | if (embeddings) embeddings = make_float_array(det.embeddings, embedding_size); |
| | | if (prob) prob = make_float_array(det.prob, classes); |
| | | if (uc) uc = make_float_array(det.uc, 4); |
| | | } |
| | | |
| | | ~detection_t() { |
| | | if (embeddings) free(embeddings); |
| | | if (prob) free(prob); |
| | | if (uc) free(uc); |
| | | } |
| | | }; |
| | | |
| | | |
| | | |
| | | void set_track_id(detection *new_dets, int new_dets_num, float thresh, float sim_thresh, float track_ciou_norm, int deque_size, int dets_for_track, int dets_for_show) |
| | | { |
| | | static int new_track_id = 1; |
| | | static std::deque<std::vector<detection_t>> old_dets_dq; |
| | | |
| | | // copy detections from queue of vectors to the one vector |
| | | std::vector<detection_t> old_dets; |
| | | for (std::vector<detection_t> &v : old_dets_dq) { |
| | | for (int i = 0; i < v.size(); ++i) { |
| | | old_dets.push_back(v[i]); |
| | | } |
| | | } |
| | | |
| | | std::vector<similarity_detections_t> sim_det(old_dets.size() * new_dets_num); |
| | | |
| | | // calculate similarity |
| | | for (int old_id = 0; old_id < old_dets.size(); ++old_id) { |
| | | for (int new_id = 0; new_id < new_dets_num; ++new_id) { |
| | | const int index = old_id*new_dets_num + new_id; |
| | | const float sim = cosine_similarity(new_dets[new_id].embeddings, old_dets[old_id].embeddings, old_dets[0].embedding_size); |
| | | sim_det[index].new_id = new_id; |
| | | sim_det[index].old_id = old_id; |
| | | sim_det[index].sim = sim; |
| | | } |
| | | } |
| | | |
| | | // sort similarity |
| | | std::sort(sim_det.begin(), sim_det.end(), [](similarity_detections_t v1, similarity_detections_t v2) { return v1.sim > v2.sim; }); |
| | | //if(sim_det.size() > 0) printf(" sim_det_first = %f, sim_det_end = %f \n", sim_det.begin()->sim, sim_det.rbegin()->sim); |
| | | |
| | | std::vector<int> new_idx(new_dets_num, 1); |
| | | std::vector<int> old_idx(old_dets.size(), 1); |
| | | std::vector<int> track_idx(new_track_id, 1); |
| | | |
| | | // match objects |
| | | for (int index = 0; index < new_dets_num*old_dets.size(); ++index) { |
| | | const int new_id = sim_det[index].new_id; |
| | | const int old_id = sim_det[index].old_id; |
| | | const int track_id = old_dets[old_id].track_id; |
| | | const int det_count = old_dets[old_id].sort_class; |
| | | //printf(" ciou = %f \n", box_ciou(new_dets[new_id].bbox, old_dets[old_id].bbox)); |
| | | if (track_idx[track_id] && new_idx[new_id] && old_idx[old_id] && check_classes_id(new_dets[new_id], old_dets[old_id], thresh)) { |
| | | float sim = sim_det[index].sim; |
| | | //float ciou = box_ciou(new_dets[new_id].bbox, old_dets[old_id].bbox); |
| | | float ciou = box_iou(new_dets[new_id].bbox, old_dets[old_id].bbox); |
| | | sim = sim * (1 - track_ciou_norm) + ciou * track_ciou_norm; |
| | | if (sim_thresh < sim && new_dets[new_id].sim < sim) { |
| | | new_dets[new_id].sim = sim; |
| | | new_dets[new_id].track_id = track_id; |
| | | new_dets[new_id].sort_class = det_count + 1; |
| | | //new_idx[new_id] = 0; |
| | | old_idx[old_id] = 0; |
| | | if(track_id) track_idx[track_id] = 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // set new track_id |
| | | new_track_id = fill_remaining_id(new_dets, new_dets_num, new_track_id, thresh, dets_for_track); |
| | | |
| | | // store new_detections to the queue of vectors |
| | | std::vector<detection_t> new_det_vec; |
| | | for (int i = 0; i < new_dets_num; ++i) { |
| | | if (check_prob(new_dets[i], thresh)) { |
| | | new_det_vec.push_back(new_dets[i]); |
| | | } |
| | | } |
| | | |
| | | // add new |
| | | old_dets_dq.push_back(new_det_vec); |
| | | // remove old |
| | | if (old_dets_dq.size() > deque_size) old_dets_dq.pop_front(); |
| | | |
| | | // remove detection which were detected only on few frames |
| | | for (int i = 0; i < new_dets_num; ++i) { |
| | | if (new_dets[i].sort_class < dets_for_show) { |
| | | for (int j = 0; j < new_dets[i].classes; ++j) { |
| | | new_dets[i].prob[j] = 0; |
| | | } |
| | | } |
| | | } |
| | | } |