first commit
This commit is contained in:
128
nodes/track/vp_track_node.cpp
Normal file
128
nodes/track/vp_track_node.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
#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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user