Files
VideoPipe/nodes/broker/vp_plate_socket_broker_node.cpp
2026-06-03 12:43:14 +08:00

160 lines
7.4 KiB
C++

#include "vp_plate_socket_broker_node.h"
namespace vp_nodes {
vp_plate_socket_broker_node::vp_plate_socket_broker_node(std::string node_name,
std::string des_ip,
int des_port,
std::string plates_dir,
int min_crop_width,
int min_crop_height,
vp_broke_for broke_for,
bool only_for_tracked,
int broking_cache_warn_threshold,
int broking_cache_ignore_threshold):
vp_msg_broker_node(node_name, broke_for, broking_cache_warn_threshold, broking_cache_ignore_threshold),
des_ip(des_ip),
des_port(des_port),
plates_dir(plates_dir),
min_crop_width(min_crop_width),
min_crop_height(min_crop_height),
only_for_tracked(only_for_tracked) {
// only for vp_frame_target
assert(broke_for == vp_broke_for::NORMAL);
udp_writer = kissnet::udp_socket(kissnet::endpoint(des_ip, des_port));
VP_INFO(vp_utils::string_format("[%s] [message broker] set des_ip as `%s` and des_port as [%d]", node_name.c_str(), des_ip.c_str(), des_port));
this->initialized();
}
vp_plate_socket_broker_node::~vp_plate_socket_broker_node() {
deinitialized();
stop_broking();
}
void vp_plate_socket_broker_node::format_msg(const std::shared_ptr<vp_objects::vp_frame_meta>& meta, std::string& msg) {
/* format:
line 0, <--
line 1, 1st time
line 2, 1st channel index, frame index
line 3, 1st the cropped image's path
line 4, 1st the whole image's path
line 5, 1st plate color
line 6, 1st plate text
line 7, -->
line 8, <--
line 9, 2nd time
line 10, 2nd channel index, frame index
line 11, 2nd the cropped image's path
line 12, 2nd the whole image's path
line 13, 2nd plate color
line 14, 2nd plate text
line 15, -->
line 16, ...
*/
auto& broked_ids = all_broked_ids[meta->channel_index];
auto& broked_texts = all_broked_texts[meta->channel_index];
// remove 50 elements every 100 ids
if (broked_ids.size() > 100) {
broked_ids.erase(broked_ids.begin(), broked_ids.begin() + 50);
}
if (broked_texts.size() > 100) {
broked_texts.erase(broked_texts.begin(), broked_texts.begin() + 50);
}
std::stringstream msg_stream;
auto format_basic_info = [&](int channel_index, int frame_index) {
msg_stream << vp_utils::time_format(NOW) << std::endl; // line1
msg_stream << channel_index << "," << frame_index << std::endl; // line2
};
auto save_cropped_image = [&](cv::Mat& frame, cv::Rect rect, std::string name) {
auto cropped = frame(rect);
cv::imwrite(name, cropped);
msg_stream << name << std::endl; // line3
};
auto save_whole_image = [&](cv::Mat& frame, std::string name) {
cv::imwrite(name, frame);
msg_stream << name << std::endl; // line4
};
auto format_plate = [&](const std::string& plate_color, const std::string& plate_text) {
msg_stream << plate_color << std::endl; // line5
msg_stream << plate_text << std::endl; // line6
};
if (broke_for == vp_broke_for::NORMAL) {
for (int i = 0; i < meta->targets.size(); i++) {
auto& t = meta->targets[i];
// only broke for tracked targets and have enough frames
if ((only_for_tracked && t->track_id < 0) || (only_for_tracked && t->tracks.size() < min_tracked_frames)) {
continue;
}
// only broke 1 time for specific track id if it has been tracked, or broke many times
if (t->track_id >= 0 &&
std::find(broked_ids.begin(), broked_ids.end(), t->track_id) != broked_ids.end()) {
broked_ids.push_back(t->track_id);
continue;
}
// size filter
if (t->width < min_crop_width || t->height < min_crop_height) {
continue;
}
auto color_and_text = vp_utils::string_split(t->primary_label, '_');
// make sure plate text and color detected
if(color_and_text.size() != 2) {
continue;
}
auto& color = color_and_text[0];
auto& text = color_and_text[1];
// check for length, 7 or 3 + 6 or 3 + 7
if (text.length() != 7 && text.length() != 9 && text.length() != 10) {
continue;
}
// only broke 1 time for specific plate text in small period
if (std::find(broked_texts.begin(), broked_texts.end(), text) != broked_texts.end()) {
broked_texts.push_back(text);
continue;
}
// cache for texts
broked_texts.push_back(text);
// cache for ids
if (t->track_id >= 0) {
broked_ids.push_back(t->track_id);
}
auto cropped_name = plates_dir + "/" + std::to_string(t->channel_index) + "_" + std::to_string(t->frame_index) + "_" + color + "_" + text + "_cropped.jpg";
auto whole_name = plates_dir + "/" + std::to_string(t->channel_index) + "_" + std::to_string(t->frame_index) + "_" + color + "_" + text + "_whole.jpg";
// start flag
msg_stream << "<--" << std::endl;
// basic info
format_basic_info(meta->channel_index, meta->frame_index);
// save small cropped image
save_cropped_image(meta->frame, cv::Rect(t->x, t->y, t->width, t->height), cropped_name);
// save whole image
save_whole_image(meta->frame, whole_name);
// format color and text
format_plate(color, text);
// end flag
msg_stream << "-->";
if (i != meta->targets.size() - 1) {
msg_stream << std::endl; // not the last one
}
}
}
msg = msg_stream.str();
}
void vp_plate_socket_broker_node::broke_msg(const std::string& msg) {
// broke msg to socket by udp
auto bytes_2_send = reinterpret_cast<const std::byte*>(msg.c_str());
auto bytes_2_send_len = msg.size();
udp_writer.send(bytes_2_send, bytes_2_send_len);
}
}