128 lines
5.7 KiB
C++
128 lines
5.7 KiB
C++
|
|
#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_objects::vp_meta> vp_track_node::handle_control_meta(std::shared_ptr<vp_objects::vp_control_meta> meta) {
|
|
return meta;
|
|
}
|
|
|
|
std::shared_ptr<vp_objects::vp_meta> vp_track_node::handle_frame_meta(std::shared_ptr<vp_objects::vp_frame_meta> meta) {
|
|
// channel_index can be different each call
|
|
auto channel_index = meta->channel_index;
|
|
|
|
// data used for tracking
|
|
std::vector<vp_objects::vp_rect> rects; // rects of targets
|
|
std::vector<std::vector<float>> embeddings; // embeddings of targets
|
|
std::vector<int> 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<vp_objects::vp_frame_meta> frame_meta,
|
|
std::vector<vp_objects::vp_rect>& target_rects,
|
|
std::vector<std::vector<float>>& 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<vp_objects::vp_frame_meta> frame_meta,
|
|
const std::vector<vp_objects::vp_rect>& target_rects,
|
|
const std::vector<std::vector<float>>& target_embeddings,
|
|
const std::vector<int>& 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++;
|
|
}
|
|
}
|
|
}
|
|
} |