#include "vp_track_node.h" //#include "../objects/shapes/vp_rect.h" namespace vp_nodes { vp_track_node::vp_track_node(std::string node_name, vp_track_for track_for): vp_node(node_name), track_for(track_for) { } vp_track_node::~vp_track_node() { } std::shared_ptr vp_track_node::handle_control_meta(std::shared_ptr meta) { return meta; } std::shared_ptr vp_track_node::handle_frame_meta(std::shared_ptr meta) { // channel_index can be different each call auto channel_index = meta->channel_index; // data used for tracking std::vector rects; // rects of targets std::vector> embeddings; // embeddings of targets std::vector track_ids; // track ids of targets // step 1, collect data preprocess(meta, rects, embeddings); // step 2, track by channel track(channel_index, rects, embeddings, track_ids); // step 3, postprocess postprocess(meta, rects, embeddings, track_ids); return meta; } void vp_track_node::preprocess(std::shared_ptr frame_meta, std::vector& target_rects, std::vector>& target_embeddings) { if (track_for == vp_track_for::NORMAL) { for(auto& i: frame_meta->targets) { target_rects.push_back(i->get_rect()); // rect fo target (via i variable) target_embeddings.push_back(i->embeddings); // embeddings of target (via i variable) } } if (track_for == vp_track_for::FACE) { for(auto& i: frame_meta->face_targets) { target_rects.push_back(i->get_rect()); // rect of face target (via i variable) target_embeddings.push_back(i->embeddings); // embeddings of face target (via i variable) } } /* ... extend for more track for... */ } // write track_ids back to frame meta // we can also cache history rects for each target, and then push them back to tracks field (such as vp_frame_target::tracks) void vp_track_node::postprocess(std::shared_ptr frame_meta, const std::vector& target_rects, const std::vector>& target_embeddings, const std::vector& track_ids) { if (track_ids.empty()) { return; } // assert for length of vectors since they are generated by step1 & step2 separately // assert(target_rects.size() == target_embeddings.size()); assert(target_rects.size() == track_ids.size()); // support multi channels auto& tracks_by_id = all_tracks_by_id[frame_meta->channel_index]; auto& last_tracked_frame_indexes = all_last_tracked_frame_indexes[frame_meta->channel_index]; if (track_for == vp_track_for::NORMAL) { //assert(target_rects.size() == frame_meta->targets.size()); for (int i = 0; i < frame_meta->targets.size(); i++) { auto& target = frame_meta->targets[i]; auto& rect = target_rects[i]; auto& track_id = track_ids[i]; // -1 means no track result returned yet if (track_id != -1) { tracks_by_id[track_id].push_back(rect); // cache last_tracked_frame_indexes[track_id] = frame_meta->frame_index; // update stamp target->track_id = track_id; // write track_id back to target target->tracks = tracks_by_id[track_id]; // write tracks back to target } } } if (track_for == vp_track_for::FACE) { // assert(target_rects.size() == frame_meta->face_targets.size()); for (int i = 0; i < frame_meta->face_targets.size(); i++) { auto& face = frame_meta->face_targets[i]; auto& rect = target_rects[i]; auto& track_id = track_ids[i]; // -1 means no track result returned yet if (track_id != -1) { tracks_by_id[track_id].push_back(rect); // cache last_tracked_frame_indexes[track_id] = frame_meta->frame_index; // update stamp face->track_id = track_id; // write track_id back to face target face->tracks = tracks_by_id[track_id]; // write tracks back to face target } } } /* ... extend for more track for... */ // remove cache tracks if has been long time since last updated (maybe it disappeared already). for (auto i = last_tracked_frame_indexes.begin(); i != last_tracked_frame_indexes.end();) { if (frame_meta->frame_index - (i->second) > max_allowed_disappear_frames || frame_meta->frame_index < i->second) { VP_DEBUG(vp_utils::string_format("[%s] [tracking] long time no update, so erase cache of tracks for track_id:`%d`, size of tracks is:`%d`", node_name.c_str(), i->first, tracks_by_id[i->first].size())); tracks_by_id.erase(i->first); // erase tracks first i = last_tracked_frame_indexes.erase(i); // erase stamp then } else { i++; } } } }