|
|
#include "vp_ba_person_gathering_node.h"
|
|
namespace vp_nodes
|
{
|
|
vp_ba_person_gathering_node::vp_ba_person_gathering_node(std::string node_name,
|
int min_gathering_person,
|
bool need_record_image,
|
bool need_record_video) : vp_node(node_name), min_gathering_person(min_gathering_person), need_record_image(need_record_image), need_record_video(need_record_video)
|
{
|
VP_INFO(vp_utils::string_format("[%s] %s", node_name.c_str(), to_string().c_str()));
|
this->initialized();
|
}
|
|
vp_ba_person_gathering_node::~vp_ba_person_gathering_node()
|
{
|
deinitialized();
|
}
|
|
std::string vp_ba_person_gathering_node::to_string()
|
{
|
/*
|
* return vertexs of all jam regions
|
* [channel0: x1,y1 x2,y2 ...][channel1: x1,y1 x2,y2 ...]...
|
*/
|
|
return "vp_ba_person_gathering_node";
|
}
|
|
bool vp_ba_person_gathering_node::isNearby(int p1_width, int p1_x, int p1_y, int p2_width, int p2_x, int p2_y, float factor)
|
{
|
// 动态距离根据宽度计算
|
float dynamicDistance = std::max(p1_width, p2_width) * factor;
|
|
// 欧几里得距离计算
|
float dx = p1_x - p2_x;
|
float dy = p1_y - p2_y;
|
float distance = std::sqrt(dx * dx + dy * dy);
|
|
return distance < dynamicDistance;
|
}
|
|
std::shared_ptr<vp_objects::vp_meta> vp_ba_person_gathering_node::handle_frame_meta(std::shared_ptr<vp_objects::vp_frame_meta> meta)
|
{
|
// for current channel
|
auto &person_gathering_checking_status = all_person_gathering_checking_status[meta->channel_index];
|
auto &person_gathering_result = all_person_gathering_results[meta->channel_index];
|
auto &last_notify = all_last_notifys[meta->channel_index];
|
|
// for vp_frame_target only
|
std::vector<int> hit_traget_ids;
|
for (auto &target : meta->targets)
|
{
|
if (target->primary_label == target->class_label_of_person)
|
{
|
auto len = target->tracks.size();
|
// auto loc = target->get_rect().track_point();
|
|
// target has been tracked AND tracked enough frames
|
if (len < check_interval_frames || target->track_id < 0)
|
{
|
continue;
|
}
|
// if target inside of stop region or not
|
// if (!point_in_poly(loc, jam_region))
|
//{
|
// continue;
|
//}
|
|
bool is_this_target_gathering= false;
|
|
for (auto &tempTarget : meta->targets)
|
{
|
|
if (isNearby(target->width, target->x, target->y, tempTarget->width, tempTarget->x, tempTarget->y, person_gathering_distance_factor))
|
{
|
is_this_target_gathering = true;
|
//person_gathering_checking_status[target->track_id]++;
|
//hit_traget_ids.push_back(target->track_id);
|
}
|
}
|
if (is_this_target_gathering)
|
{
|
person_gathering_checking_status[target->track_id]++;
|
hit_traget_ids.push_back(target->track_id);
|
|
}
|
}
|
}
|
|
// count for stop targets
|
auto personGathers = 0;
|
std::vector<int> involve_targets;
|
for (auto i = person_gathering_checking_status.begin(); i != person_gathering_checking_status.end();)
|
{
|
if (std::find(hit_traget_ids.begin(), hit_traget_ids.end(), i->first) == hit_traget_ids.end())
|
{
|
// remove since it not satisfy stop condition
|
i = person_gathering_checking_status.erase(i);
|
continue;
|
}
|
if (i->second >= check_min_hit_frames)
|
{
|
involve_targets.push_back(i->first);
|
personGathers++;
|
}
|
i++;
|
}
|
VP_INFO(std::to_string(involve_targets.size()));
|
|
|
|
if (personGathers >= min_gathering_person && !person_gathering_result && (meta->frame_index - last_notify) > (check_notify_interval * meta->fps))
|
{
|
person_gathering_result = true;
|
last_notify = meta->frame_index;
|
// send record image and record video signal, recording actions would occur if record nodes exist in pipeline
|
std::string image_file_name_without_ext = ""; // empty means no recording image
|
std::string video_file_name_without_ext = ""; // empty means no recording video
|
|
// send image record control meta
|
if (need_record_image)
|
{
|
image_file_name_without_ext = vp_utils::time_format(NOW, "person_gathering_image__<year><mon><day><hour><min><sec><mili>");
|
auto image_record_control_meta = std::make_shared<vp_objects::vp_image_record_control_meta>(meta->channel_index, image_file_name_without_ext, true);
|
pendding_meta(image_record_control_meta);
|
}
|
// send video record control meta
|
if (need_record_video)
|
{
|
video_file_name_without_ext = vp_utils::time_format(NOW, "person_gathering_video__<year><mon><day><hour><min><sec><mili>");
|
auto video_record_control_meta = std::make_shared<vp_objects::vp_video_record_control_meta>(meta->channel_index, video_file_name_without_ext);
|
pendding_meta(video_record_control_meta);
|
}
|
|
std::vector<vp_objects::vp_point> involve_region;
|
auto ba_result = std::make_shared<vp_objects::vp_ba_result>(vp_objects::vp_ba_type::GATHERING,
|
meta->channel_index,
|
meta->frame_index,
|
involve_targets,
|
involve_region,
|
"person_gathering", // meaningful label
|
image_file_name_without_ext,
|
video_file_name_without_ext);
|
// fill back to frame meta
|
meta->ba_results.push_back(ba_result);
|
// info log
|
VP_INFO(vp_utils::string_format("[%s] [channel %d] has found target person falldown.", node_name.c_str(), meta->channel_index));
|
if (need_record_image || need_record_video)
|
{
|
VP_INFO(vp_utils::string_format("[%s] [channel %d] image & video record file names are: [%s & %s]", node_name.c_str(), meta->channel_index, image_file_name_without_ext.c_str(), video_file_name_without_ext.c_str()));
|
}
|
}
|
if (personGathers < min_gathering_person && person_gathering_result)
|
{
|
person_gathering_result = false;
|
last_notify = meta->frame_index;
|
}
|
return meta;
|
}
|
}
|