diff --git a/src/ai_engine_module/RegionLeave.cpp b/src/ai_engine_module/RegionLeave.cpp new file mode 100644 index 0000000..c17d901 --- /dev/null +++ b/src/ai_engine_module/RegionLeave.cpp @@ -0,0 +1,250 @@ +#include "./RegionLeave.h" +#include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/opencv.hpp" +#include + +#include "../helpers/gen_json.hpp" +#include "../ai_platform/mvpt_process_assist.h" + + + +std::set algor_type_to_det_label_set(const algorithm_type_t &algor_type) { + if (algorithm_type_t::HUMAN_LEAVE_REGION == algor_type || algorithm_type_t::HUMAN_REGION_DISMISS == algor_type + || algorithm_type_t::HUMAN_REGION_FAST_MOVING == algor_type) { + return {det_class_label_t::HUMAN}; + } else if (algorithm_type_t::VEHICLE_LEAVE_REGION == algor_type) { + return { + det_class_label_t::LARGE_CAR, det_class_label_t::MEDIUM_BUS, det_class_label_t::SMALL_CAR, + det_class_label_t::TRUCK, det_class_label_t::TRACTOR, + }; + } else { + return {}; + } +} + +/* 是否是有效目标框的辅助判断函数 */ +bool check_obj_cls(const int &cls, const algorithm_type_t &algor_type) { + return algor_type_to_det_label_set(algor_type).count(static_cast(cls)); +} + +RegionLeave::RegionLeave(){ + m_task_param_manager = task_param_manager::getInstance(); +} + +RegionLeave::~RegionLeave() +{ + +} +void RegionLeave::init(int devId, algorithm_type_t eType){ + + m_devId = devId; + m_eType = eType; + + m_save_util = new save_snapshot_reprocessing(m_devId); +} + +#ifdef POST_USE_RABBITMQ +void RegionLeave::set_callback(callback_t cb) { + m_save_util->set_callback(cb); +} +#endif + +/* 根据用户输入的点 初始化禁区区域mask */ +bool RegionLeave::add_task(const string &task_id, const int width, const int height) { + + auto &¶ms_ptr = m_task_param_manager->get_task_other_param(task_id, m_eType); + if (!params_ptr) + { + LOG_ERROR("{} is nullptr when get algor param from task_param", task_id); + return false; + } + + if (params_ptr->algor_param == nullptr) + return false; + + auto *algor_params_ptr = (algor_config_param_trespass_basic *)(params_ptr->algor_param); + if (algor_params_ptr == nullptr) + { + return false; + } + + cv::Mat src(height, width, CV_8UC3); + src.setTo(0); + + std::vector contour; + for (int idx = 0; idx < algor_params_ptr->points_count; idx++) { + contour.emplace_back(algor_params_ptr->points[idx].x_, algor_params_ptr->points[idx].y_); + } + + if(contour.size() <= 0){ + return false; + } + + std::vector> contours; + contours.push_back(contour); + + cv::polylines(src, contours, true, cv::Scalar(255, 255, 255), 2, 8); // 第2个参数可以采用contour或者contours,均可 + cv::fillPoly(src, contours, cv::Scalar(255, 255, 255)); // fillPoly函数的第二个参数是二维数组 + + cv::Mat &dst_mat = region_map[task_id]; + cv::cvtColor(src, region_map[task_id], cv::COLOR_BGR2GRAY); + cv::threshold(region_map[task_id], region_map[task_id], 100, 255, cv::THRESH_BINARY); + + return true; +} + +/* 目标在禁区内外的辅助判断函数 */ +bool RegionLeave::in_rect_analysis(string task_id, const box_t &cur_bos) { + int center_x = int((cur_bos.left + cur_bos.right) / 2.0); + int center_y = int((cur_bos.top + cur_bos.bottom) / 2.0); + + cv::Mat &dst_mat = region_map[task_id]; + if (dst_mat.data[center_y * dst_mat.cols + center_x] && dst_mat.data[center_y * dst_mat.cols + center_x + 1] && + dst_mat.data[center_y * dst_mat.cols + center_x - 1] && dst_mat.data[(center_y + 1) * dst_mat.cols + center_x] && + dst_mat.data[(center_y - 1) * dst_mat.cols + center_x]) { + return true; // 进入禁区 + } else { + return false; // 未进入禁区 + } +} + +bool RegionLeave::is_valid_box(string task_id, const box_t &box, const algorithm_type_t &algor_type) { + auto &¶ms_ptr = m_task_param_manager->get_task_other_param(task_id, algor_type); + if (!params_ptr) + { + LOG_ERROR("{} is nullptr when get algor param from task_param", task_id); + return false; + } + + if (params_ptr->basic_param == nullptr) + return false; + + if (!snapshot_legal_inarea(params_ptr->basic_param->algor_valid_rect, box.left, box.top, box.right, box.bottom)) + return false; + + if (params_ptr->algor_param == nullptr) + return false; + + auto *algor_params_ptr = (algor_config_param_trespass_basic *)(params_ptr->algor_param); + + if (box.width() == 0 || box.height() == 0) + return false; + + if (box.score < algor_params_ptr->conf_threshold || box.width() < algor_params_ptr->minmum_width || + box.height() < algor_params_ptr->minmum_height) + return false; + + return check_obj_cls(box.cls, algor_type); +} + +/* 非法闯入禁区的 算法判断函数 */ +void RegionLeave::process(std::vector& vec_gpuMem, const std::vector &det_results, const vector> &delete_objs) +{ + if (det_results.size() <= 0) { + return ; + } + + for (int i = 0; i < det_results.size(); i++){ + DeviceMemory* gpuMem = vec_gpuMem[i]; + string task_id = gpuMem->getId(); + + // 删除 已经删除的目标 + for (auto obj_idx : delete_objs[i]) { + OBJ_KEY obj_key{task_id, obj_idx}; + + if (obj_to_position_.find(obj_key) != obj_to_position_.end()) { + obj_to_position_.erase(obj_key); + } + } + + auto it = region_map.find(task_id); + if (it == region_map.end()) { + continue; + } + + auto &¶ms_ptr = m_task_param_manager->get_task_other_param(task_id, m_eType); + if (!params_ptr && !params_ptr->basic_param) + { + LOG_ERROR("{} is nullptr when get algor param from task_param", task_id); + continue; + } + + bool b_src_saved = false; + + string sep = "/"; + + auto& basic_param = params_ptr->basic_param; + std::string cur_src_ts = std::to_string(helpers::timer::get_timestamp()); + std::string origin_file_path = basic_param->result_folder + sep + task_id + "_origin_" + cur_src_ts + ".jpg"; + + /* 依次判断检测目标框 是否有非法闯入 判断逻辑:之前帧在禁区外 当前帧进入禁区 */ + auto& one_result = det_results[i]; + std::vector boxes; + for (unsigned c = 0; c < one_result.obj_count; ++c) { + + auto obj_c = one_result.obj[c]; + + box_t unique_box; + unique_box.id = obj_c.id; + unique_box.cls = obj_c.index; + unique_box.top = obj_c.top; + unique_box.left = obj_c.left; + unique_box.right = obj_c.right; + unique_box.bottom = obj_c.bottom; + unique_box.score = obj_c.confidence; + + OBJ_KEY obj_key{task_id, obj_c.id}; + + if (!is_valid_box(task_id, unique_box, m_eType)){ + obj_to_position_.erase(obj_key); // 如果不满足条件 非 合法框 依然删除 + } + + //! add or update. + if (in_rect_analysis(task_id, unique_box)) { + // 禁区内 + // 新加 + obj_to_position_[obj_key] = unique_box; + } else { + if (obj_to_position_.find(obj_key) != obj_to_position_.end()) // 之前在禁区内,可报警 + { + box_t box; + box.left = obj_c.left; + box.right = obj_c.right; + box.top = obj_c.top; + box.bottom = obj_c.bottom; + box.score = obj_c.confidence; + boxes.push_back(box); + + // 报完警清除记录 + obj_to_position_.erase(obj_key); + } + } + } + + if (boxes.size() <= 0) + { + continue; + } + + int algorithm_type = (int)m_eType; + string json_str = helpers::gen_json::gen_boxes_json(task_id, algorithm_type, boxes, origin_file_path); + + ImgSaveInfo info_origin; + info_origin.img_info = VPCUtil::vpc_devMem2vpcImg(gpuMem); + info_origin.file_path = origin_file_path; + info_origin.json_str = json_str; + m_save_util->reprocessing_process_wo_locus_async(info_origin); + } +} + +void RegionLeave::release_task(string task_id){ + auto it = region_map.find(task_id); + if (it != region_map.end()) + { + region_map.erase(it); + } +} + + + diff --git a/src/ai_engine_module/RegionLeave.h b/src/ai_engine_module/RegionLeave.h new file mode 100644 index 0000000..bd5deca --- /dev/null +++ b/src/ai_engine_module/RegionLeave.h @@ -0,0 +1,51 @@ +#ifndef __REGION_LEAVE_H__ +#define __REGION_LEAVE_H__ + +#include +#include +#include + +#include "opencv2/highgui/highgui.hpp" + +#include "ai_engine_header.h" +#include "../ai_platform/task_param_manager.h" +#include "../decoder/interface/DeviceMemory.hpp" +#include "../reprocessing_module/save_snapshot_reprocessing.h" + + +class RegionLeave { +public: + RegionLeave(); + ~RegionLeave(); + + void init(int devId, algorithm_type_t eType); + + bool add_task(const string &task_id, const int width, const int height); + + void process(std::vector& vec_gpuMem, const std::vector &det_result, const vector> &delete_objs); + + void release_task(string task_id); + +#ifdef POST_USE_RABBITMQ + typedef std::function callback_t; + void set_callback(callback_t cb); +#endif + +private: + bool in_rect_analysis(string task_id, const box_t &cur_bos); + + bool is_valid_box(string task_id, const box_t &box, const algorithm_type_t &algor_type); + +private: + task_param_manager *m_task_param_manager{nullptr}; + std::map obj_to_position_; // 保存物体上一帧的位置,基于非法闯入判断逻辑,上一帧在框外,下一帧闯入禁区 + std::map region_map; + + int m_devId{0}; + algorithm_type_t m_eType; + + save_snapshot_reprocessing *m_save_util{nullptr}; +}; + + +#endif // __REGION_LEAVE_H__ \ No newline at end of file diff --git a/src/ai_engine_module/ai_engine_module.h b/src/ai_engine_module/ai_engine_module.h index bd35335..9490d70 100644 --- a/src/ai_engine_module/ai_engine_module.h +++ b/src/ai_engine_module/ai_engine_module.h @@ -13,4 +13,5 @@ #include "./traffic_light_process.h" #include "./road_seg_statistics.h" #include "./road_seg_3cls_statistics.h" -#include "./road_seg_correlation_algor.h" \ No newline at end of file +#include "./road_seg_correlation_algor.h" +#include "./RegionLeave.h" \ No newline at end of file diff --git a/src/ai_platform/MultiSourceProcess.cpp b/src/ai_platform/MultiSourceProcess.cpp index 3b6f358..eb36072 100755 --- a/src/ai_platform/MultiSourceProcess.cpp +++ b/src/ai_platform/MultiSourceProcess.cpp @@ -225,6 +225,10 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){ return -1; } + m_algorthim_region_leave.init(vptParam.gpuid, algorithm_type_t::HUMAN_LEAVE_REGION); + m_algorthim_region_dismiss.init(vptParam.gpuid, algorithm_type_t::HUMAN_REGION_DISMISS); + m_algorthim_region_fastmoving.init(vptParam.gpuid, algorithm_type_t::HUMAN_REGION_FAST_MOVING); + m_task_param_manager = task_param_manager::getInstance(); m_snapshot_reprocessing = new snapshot_reprocessing(m_devId); @@ -290,11 +294,23 @@ int CMultiSourceProcess::AddMqConn(mq_type_t mq_type, rabbitmq_conn_params_t mq_ LOG_INFO("为报警类 绑定MQ回调"); /* 为报警类 绑定回调 传入mq_manager_.publish 内部直接调用*/ - if (m_save_snapshot_reprocessing!= nullptr && mq_type_t::ALARM_MQ == mq_type) { - m_save_snapshot_reprocessing->set_callback( - std::bind(&mq::Manager::publish, mq_manager_, mq_type, std::placeholders::_1, true)); - LOG_INFO("为报警类 绑定MQ回调 成功!"); + if( mq_type_t::ALARM_MQ == mq_type){ + if (m_save_snapshot_reprocessing!= nullptr) { + m_save_snapshot_reprocessing->set_callback( + std::bind(&mq::Manager::publish, mq_manager_, mq_type, std::placeholders::_1, true)); + LOG_INFO("为报警类 绑定MQ回调 成功!"); + } + + m_algorthim_region_leave.set_callback( + std::bind(&mq::Manager::publish, mq_manager_, mq_type, std::placeholders::_1, true)); + + m_algorthim_region_dismiss.set_callback( + std::bind(&mq::Manager::publish, mq_manager_, mq_type, std::placeholders::_1, true)); + + m_algorthim_region_fastmoving.set_callback( + std::bind(&mq::Manager::publish, mq_manager_, mq_type, std::placeholders::_1, true)); } + LOG_INFO("初始化MQ队列成功!"); @@ -385,6 +401,9 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ // pDecManager->setDecKeyframe(config.name, true); // 只对关键帧解码 + int input_image_width = 0; + int input_image_height = 0; + pDecManager->getResolution(config.name, input_image_width, input_image_height); // 保存新添加任务的配置参数 m_task_param_manager->add_task_param(task_id, _cur_task_param); @@ -407,12 +426,17 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ if (m_task_param_manager->task_has_vpt_algor(task_id)) vpt_process.addTaskTracker(task_id, 1, 1, skip_frame_); - // 人脸跟踪 #ifdef WITH_FACE_DET_SS + // 人脸跟踪 if (m_task_param_manager->task_has_face_algor(task_id)) m_face_det_ai_engine.add_tracker(task_id, skip_frame_); // 跳帧数暂时写死 #endif + // 必须在 add_task_param 之后 todo 这里需要用参数过滤是否初始化 + m_algorthim_region_leave.add_task(task_id, input_image_width, input_image_height); + m_algorthim_region_dismiss.add_task(task_id, input_image_width, input_image_height); + m_algorthim_region_fastmoving.add_task(task_id, input_image_width, input_image_height); + m_FinishedTaskMtx.lock(); m_FinishedTaskMap[task_id] = false; m_FinishedTaskMtx.unlock(); @@ -664,6 +688,11 @@ bool CMultiSourceProcess::finish_task(const string taskID, const bool delete_sna // #ifdef WITH_SECOND_PROCESS pedestrian_vehicle_retrograde_.force_release_result(taskID); //221024 byzsh // #endif + + m_algorthim_region_leave.release_task(taskID); + m_algorthim_region_dismiss.release_task(taskID); + m_algorthim_region_fastmoving.release_task(taskID); + #ifdef USE_VILLAGE tricycle_manned_.force_release_result(taskID); truck_manned_.force_release_result(taskID); @@ -925,8 +954,10 @@ int CMultiSourceProcess::algorthim_vpt(vector vec_gpuMem){ algorthim_trespass(vpt_interest_task_id, vec_vptMem, vptResult, deleteObjectID); trespass_snapshot(vpt_interest_task_id, deleteObjectID); -// #endif -#ifdef USE_VILLAGE + m_algorthim_region_leave.process(vec_vptMem, vptResult, deleteObjectID); + m_algorthim_region_dismiss.process(vec_vptMem, vptResult, deleteObjectID); + m_algorthim_region_fastmoving.process(vec_vptMem, vptResult, deleteObjectID); + cross_line_process(vec_vptMem, vptResult, algorithm_type_t::HUMAN_CROSSING_LINE); cross_line_process(vec_vptMem, vptResult, algorithm_type_t::HUMAN_CLIMB); cross_line_process(vec_vptMem, vptResult, algorithm_type_t::VEHICLE_ILLEGAL_CROSSING_LINE); @@ -935,6 +966,9 @@ int CMultiSourceProcess::algorthim_vpt(vector vec_gpuMem){ wander_detect(vec_vptMem, vptResult, algorithm_type_t::VEHICLE_ILLEGAL_PARKING); // 轨迹记录 trace_record(vec_vptMem, vptResult); + +// #endif +#ifdef USE_VILLAGE // 农村违法分析的快照缓存 m_snapshot_reprocessing->update_village_bestsnapshot(vec_vptMem, vptResult, deleteObjectID); // 三轮车载人 diff --git a/src/ai_platform/MultiSourceProcess.h b/src/ai_platform/MultiSourceProcess.h index a12a64d..779a568 100755 --- a/src/ai_platform/MultiSourceProcess.h +++ b/src/ai_platform/MultiSourceProcess.h @@ -180,6 +180,10 @@ private: face_det_ai_engine m_face_det_ai_engine; // 人脸检测 + RegionLeave m_algorthim_region_leave; + RegionLeave m_algorthim_region_dismiss; + RegionLeave m_algorthim_region_fastmoving; + deque m_recoderinfo_queue; mutex m_recoderinfo_queue_mtx; thread* m_recode_thread {nullptr}; diff --git a/src/ai_platform/header.h b/src/ai_platform/header.h index aea9ff6..7868d8a 100755 --- a/src/ai_platform/header.h +++ b/src/ai_platform/header.h @@ -35,8 +35,11 @@ enum class algorithm_type_t { ROAD_WORK_DET = 212, // 221026byzsh施工占道 HUMAN_LINGER = 214, // 人员徘徊 + HUMAN_REGION_DISMISS = 216, // 人员逃散 + HUMAN_REGION_FAST_MOVING = 217, // 人员快速移动 HUMAN_CLIMB = 220, // 人员攀爬 HUMAN_CROSSING_LINE = 221, // 人员越线 + HUMAN_LEAVE_REGION = 222, // 区域离开 VEHICLE_SNAPSHOT = 301, VEHICLE_RETROGRADE = 310, @@ -44,6 +47,7 @@ enum class algorithm_type_t { VEHICLE_GATHER = 312, // 车辆聚集 VEHICLE_ILLEGAL_PARKING = 313, // 车辆违停 VEHICLE_ILLEGAL_CROSSING_LINE = 314, // 车辆压线 + VEHICLE_LEAVE_REGION = 315, // 区域离开 NONMOTOR_VEHICLE_SNAPSHOT = 401, TAKEAWAY_MEMBER_CLASSIFICATION = 402, diff --git a/src/ai_platform/mvpt_process_assist.h b/src/ai_platform/mvpt_process_assist.h index 27309d3..3b55722 100755 --- a/src/ai_platform/mvpt_process_assist.h +++ b/src/ai_platform/mvpt_process_assist.h @@ -25,17 +25,15 @@ using namespace std; int CreateDir(char *pszDir); void CreateResultFolder(char* resultFolder, const char* jointFolder); -//bool sy_legal_pos(bitset flags, int left, int top, int right, int bottom, int imgHeight, int imgWidth); + bool LegalArea(int maxArea, int lastArea, int left, int top, int right, int bottom); bool LegalMinArea(int width, int height, sy_rect min_box); -void ExpandMargin(int direction_x, int direction_y, int boundary_w, int boundary_h, - int &boundary_left, int &boundary_right, int &boundary_top, int &boundary_bottom); -void CreateResultFolder(char* resultFolder, const char* jointFolder); +void ExpandMargin(int direction_x, int direction_y, int boundary_w, int boundary_h, int &boundary_left, int &boundary_right, int &boundary_top, int &boundary_bottom); bool snapshot_legal_inarea(int width, int height); bool snapshot_legal_inarea(sy_rect algor_area, int left, int top, int right, int bottom); bool snapshot_legal_minarea(int index, int width, int height); -// bool snapshot_algor_open_config(const OBJ_KEY& obj_key); + bool snapshot_legal_pos(bitset flags, int left, int top, int right, int bottom, int image_width, int image_height); bool snapshot_legal_area(int max_area, int last_area, int left, int top, int right, int bottom); bool snapshot_legal_pose(float last_roll, float last_yaw, float last_pitch, float roll, float yaw, float pitch); // added by zsh 220719 判断人脸姿态角