From 8072fc32ce5a3bc0e500627e75212d9d0b962716 Mon Sep 17 00:00:00 2001 From: Hu Chunming <2657262686@qq.com> Date: Mon, 4 Aug 2025 20:57:24 +0800 Subject: [PATCH] 代码同步初步完成,人脸检测模型还不兼容 --- src/ai_engine_module/GatherDetect.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ai_engine_module/GatherDetect.h | 40 ++++++++++++++++++++++++++++++++++++++++ src/ai_engine_module/RegionLeave.cpp | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ai_engine_module/RegionLeave.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ai_engine_module/ai_engine_module.h | 8 ++++++++ src/ai_engine_module/face_det_ai_engine.cpp | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ai_engine_module/face_det_ai_engine.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ai_engine_module/face_detect.h | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ai_platform/MultiSourceProcess.cpp | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ai_platform/MultiSourceProcess.h | 6 ++++++ src/decoder/dvpp/VpcPicConverter.h | 20 -------------------- src/decoder/dvpp/VpcUtils.cpp | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/decoder/dvpp/VpcUtils.h | 23 +++++++++++++++++++++++ src/helpers/img_util.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/helpers/img_util.h | 15 +++++++++++++++ src/reprocessing_module/mq_manager.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/reprocessing_module/mq_manager.hpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/reprocessing_module/post_reprocessing.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/reprocessing_module/post_reprocessing.hpp | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/reprocessing_module/rbmq/RabbitmqClient.hpp | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/reprocessing_module/rbmq/RabbitmqClientImpl.cpp | 463 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/reprocessing_module/rbmq/RabbitmqClientImpl.hpp | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/reprocessing_module/rbmq/common.h | 30 ++++++++++++++++++++++++++++++ src/reprocessing_module/snapshot_reprocessing.cpp | 576 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- src/reprocessing_module/snapshot_reprocessing.h | 17 ++++++++++++++++- src/util/common_tool.cpp | 24 ++++++++++++++++++++++++ src/util/common_tool.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 27 files changed, 3033 insertions(+), 44 deletions(-) create mode 100644 src/ai_engine_module/GatherDetect.cpp create mode 100644 src/ai_engine_module/GatherDetect.h create mode 100644 src/ai_engine_module/RegionLeave.cpp create mode 100644 src/ai_engine_module/RegionLeave.h create mode 100644 src/ai_engine_module/ai_engine_module.h create mode 100755 src/ai_engine_module/face_det_ai_engine.cpp create mode 100755 src/ai_engine_module/face_det_ai_engine.h create mode 100755 src/ai_engine_module/face_detect.h delete mode 100644 src/decoder/dvpp/VpcPicConverter.h create mode 100644 src/decoder/dvpp/VpcUtils.cpp create mode 100644 src/decoder/dvpp/VpcUtils.h create mode 100644 src/helpers/img_util.cpp create mode 100644 src/helpers/img_util.h create mode 100755 src/reprocessing_module/mq_manager.cpp create mode 100755 src/reprocessing_module/mq_manager.hpp create mode 100755 src/reprocessing_module/post_reprocessing.cpp create mode 100755 src/reprocessing_module/post_reprocessing.hpp create mode 100755 src/reprocessing_module/rbmq/RabbitmqClient.hpp create mode 100755 src/reprocessing_module/rbmq/RabbitmqClientImpl.cpp create mode 100755 src/reprocessing_module/rbmq/RabbitmqClientImpl.hpp create mode 100755 src/reprocessing_module/rbmq/common.h create mode 100644 src/util/common_tool.cpp create mode 100644 src/util/common_tool.h diff --git a/src/ai_engine_module/GatherDetect.cpp b/src/ai_engine_module/GatherDetect.cpp new file mode 100644 index 0000000..5a92286 --- /dev/null +++ b/src/ai_engine_module/GatherDetect.cpp @@ -0,0 +1,94 @@ +/* + * @Author: yangzilong + * @Date: 2021-12-16 14:25:13 + * @Last Modified by: yangzilong + * @Email: yangzilong@objecteye.com + * @Description: + */ +#include "GatherDetect.h" +#include "../helpers/img_util.h" + +GatherDetect::GatherDetect() +{ + m_task_param_manager = task_param_manager::getInstance(); +} + +void GatherDetect::init(algorithm_type_t eType) +{ + m_eType = eType; +} + +std::vector GatherDetect::process(vector vec_vptMem, vector &ol_det_result) { + std::vector results; + + map && algor_config_param = m_task_param_manager->get_task_algor_params(); + map> && algor_param = m_task_param_manager->get_task_other_params(); + + for (size_t idx = 0; idx < vec_vptMem.size(); idx++) + { + DeviceMemory* cur_vptMem = vec_vptMem[idx]; + string task_id = cur_vptMem->getId(); + + auto it_algor = algor_param.find(task_id); + if (it_algor == algor_param.end()) { + continue; + } + + task_param_manager::algo_param_type_t_* cur_task_params = algor_param[task_id][m_eType]; + if (nullptr == cur_task_params) { + continue; + } + + algor_basic_config_param_t* basic_param = (algor_basic_config_param_t*)cur_task_params->basic_param; + if (basic_param == nullptr || basic_param->adapt_param == nullptr) { + continue; + } + universal_algor_adapt_param *adapt_param = basic_param->adapt_param; + + map> taskid_to_boxes; + + onelevel_det_result &cur_task_ol_detres = ol_det_result[idx]; + for (int c = 0; c < cur_task_ol_detres.obj_count; c++) + { + auto& obj_c = cur_task_ol_detres.obj[c]; + + bool bHuman = m_eType == algorithm_type_t::HUMAN_GATHER || m_eType == algorithm_type_t::HUMAN_DENSITY || m_eType == algorithm_type_t::HUMAN_REGION_GATHER; + + bool bCount = false; + if(bHuman && obj_c.index == (int)det_class_label_t::HUMAN) { + bCount = true; + } else if (m_eType == algorithm_type_t::VEHICLE_GATHER && obj_c.index >= 4 && obj_c.index <= 8) { + bCount = true; + } + + sy_point center; + center.x_ = (obj_c.right + obj_c.left)/ 2 ; + center.y_ = (obj_c.bottom + obj_c.top) / 2; + // vec_pt.push_back(center); + if (bCount && common::isInPolygon(adapt_param->points, adapt_param->points_count, center)) { + box_t box; + box.top = obj_c.top; + box.left = obj_c.left; + box.right = obj_c.right; + box.bottom = obj_c.bottom; + box.score = obj_c.confidence; + taskid_to_boxes[task_id].emplace_back(std::move(box)); + } + } + + int count_threshold = ((algor_config_param_human_gather*)cur_task_params->algor_param)->human_count_threshold; + int frame_stride = ((algor_config_param_human_gather*)cur_task_params->algor_param)->frame_stride; + + if (taskid_to_boxes[task_id].size() > count_threshold && cur_vptMem->getFrameNb() % frame_stride == 0) + { + GatherResult data; + data.origin_img = VPCUtil::vpc_devMem2vpcImg(vec_vptMem[idx]); + data.task_id = task_id; + data.boxes = std::move(taskid_to_boxes[task_id]); + data.id = gid_++; + results.emplace_back(std::move(data)); + } + } + + return results; +} \ No newline at end of file diff --git a/src/ai_engine_module/GatherDetect.h b/src/ai_engine_module/GatherDetect.h new file mode 100644 index 0000000..98ca4cb --- /dev/null +++ b/src/ai_engine_module/GatherDetect.h @@ -0,0 +1,40 @@ +/* + * @Author: yangzilong + * @Date: 2021-12-10 15:48:49 + * @Last Modified by: yangzilong + * @Last Modified time: Do not edit + * @Email: yangzilong@objecteye.com + * @Description: + */ +#pragma once + +#include +#include +#include +#include "../ai_platform/task_param_manager.h" +#include "./ai_engine_header.h" +#include "../decoder/interface/DeviceMemory.hpp" + +struct GatherResult +{ + long long id; + vpc_img_info origin_img; + std::vector boxes; + std::string task_id; +} ; + +class GatherDetect +{ +public: + GatherDetect(); + + void init(algorithm_type_t eType); + + std::vector process(vector vec_vptMem, vector &ol_det_result); + +private: + task_param_manager *m_task_param_manager{nullptr}; + long long gid_{0}; + + algorithm_type_t m_eType{algorithm_type_t::UNKNOWN}; +}; \ No newline at end of file diff --git a/src/ai_engine_module/RegionLeave.cpp b/src/ai_engine_module/RegionLeave.cpp new file mode 100644 index 0000000..9b34e41 --- /dev/null +++ b/src/ai_engine_module/RegionLeave.cpp @@ -0,0 +1,185 @@ +#include "./RegionLeave.h" +#include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/opencv.hpp" +#include + +#include "../helpers/gen_json.hpp" +#include "../helpers/img_util.h" + + +namespace ai_engine_module { + +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() +{ + if (m_save_util) + { + delete m_save_util; + m_save_util = nullptr; + } + +} +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 + +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 (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 &¶ms_ptr = m_task_param_manager->get_task_other_param(task_id, m_eType); + if (!params_ptr || !params_ptr->basic_param) + { + continue; + } + + auto& basic_param = params_ptr->basic_param; + if (basic_param == nullptr || basic_param->adapt_param == nullptr) { + continue; + } + universal_algor_adapt_param *adapt_param = basic_param->adapt_param; + + string sep = "/"; + + 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); // 如果不满足条件 非 合法框 依然删除 + } + + sy_point center; + center.x_ = (obj_c.right + obj_c.left)/ 2 ; + center.y_ = (obj_c.bottom + obj_c.top) / 2; + if (common::isInPolygon(adapt_param->points, adapt_param->points_count, center)) { + // 禁区内 + // 新加 + 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); + } +} + +} // namespace ai_engine_module \ No newline at end of file diff --git a/src/ai_engine_module/RegionLeave.h b/src/ai_engine_module/RegionLeave.h new file mode 100644 index 0000000..b8d3617 --- /dev/null +++ b/src/ai_engine_module/RegionLeave.h @@ -0,0 +1,49 @@ +#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" + + +namespace ai_engine_module { + +class RegionLeave { +public: + RegionLeave(); + ~RegionLeave(); + + void init(int devId, algorithm_type_t eType); + + void process(std::vector& vec_gpuMem, const std::vector &det_result, const vector> &delete_objs); + +#ifdef POST_USE_RABBITMQ + typedef std::function callback_t; + void set_callback(callback_t cb); +#endif + +private: + 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}; +}; + + +} // namespace ai_engine_module + +#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 new file mode 100644 index 0000000..9a3d962 --- /dev/null +++ b/src/ai_engine_module/ai_engine_module.h @@ -0,0 +1,8 @@ +#pragma once + +#include "./VPTProcess.h" +#include "./face_det_ai_engine.h" +#include "./pedestrian_vehicle_retrograde.h" +#include "./pedestrian_vehicle_trespass.h" +#include "./RegionLeave.h" +#include "./GatherDetect.h" \ No newline at end of file diff --git a/src/ai_engine_module/face_det_ai_engine.cpp b/src/ai_engine_module/face_det_ai_engine.cpp new file mode 100755 index 0000000..739ca20 --- /dev/null +++ b/src/ai_engine_module/face_det_ai_engine.cpp @@ -0,0 +1,258 @@ +#include "face_det_ai_engine.h" + +#include "../common/logger.hpp" +#include "../ai_platform/mvpt_process_assist.h" +#include "../ai_platform/macro_definition.h" + +#include "opencv2/opencv.hpp" +#include "face_detect.h" + +#include "../helpers/img_util.h" + +face_det_ai_engine::face_det_ai_engine(){ + m_max_batchsize = 10; +} + +face_det_ai_engine::~face_det_ai_engine(){ + fd_release(&handle); + clear(); + + if(m_algorthim_ctx){ + aclrtSetDevice(m_devId); + aclrtDestroyContext(m_algorthim_ctx); + } +} + +int face_det_ai_engine::init_ai_engine(const facedet_ai_engine_param &ai_param/*, person_det_algorthim_cache * cache*/){ + + task_param_manager_ = task_param_manager::getInstance(); + + m_devId = ai_param.sdk_param.devId; + + ACL_CALL(aclrtSetDevice(m_devId), ACL_ERROR_NONE, -1); + ACL_CALL(aclrtCreateContext(&m_algorthim_ctx, m_devId), ACL_ERROR_NONE, -1); + + return fd_init(&handle, ai_param.sdk_param); +} + +int face_det_ai_engine::ai_engine_process_batch(std::vector &task_ids, sy_img *image_data_array, std::vector &result , std::vector> &deleteObjectID){ + + map> && algor_param = task_param_manager_->get_task_other_params(); + + const int total_batchsize = task_ids.size(); + if (total_batchsize <= 0){ + return 0; + } + + aclrtSetDevice(m_devId); + int ret = aclrtSetCurrentContext(m_algorthim_ctx); + if(ACL_ERROR_NONE != ret){ + return 0; + } + + fd_result *fd_result_ = new fd_result[total_batchsize]; + for (int i = 0; i < total_batchsize; ++i) + fd_result_[i].info = new fd_info[50]; + + do{ + int stride = m_max_batchsize; + int steps = (total_batchsize + stride - 1) / stride; + + bool bError = false; + for (int c = 0; c < steps; ++c) { + int offset = c * m_max_batchsize; + const int batchsize = (c == steps - 1) ? (total_batchsize - offset) : stride; + + int ret = fd_detect_batch(handle, image_data_array + offset, SY_FORMAT_BGR888, batchsize, fd_result_ + offset); + if(ret < 0){ + LOG_ERROR(" fd_detect_batch error!!! image_size: {} model_batch_size: {}, step: [{}/{}] offset: {} batchsize: {}", total_batchsize, m_max_batchsize, c, steps, offset, batchsize); + bError = true; + break; + } + } + + if(bError){ + break; + } + + // 属性检测使用人脸检测的原图,不需要切图 + int cur_index = 0; + int img_index = 0; + + vector >> detectResult(total_batchsize); // sort + auto task_id_iter = task_ids.cbegin(); + for (int c = 0; c < total_batchsize; ++c) + { + string task_id = *task_id_iter; + task_id_iter++; + + task_param_manager::algo_param_type_t_* cur_task_params = algor_param[task_id][algorithm_type_t::FACE_SNAPSHOT]; + if (cur_task_params->basic_param == nullptr) { + continue; + } + + auto adapt_param = cur_task_params->basic_param->adapt_param; + if (adapt_param == nullptr){ + continue; + } + + for (int i = 0; i < fd_result_[c].count; ++i) + { + auto& obj_c = fd_result_[c].info[i]; + + sy_point center; + center.x_ = obj_c.face_position.left_ + obj_c.face_position.width_ / 2 ; + center.y_ = obj_c.face_position.top_ + obj_c.face_position.height_ / 2; + if (!common::isInPolygon(adapt_param->points, adapt_param->points_count, center) || obj_c.face_pos_score < ((algor_config_param_snapshot *)cur_task_params->algor_param)->threshold) { + continue; + } + + vector obj; + obj.push_back(fd_result_[c].info[i].face_position.left_); + obj.push_back(fd_result_[c].info[i].face_position.top_); + obj.push_back(fd_result_[c].info[i].face_position.left_ + fd_result_[c].info[i].face_position.width_); //right + obj.push_back(fd_result_[c].info[i].face_position.top_ + fd_result_[c].info[i].face_position.height_); //bottom + obj.push_back(fd_result_[c].info[i].score); + obj.push_back(1); //统一index值为1 + //存入关键点信息 + for(int j = 0; j < FACIALFEAPOINTSIZE; ++j) + { + obj.push_back(fd_result_[c].info[i].facial_fea_point[j].x_); + obj.push_back(fd_result_[c].info[i].facial_fea_point[j].y_); + } + + //-added by zsh 添加姿态角信息------------------------------ + obj.push_back(fd_result_[c].info[i].roll); + obj.push_back(fd_result_[c].info[i].yaw); + obj.push_back(fd_result_[c].info[i].pitch); + // cout << fabs(fd_result_[c].info[i].roll) << " " << fabs(fd_result_[c].info[i].yaw) << " " << fabs(fd_result_[c].info[i].pitch) << endl; + //-------------------------------------------------------- + detectResult[c].push_back(obj); + + #if 0 + if (fd_result_[img_index].count > 1) + { + //选择居中且靠上的人脸作为唯一的结果 + float min_dis = numeric_limits::max(); + int min_index = 0; + float person_center_x = (float)(cur_persondet_result[c]->obj[i].right - cur_persondet_result[c]->obj[i].left) / 2.0; + float person_center_y = (float)(cur_persondet_result[c]->obj[i].bottom - cur_persondet_result[c]->obj[i].top) / 6.0; + for (int j = 0; j < fd_result_[img_index].count; ++j) + { + float cx = (float)fd_result_[img_index].info[j].face_position.left_ + (float)(fd_result_[img_index].info[j].face_position.width_) / 2.0; + float cy = (float)fd_result_[img_index].info[j].face_position.top_ + (float)(fd_result_[img_index].info[j].face_position.height_) / 2.0; + float dis = (person_center_x - cx) * (person_center_x - cx) + (person_center_y - cy) * (person_center_y - cy); + if (dis < min_dis) + { + min_dis = dis; + min_index = j; + } + } + //姿态角控制 + if (fabs(fd_result_[img_index].info[min_index].roll) < pose_thresld[c] && fabs(fd_result_[img_index].info[min_index].yaw) < pose_thresld[c] && fabs(fd_result_[img_index].info[min_index].pitch) < pose_thresld[c]) + { + cur_res.count = 1; + cur_res.info = new fd_info[1]; + memcpy(&cur_res.info[0], &fd_result_[img_index].info[min_index], sizeof(fd_info)); + } + else + { + cur_res.info = new fd_info[1]; + cur_res.count = 0; + } + + } + else if (fd_result_[img_index].count == 1 && fabs(fd_result_[img_index].info[0].roll) < pose_thresld[c] && fabs(fd_result_[img_index].info[0].yaw) < pose_thresld[c] && fabs(fd_result_[img_index].info[0].pitch) < pose_thresld[c]) //姿态角控制 + { + cur_res.count = 1; + cur_res.info = new fd_info[1]; + memcpy(&cur_res.info[0], &fd_result_[img_index].info[0], sizeof(fd_info)); + } + else + { + cur_res.info = new fd_info[1]; + cur_res.count = 0; + } + _fd_result[vec_ids[c]].push_back(cur_res); + + for (int j = 0; j < cur_res.count; ++j) + { + ++cur_index; + } + #endif + + } + } + + //跟踪 + for (size_t real_index = 0; real_index < total_batchsize; real_index++) { + string task_id = task_ids[real_index]; + + bool isUseDet = true; + vector delete_ids; + const float maxLen = std::sqrt(image_data_array[real_index].w_ * image_data_array[real_index].w_ + image_data_array[real_index].h_ * image_data_array[real_index].h_); //-modified by zsh 220719 + for (int j = 0; j < task_trackers[task_id].fusion_interval; ++j) { + if (j == 0) { + int objCount = task_trackers[task_id].tracker.update_v2(isUseDet, /*save lk = */true, /*center_dist = */true, maxLen, detectResult[real_index], result[real_index].obj, deleteObjectID[real_index]); + result[real_index].obj_count = objCount; + vector>().swap(detectResult[real_index]); + detectResult[real_index].clear(); + isUseDet = false; + } else { + onelevel_det_result unresult; + unresult.obj_count = task_trackers[task_id].tracker.update_v2(isUseDet, true, true, maxLen, detectResult[real_index], unresult.obj, deleteObjectID[real_index]); + } + } + + ++real_index; + } + + vector >>().swap(detectResult); // free memory. + + ret = total_batchsize; + }while(0); + + if (fd_result_) { + for (int i = 0; i < total_batchsize; ++i) { + delete[] fd_result_[i].info; + fd_result_[i].info = nullptr; + } + delete[] fd_result_; + fd_result_ = nullptr; + } + + return ret; +} + +void face_det_ai_engine::clear() +{ + for (auto it = _fd_result.begin(); it != _fd_result.end();) + { + for (auto &fd : it->second) + { + delete[] fd.info; + fd.info = nullptr; + } + _fd_result.erase(it++); + } +} + +void face_det_ai_engine::add_tracker(std::string task_id, int fusion_interval){ + LOG_INFO("face: tracker add task {}", task_id.c_str()); + task_tracker t; + t.task_id = task_id; + t.tracker.FusionInterval = fusion_interval; // 221117byzsh + t.fusion_interval = fusion_interval; + task_trackers.insert(std::make_pair(task_id, t)); +} + + +void face_det_ai_engine::finish_task(std::string task_id) +{ + LOG_INFO("face: tracker finish task {}", task_id.c_str()); + auto iter = task_trackers.find(task_id); + if (iter != task_trackers.end()) + { + task_trackers.erase(task_id); + } +} \ No newline at end of file diff --git a/src/ai_engine_module/face_det_ai_engine.h b/src/ai_engine_module/face_det_ai_engine.h new file mode 100755 index 0000000..6f914b8 --- /dev/null +++ b/src/ai_engine_module/face_det_ai_engine.h @@ -0,0 +1,61 @@ +#ifndef _FACE_DET_AI_ENGINE_ +#define _FACE_DET_AI_ENGINE_ + +#include "face_detect.h" +#include "./sort/Sort.h" +#include "../ai_platform/task_param_manager.h" +#include "../ai_platform/det_obj_header.h" + +#include "acl/acl.h" +#include "acl/ops/acl_dvpp.h" + +using namespace std; + + +typedef struct facedet_ai_engine_param +{ + //int min_recg_frame_counts; + fd_param sdk_param; +} facedet_ai_engine_param; + +#ifndef _TASK_TRACKER_ +#define _TASK_TRACKER_ +struct task_tracker +{ + std::string task_id; + int fusion_interval;//跳帧数 + //tracker *trk;; + Sort tracker; +}; +#endif + +class face_det_ai_engine/*: public base_ai_engine*/ +{ +public: + face_det_ai_engine(); + ~face_det_ai_engine(); + + int init_ai_engine(const facedet_ai_engine_param &ai_param/*, person_det_algorthim_cache * cache*/); + int ai_engine_process_batch(std::vector &task_ids, sy_img *image_data_array, std::vector &result + , std::vector> &deleteObjectID); + void finish_task(std::string task_id); + void add_tracker(std::string task_id, int fusion_interval); + void clear(); + +private: + //int cur_batchsize; + //person_det_algorthim_cache * _cache; + void* handle; + int m_max_batchsize; + + int m_devId; + aclrtContext m_algorthim_ctx; + + std::map task_trackers; + //std::vector _cut_data_array; + std::map> _fd_result; + + task_param_manager *task_param_manager_; +}; + +#endif \ No newline at end of file diff --git a/src/ai_engine_module/face_detect.h b/src/ai_engine_module/face_detect.h new file mode 100755 index 0000000..cddb023 --- /dev/null +++ b/src/ai_engine_module/face_detect.h @@ -0,0 +1,159 @@ +/************************************************************ +* Version: face_detect_v1.4.1.20201221.x86_64.gpu +* CopyRight: 中科视语(北京)科技有限公司 +* UpdateDate: 20201221 +* Content: +************************************************************/ +#ifndef FACEDETECT_H_ +#define FACEDETECT_H_ + +#ifdef _MSC_VER +#ifdef FACEDETECT_EXPORTS +#define FACEDETECT_API __declspec(dllexport) +#else +#define FACEDETECT_API __declspec(dllimport) +#endif +#else +#define FACEDETECT_API __attribute__ ((visibility ("default"))) +#endif +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "sy_common.h" //通用数据结构体定义 + +// #define GPUIMG_PROCESS + +#ifndef FACIALFEAPOINTSIZE //关键点检测支持25个点 +#define FACIALFEAPOINTSIZE 25 +#endif + + +#ifndef __FD_INFO__ +#define __FD_INFO__ + typedef struct fd_info { + sy_rect face_position; //人脸位置 + float face_pos_score; //人脸框置信度 + sy_point facial_fea_point[FACIALFEAPOINTSIZE]; //人脸关键点位置信息 + int occlusion; //人脸遮挡度,范围值为0-100,越大表示人脸遮挡程度越高 + int clarity; //人脸清晰度,范围值为0-100,越大表示图像越清晰,人脸清晰度判别建议阈值为30 + int brightness; //人脸亮度,只有3种可能的值:[-1->太暗,0->正常,1->太亮],亮度结果会受亮度阈值参数brightness_min和brightness_max影响 + //int hat; //带帽子,范围为0-100,越大表示越可能有佩戴帽子,建议判别阈值为50 + //int glass; //带眼镜,范围为0-100,越大表示越可能有戴眼镜,建议判别阈值为70 + float roll; //姿态角 + float yaw; //姿态角 + float pitch; //姿态角 + float score; //人脸置信度 + } fd_info; +#endif + +#ifndef __FD_RESULT__ +#define __FD_RESULT__ + typedef struct fd_result { //结果结构体 + fd_info *info; //内存由外部申请 + int count; //人脸个数 + } fd_result; +#endif + +#ifndef __FD_PARAM__ +#define __FD_PARAM__ + typedef struct fd_param + { + sy_command facial_fea_point_config; //是否启动关键点检测 + sy_command pose_config; //是否启动姿态角 + sy_command quality_config; //是否启动质量检测 + sy_command score_config; //是否启动人脸置信度 + // int log; //日志 + // int mode; //运行模式(DEVICE_GPU / DEVICE_CPU) + int devId; //指定显卡id + float thresld; //检测阈值 建议0.7 + + int max_result_count; //检测结果目标数上限 + // int max_batch_size_detect; //检测批处理检测数量上限 + // int max_batch_size_ldmk; //关键点批处理检测数量上限 + // int max_batch_size_pose; //姿态角批处理检测数量上限 + // int max_batch_size_score; //置信度批处理检测数量上限 + // int max_batch_size_blurglass; //质量(模糊)批处理检测数量上限 + // //int max_batch_size_hat; //质量(帽子)批处理检测数量上限 + // int max_batch_size_occlusion; //质量(遮挡)批处理检测数量上限 + + char * auth_license; + char* det_modelNames; //人脸检测 + char* ldmk_modelNames; //人脸关键点 + char* pose_modelNames; //人脸姿态 + char* score_modelNames; //人脸置信度 + char* fuzzy_modelNames; //人脸质量_模糊 + char* occlusion_modelNames; //人脸质量_遮挡 + + fd_param() : facial_fea_point_config(SY_CONFIG_OPEN), pose_config(SY_CONFIG_OPEN), \ + quality_config(SY_CONFIG_OPEN), score_config(SY_CONFIG_OPEN), thresld(0.6), devId(0), max_result_count(20), auth_license("") {}; //默认功能全部启动 + }fd_param; +#endif + + /************************************************************************* + * function: fd_init + * purpose: init resources + * param: + [in] handle - handle + [in] param - init param + * return: success(0) or error code(<0) + * notes: null + *************************************************************************/ + FACEDETECT_API int fd_init(void ** handle, fd_param param); + + + /************************************************************************* + * function: fd_release + * purpose: release sources + * param: + [in] handle - handle + * return: null + * notes: null + *************************************************************************/ + FACEDETECT_API void fd_release(void ** handle); + + /************************************************************************* + * function: fd_get_version + * purpose: get sdk version + * param: null + * return: null + * notes: null + *************************************************************************/ + FACEDETECT_API const char * fd_get_version(); + + /************************************************************************* + * function: fd_detect_batch + * purpose: detect faces + * param: + [in] handle - handle + [in] img_data_array - data array + [in] format - data format + [in] batch_size - batch size + [in] result - face detect result + * return: success(0) or error code(<0) + * notes: null + *************************************************************************/ + //FACEDETECT_API int fd_detect_batch(void * handle, sy_img * img_data_array, sy_format format, int batch_size, fd_result *result); + + /************************************************************************* + * function: fd_detect + * purpose: detect faces + * param: + [in] handle - handle + [in] img_data_array - data array + [in] format - data format + [in] result - face detect result + * return: success(0) or error code(<0) + * notes: null + *************************************************************************/ + FACEDETECT_API int fd_detect(void * handle, sy_img img_data, sy_format format, fd_result *result); + + + FACEDETECT_API int fd_detect_batch(void * handle, sy_img * img_data_array, sy_format format, int batch_size, fd_result *result); +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/src/ai_platform/MultiSourceProcess.cpp b/src/ai_platform/MultiSourceProcess.cpp index 5fde7bf..ffd87a2 100644 --- a/src/ai_platform/MultiSourceProcess.cpp +++ b/src/ai_platform/MultiSourceProcess.cpp @@ -93,6 +93,8 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){ m_devId = vptParam.gpuid; + string models_dir = vptParam.models_dir; + VPTProcess_PARAM vparam; vparam.gpuid = m_devId; vparam.max_batch = m_batch_size; @@ -105,6 +107,42 @@ int CMultiSourceProcess::InitAlgorthim(tsl_aiplatform_param vptParam){ return ret; } +#ifdef WITH_FACE_DET_SS + // 人脸检测初始化 + facedet_ai_engine_param fd_param; + char model_path_yolov5s[100]; + strcpy(model_path_yolov5s, (models_dir + "/models/face_detect/face_det_yolov5s_310p.om").c_str()); + fd_param.sdk_param.det_modelNames = model_path_yolov5s; + char model_path_ldmk[100]; + strcpy(model_path_ldmk, (models_dir + "/models/face_detect/face_ldmk_310p.om").c_str()); + fd_param.sdk_param.ldmk_modelNames = model_path_ldmk; + char model_path_pose[100]; + strcpy(model_path_pose, (models_dir + "/models/face_detect/face_pose_310p.om").c_str()); + fd_param.sdk_param.pose_modelNames = model_path_pose; + char model_path_score[100]; + strcpy(model_path_score, (models_dir + "/models/face_detect/face_score_310p.om").c_str()); + fd_param.sdk_param.score_modelNames = model_path_score; + char model_path_fuzzy[100]; + strcpy(model_path_fuzzy, (models_dir + "/models/face_detect/face_fuzzy_310p.om").c_str()); + fd_param.sdk_param.fuzzy_modelNames = model_path_fuzzy; + char model_path_occlusion[100]; + strcpy(model_path_occlusion, (models_dir + "/models/face_detect/face_occlusion_310p.om").c_str()); + fd_param.sdk_param.occlusion_modelNames = model_path_occlusion; + fd_param.sdk_param.thresld = 0.6; + fd_param.sdk_param.devId = m_devId; + fd_param.sdk_param.auth_license = "sy_tongtu_aiplatform_sdk_2023"; + fd_param.sdk_param.facial_fea_point_config = SY_CONFIG_OPEN; //是否启动关键点检测 + fd_param.sdk_param.pose_config = SY_CONFIG_OPEN; //是否启动姿态角 + fd_param.sdk_param.quality_config = SY_CONFIG_OPEN; //是否启动质量检测 + fd_param.sdk_param.score_config = SY_CONFIG_OPEN; //是否启动人脸置信度 //SY_CONFIG_OPEN SY_CONFIG_CLOSE + fd_param.sdk_param.max_result_count = 50; + ret = m_face_det_ai_engine.init_ai_engine(fd_param); + if (ret < 0 ) { + LOG_FATAL("Init face detection failed"); + return ret; + } +#endif + 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); @@ -279,6 +317,12 @@ bool CMultiSourceProcess::AddTask(task_param _cur_task_param){ if (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 + m_FinishedTaskMtx.lock(); m_FinishedTaskMap[task_id] = false; m_FinishedTaskMtx.unlock(); @@ -449,6 +493,12 @@ bool CMultiSourceProcess::finish_task(const string taskID, const bool delete_sna if (!vpt_process.finishTaskTracker(taskID)) LOG_ERROR("Finish VPT Tracker failed, task_id: {}", taskID); +#ifdef WITH_FACE_DET_SS + // 人脸任务结束 + if (m_task_param_manager->task_has_face_algor(taskID)) + m_face_det_ai_engine.finish_task(taskID); +#endif + #ifdef POST_USE_RABBITMQ auto json_str = helpers::gen_json::gen_office_task_heart_beat_json({taskID}); mq_manager_->publish(mq_type_t::HEART_BEAT_MQ, json_str.c_str(), true); @@ -514,6 +564,10 @@ int CMultiSourceProcess::algorthim_process_thread(){ aclrtSetCurrentContext(ctx); algorthim_vpt(vec_gpuMem); +#ifdef WITH_FACE_DET_SS + algorthim_face_detect(vec_gpuMem); +#endif + for(int i=0;i < vec_gpuMem.size(); i++){ DeviceMemory* mem = vec_gpuMem[i]; if(mem->getSize() <= 0){ @@ -1085,6 +1139,64 @@ bool CMultiSourceProcess::save_snapshot_process(const OBJ_KEY &obj_key, const al return true; } +// 人脸检测抓拍算法模块 +void CMultiSourceProcess::algorthim_face_detect(vector vec_gpuMem) { + + vector interest_task_list; + vector interest_imgs; + vector vec_vptMem; + for (int i = 0; i < vec_gpuMem.size(); i++) { + DeviceMemory* mem = vec_gpuMem[i]; + if (!m_task_param_manager->task_has_face_algor(mem->getId())){ + continue; + } + + sy_img img; + img.w_ = mem->getWidth(); + img.h_ = mem->getHeight(); + img.c_ = mem->getChannel(); + img.data_ = mem->getMem(); + interest_imgs.push_back(img); + interest_task_list.push_back(mem->getId()); + vec_vptMem.push_back(mem); + } + + if (!interest_imgs.empty()) { + + unsigned image_size = interest_imgs.size(); + + // 人脸检测、跟踪 + std::vector facedet_result(image_size); + std::vector> face_deleteObjectID(image_size); + + int ret = m_face_det_ai_engine.ai_engine_process_batch(interest_task_list, interest_imgs.data(), facedet_result, face_deleteObjectID); + if(ret <= 0){ + LOG_ERROR("face detect error!!!"); + return; + } + + // 跟踪结果送入快照更新 + m_snapshot_reprocessing->update_face_bestsnapshot(vec_vptMem, facedet_result, face_deleteObjectID); + + // 保存已结束轨迹的目标 + auto task_iter_face = interest_task_list.begin(); //debug by zsh + for (int i = 0; i < face_deleteObjectID.size(); i++) { + for (int j = 0; j < face_deleteObjectID[i].size(); ++j) { + OBJ_KEY deleteObj = {*task_iter_face, face_deleteObjectID[i][j]}; + LOG_TRACE("{}: {}",*task_iter_face,face_deleteObjectID[i][j]); + face_locus_finished(deleteObj); + } + ++task_iter_face; + } + + for (int i = 0; i < face_deleteObjectID.size(); ++i){ + std::vector().swap(face_deleteObjectID[i]); + } + std::vector>().swap(face_deleteObjectID); + std::vector().swap(facedet_result); + } +} + void CMultiSourceProcess::cross_line_process(vector vec_gpuMem, vector& vptResult, algorithm_type_t eType) { map> && algor_param = m_task_param_manager->get_task_other_params(); @@ -1334,6 +1446,56 @@ int CMultiSourceProcess::gather_process(vector& vec_gpuMem, vecto return 0; } +void CMultiSourceProcess::face_locus_finished(const OBJ_KEY obj_key) { + map _total_face_snapshot_info = m_snapshot_reprocessing->get_total_face_snapshot_info(); + + auto it = _total_face_snapshot_info.find(obj_key); + if ( it == _total_face_snapshot_info.end()) { + return; + } + + LOG_DEBUG("face reprocessing {}:{}.", obj_key.video_id, obj_key.obj_id); + + auto task_other_params = m_task_param_manager->get_task_other_params(); + + const algor_basic_config_param_t *cur_param = + ((algor_init_config_param_t *)(task_other_params[obj_key.video_id][algorithm_type_t::FACE_SNAPSHOT]))->basic_param; + + OBJ_VALUE obj_value = it->second; + + std::string cur_time1 = std::to_string(helpers::timer::get_timestamp()); + + // 原图 + string fpath_src = std::string(cur_param->result_folder) + helpers::os::sep + obj_key.video_id + "_" + + std::to_string(obj_key.obj_id) + "_" + cur_time1 + ".jpg"; + + ImgSaveInfo origin_save_info; + origin_save_info.file_path = fpath_src; + origin_save_info.img_info = obj_value.snapShot; + origin_save_info.obj_rect = obj_value.obj_pos; + m_save_snapshot_reprocessing->reprocessing_process_wo_locus_async(origin_save_info); + + // 抠图 + string json_str = ""; + std::string cur_time2 = std::to_string(helpers::timer::get_timestamp()); + string fpath_snapShotLittle = std::string(cur_param->result_folder_little) + helpers::os::sep + obj_key.video_id + "_" + + std::to_string(obj_key.obj_id) + "_" + cur_time2 + ".jpg"; + +#ifdef POST_USE_RABBITMQ + json_str = helpers::gen_json::gen_face_detection_json( obj_key.video_id, obj_key.obj_id, fpath_snapShotLittle, fpath_src, + obj_value.position, obj_value.confidence, obj_value.landmark_point, 25); +#endif + + ImgSaveInfo roi_save_info; + roi_save_info.file_path = fpath_snapShotLittle; + roi_save_info.img_info = obj_value.snapShotLittle; + roi_save_info.json_str = json_str; + m_save_snapshot_reprocessing->reprocessing_process_wo_locus_async(roi_save_info); + + // 删除结束轨迹的数据 + m_snapshot_reprocessing->release_finished_face_locus_snapshot(obj_key.video_id, obj_key.obj_id, false); +} + int CMultiSourceProcess::CountRunningTask() { DecoderManager* pDecManager = DecoderManager::getInstance(); return pDecManager->count(); diff --git a/src/ai_platform/MultiSourceProcess.h b/src/ai_platform/MultiSourceProcess.h index e472b02..159323c 100644 --- a/src/ai_platform/MultiSourceProcess.h +++ b/src/ai_platform/MultiSourceProcess.h @@ -56,6 +56,8 @@ public: private: // 算法相关 int algorthim_vpt(vector vec_gpuMem); + // 人脸检测抓拍算法 + void algorthim_face_detect(vector vec_gpuMem); // 逆行 void algorthim_retrograde(vector& vpt_interest_task_id, vector vpt_interest_imgs, vector& vptResult); // 闯入 @@ -85,6 +87,8 @@ private: int gather_process(vector& vec_gpuMem, vector &ol_det_result, algorithm_type_t algor_type); + void face_locus_finished(const OBJ_KEY obj_key); + // 轨迹记录 void trace_record(vector& vec_gpuMem, vector& vptResult); @@ -136,4 +140,6 @@ private: GatherDetect m_human_region_gather; GatherDetect m_vehicle_gather; + face_det_ai_engine m_face_det_ai_engine; // 人脸检测 + }; \ No newline at end of file diff --git a/src/decoder/dvpp/VpcPicConverter.h b/src/decoder/dvpp/VpcPicConverter.h deleted file mode 100644 index 1973949..0000000 --- a/src/decoder/dvpp/VpcPicConverter.h +++ /dev/null @@ -1,20 +0,0 @@ -#include "dvpp_headers.h" -#include "depend_headers.h" -#include "DvppDataMemory.hpp" - - -class VpcPicConverter{ -public: - VpcPicConverter(); - ~VpcPicConverter(); - int init(aclrtContext context, string dec_name); - - DvppDataMemory* convert2bgr(acldvppPicDesc *input, int out_width, int out_height, bool key_frame); - -private: - aclrtContext context_; - aclrtStream stream_; - int m_devId; - acldvppChannelDesc *dvppChannelDesc_ ; - string m_dec_name; -}; \ No newline at end of file diff --git a/src/decoder/dvpp/VpcUtils.cpp b/src/decoder/dvpp/VpcUtils.cpp new file mode 100644 index 0000000..834cdc9 --- /dev/null +++ b/src/decoder/dvpp/VpcUtils.cpp @@ -0,0 +1,233 @@ +#include "VpcUtils.h" +#include "depend_headers.h" + +#define ALIGN_UP(val, align) (((val) % (align) == 0) ? (val) : (((val) / (align) + 1) * (align))) + +#define CHECK_AND_RETURN(ret, message) \ + if(ret != 0) {LOG_ERROR("{}", message); return ret;} +#define CHECK_NOT_RETURN(ret, message) \ + if(ret != 0) {LOG_ERROR("{}", message);} +#define CHECK_AND_RETURN_NOVALUE(ret, message) \ + if(ret != 0) {LOG_ERROR("{}", message); return;} +#define CHECK_AND_BREAK(ret, message) \ + if(ret != 0) {LOG_ERROR("{}", message); break;} + +VpcUtils::VpcUtils(){ + +} + +VpcUtils::~VpcUtils(){ + release(); +} + +int VpcUtils::init(int devId){ + + m_devId = devId; + + aclError ret = aclrtCreateContext(&context_, m_devId); + if (ret != ACL_ERROR_NONE) { + LOG_ERROR("[{}]-aclrtCreateContext failed !", m_dec_name); + return false; + } + + do + { + dvppChannelDesc_ = acldvppCreateChannelDesc(); + + ret = acldvppCreateChannel(dvppChannelDesc_); + CHECK_AND_BREAK(ret, "acldvppCreateChannel failed !"); + + ret = acldvppSetChannelDescMode(dvppChannelDesc_, DVPP_CHNMODE_VPC); + CHECK_AND_BREAK(ret, "acldvppSetChannelDescMode failed !"); + } while (0); + + return ret; +} + +void VpcUtils::release() { + + if(context_){ + aclrtSetCurrentContext(context_); + + if (dvppChannelDesc_) { + (void)acldvppDestroyChannel(dvppChannelDesc_); + (void)acldvppDestroyChannelDesc(dvppChannelDesc_); + dvppChannelDesc_ = nullptr; + } + + aclrtDestroyContext(context_); + } +} + +DvppDataMemory* VpcUtils::convert2bgr(acldvppPicDesc *inputDesc_, int out_width, int out_height, bool key_frame){ + + aclrtSetCurrentContext(context_); + + int out_buf_width = ALIGN_UP(out_width, 16) * 3; + int out_buf_height = ALIGN_UP(out_height, 2); + int out_buf_size = out_buf_width * out_buf_height; + + DvppDataMemory* rgbMem = new DvppDataMemory(3, out_buf_width, out_buf_width, out_buf_height, out_buf_height, out_buf_size, "", to_string(m_devId), key_frame, 0); + void *outBufferDev_ = (void*)rgbMem->getMem(); + + acldvppPicDesc *outputDesc_= acldvppCreatePicDesc(); + acldvppSetPicDescData(outputDesc_, outBufferDev_); + acldvppSetPicDescFormat(outputDesc_, PIXEL_FORMAT_BGR_888); + acldvppSetPicDescWidth(outputDesc_, out_width); + acldvppSetPicDescHeight(outputDesc_, out_height); + acldvppSetPicDescWidthStride(outputDesc_, out_buf_width); + acldvppSetPicDescHeightStride(outputDesc_, out_buf_height); + acldvppSetPicDescSize(outputDesc_, out_buf_size); + + aclError ret = ACL_ERROR_NONE; + aclrtStream stream_{nullptr}; + aclrtCreateStream(&stream_); + do{ + // 9. 执行异步色域转换,再调用aclrtSynchronizeStream接口阻塞程序运行,直到指定Stream中的所有任务都完成 + ret = acldvppVpcConvertColorAsync(dvppChannelDesc_, inputDesc_, outputDesc_, stream_); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("acldvppVpcConvertColorAsync failed - out_width:{} out_height:{} out_buf_width:{} out_buf_height:{} out_buf_size:{}", out_width, out_height, out_buf_width, out_buf_height, out_buf_size); + break; + } + ret = aclrtSynchronizeStream(stream_); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("aclrtSynchronizeStream failed - out_width:{} out_height:{} out_buf_width:{} out_buf_height:{} out_buf_size:{}", out_width, out_height, out_buf_width, out_buf_height, out_buf_size); + break; + } + }while(0); + + if(nullptr != stream_){ + aclrtDestroyStream(stream_); + stream_ = nullptr; + } + + acldvppDestroyPicDesc(outputDesc_); + + if(ret != ACL_ERROR_NONE){ + delete rgbMem; + rgbMem = nullptr; + } + + return rgbMem; +} + +DvppDataMemory* VpcUtils::convert2bgr(DvppDataMemory* inMem){ + + aclrtSetCurrentContext(context_); + + int out_width = inMem->getWidth(); + int out_height = inMem->getHeight(); + + + acldvppPicDesc *inputDesc_= acldvppCreatePicDesc(); + acldvppSetPicDescData(inputDesc_, inMem->getMem()); + acldvppSetPicDescFormat(inputDesc_, PIXEL_FORMAT_YUV_SEMIPLANAR_420); + acldvppSetPicDescWidth(inputDesc_, out_width); + acldvppSetPicDescHeight(inputDesc_, out_height); + acldvppSetPicDescWidthStride(inputDesc_, inMem->getWidthStride()); + acldvppSetPicDescHeightStride(inputDesc_, inMem->getHeightStride()); + acldvppSetPicDescSize(inputDesc_, inMem->getSize()); + + int out_buf_width = ALIGN_UP(out_width, 16) * 3; + int out_buf_height = ALIGN_UP(out_height, 2); + int out_buf_size = out_buf_width * out_buf_height; + + DvppDataMemory* rgbMem = new DvppDataMemory(3, out_buf_width, out_buf_width, out_buf_height, out_buf_height, out_buf_size, inMem->getId(), inMem->getDeviceId(), false, inMem->getFrameNb()); + void *outBufferDev_ = (void*)rgbMem->getMem(); + + acldvppPicDesc *outputDesc_= acldvppCreatePicDesc(); + acldvppSetPicDescData(outputDesc_, outBufferDev_); + acldvppSetPicDescFormat(outputDesc_, PIXEL_FORMAT_BGR_888); + acldvppSetPicDescWidth(outputDesc_, out_width); + acldvppSetPicDescHeight(outputDesc_, out_height); + acldvppSetPicDescWidthStride(outputDesc_, out_buf_width); + acldvppSetPicDescHeightStride(outputDesc_, out_buf_height); + acldvppSetPicDescSize(outputDesc_, out_buf_size); + + aclError ret = ACL_ERROR_NONE; + aclrtStream stream_{nullptr}; + aclrtCreateStream(&stream_); + do{ + // 9. 执行异步色域转换,再调用aclrtSynchronizeStream接口阻塞程序运行,直到指定Stream中的所有任务都完成 + ret = acldvppVpcConvertColorAsync(dvppChannelDesc_, inputDesc_, outputDesc_, stream_); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("acldvppVpcConvertColorAsync failed - out_width:{} out_height:{} out_buf_width:{} out_buf_height:{} out_buf_size:{}", out_width, out_height, out_buf_width, out_buf_height, out_buf_size); + break; + } + ret = aclrtSynchronizeStream(stream_); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("aclrtSynchronizeStream failed - out_width:{} out_height:{} out_buf_width:{} out_buf_height:{} out_buf_size:{}", out_width, out_height, out_buf_width, out_buf_height, out_buf_size); + break; + } + }while(0); + + if(nullptr != stream_){ + aclrtDestroyStream(stream_); + stream_ = nullptr; + } + + acldvppDestroyPicDesc(outputDesc_); + acldvppDestroyPicDesc(inputDesc_); + + if(ret != ACL_ERROR_NONE){ + delete rgbMem; + rgbMem = nullptr; + } + + return rgbMem; +} + +DvppDataMemory* VpcUtils::resize(acldvppPicDesc *inputDesc_, int out_width, int out_height){ + + aclrtSetCurrentContext(context_); + + int out_buf_width = ALIGN_UP(out_width, 16); + int out_buf_height = ALIGN_UP(out_height, 2); + int out_buf_size = out_buf_width * out_buf_height * 3 / 2; + + DvppDataMemory* rgbMem = new DvppDataMemory(1, out_width, out_buf_width, out_height, out_buf_height, out_buf_size, "", "", false, 0); + void *outBufferDev_ = (void*)rgbMem->getMem(); + + acldvppPicDesc *outputDesc_= acldvppCreatePicDesc(); + acldvppSetPicDescData(outputDesc_, outBufferDev_); + acldvppSetPicDescFormat(outputDesc_, acldvppGetPicDescFormat(inputDesc_)); + acldvppSetPicDescWidth(outputDesc_, out_width); + acldvppSetPicDescHeight(outputDesc_, out_height); + acldvppSetPicDescWidthStride(outputDesc_, out_buf_width); + acldvppSetPicDescHeightStride(outputDesc_, out_buf_height); + acldvppSetPicDescSize(outputDesc_, out_buf_size); + + acldvppResizeConfig *resizeConfig_ = acldvppCreateResizeConfig(); + + aclError ret = ACL_ERROR_NONE; + aclrtStream stream_{nullptr}; + aclrtCreateStream(&stream_); + do{ + // 9. 执行异步色域转换,再调用aclrtSynchronizeStream接口阻塞程序运行,直到指定Stream中的所有任务都完成 + ret = acldvppVpcResizeAsync(dvppChannelDesc_, inputDesc_, outputDesc_, resizeConfig_, stream_); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("acldvppVpcResizeAsync failed - out_width:{} out_height:{} out_buf_width:{} out_buf_height:{} out_buf_size:{}", out_width, out_height, out_buf_width, out_buf_height, out_buf_size); + break; + } + ret = aclrtSynchronizeStream(stream_); + if(ret != ACL_ERROR_NONE){ + LOG_ERROR("aclrtSynchronizeStream failed - out_width:{} out_height:{} out_buf_width:{} out_buf_height:{} out_buf_size:{}", out_width, out_height, out_buf_width, out_buf_height, out_buf_size); + break; + } + }while(0); + + if(nullptr != stream_){ + aclrtDestroyStream(stream_); + stream_ = nullptr; + } + + acldvppDestroyResizeConfig(resizeConfig_); + acldvppDestroyPicDesc(outputDesc_); + + if(ret != ACL_ERROR_NONE){ + delete rgbMem; + rgbMem = nullptr; + } + + return rgbMem; +} \ No newline at end of file diff --git a/src/decoder/dvpp/VpcUtils.h b/src/decoder/dvpp/VpcUtils.h new file mode 100644 index 0000000..e7a2e78 --- /dev/null +++ b/src/decoder/dvpp/VpcUtils.h @@ -0,0 +1,23 @@ +#include "dvpp_headers.h" +#include "depend_headers.h" +#include "DvppDataMemory.hpp" + + +class VpcUtils{ +public: + VpcUtils(); + ~VpcUtils(); + int init(int); + + DvppDataMemory* convert2bgr(acldvppPicDesc *input, int out_width, int out_height, bool key_frame); + DvppDataMemory* convert2bgr(DvppDataMemory* inMem); + + DvppDataMemory* resize(acldvppPicDesc *inputDesc_, int out_width, int out_height); +private: + void release(); +private: + aclrtContext context_{nullptr}; + int m_devId; + acldvppChannelDesc *dvppChannelDesc_ {nullptr}; + string m_dec_name; +}; \ No newline at end of file diff --git a/src/helpers/img_util.cpp b/src/helpers/img_util.cpp new file mode 100644 index 0000000..c3be8f6 --- /dev/null +++ b/src/helpers/img_util.cpp @@ -0,0 +1,56 @@ +#include "img_util.h" +#include "opencv2/opencv.hpp" + +namespace common { + +bool isInPolygon(const sy_point* point_array, int point_count, const sy_point& center) { + + std::vector polygon; + for (size_t i = 0; i < point_count; i++) + { + polygon.push_back(cv::Point(point_array[i].x_, point_array[i].y_)); + } + + if (polygon.size() <= 0) + { + return false; + } + + // 定义一个点 + cv::Point pt(center.x_, center.y_); + + // 使用pointPolygonTest函数判断点是否在多边形内 + double sign = cv::pointPolygonTest(polygon, pt, false); + if (sign > 0) + { + return true; + } + + return false; +} + +void save_result(int height, int width, sy_point* point_array, int point_count, std::vector vec_pt) { + cv::Mat image = cv::Mat::zeros(height, width, CV_8UC3); + + // 定义一个多边形的顶点数组(例如一个五边形) + std::vector polyPoints; + for (size_t i = 0; i < point_count; i++) + { + polyPoints.push_back(cv::Point(point_array[i].x_, point_array[i].y_)); + } + + // 绘制多边形边界,颜色为绿色,线宽 2 + const cv::Point* pts = &polyPoints[0]; + int npts = (int)polyPoints.size(); + cv::polylines(image, &pts, &npts, 1, true, cv::Scalar(0, 255, 0), 2); + + for (size_t i = 0; i < vec_pt.size(); i++) + { + cv::circle(image, cv::Point(vec_pt[i].x_, vec_pt[i].y_), 2, cv::Scalar(0, 255, 255), -1); + } + + cv::imwrite("gahter.jpg", image); + +} + +} \ No newline at end of file diff --git a/src/helpers/img_util.h b/src/helpers/img_util.h new file mode 100644 index 0000000..a84aa1c --- /dev/null +++ b/src/helpers/img_util.h @@ -0,0 +1,15 @@ +#ifndef __HELPERS_IMG_TUIL_H__ +#define __HELPERS_IMG_TUIL_H__ + + +#include "../common/sy_common.h" +#include + +namespace common { + +bool isInPolygon(const sy_point* point_array, int point_count, const sy_point& center); + +void save_result(int height, int width, sy_point* point_array, int point_count, std::vector vec_pt); +} + +#endif \ No newline at end of file diff --git a/src/reprocessing_module/mq_manager.cpp b/src/reprocessing_module/mq_manager.cpp new file mode 100755 index 0000000..1281735 --- /dev/null +++ b/src/reprocessing_module/mq_manager.cpp @@ -0,0 +1,60 @@ +/* + * @Author: yangzilong + * @Date: 2021-12-15 15:00:28 + * @Last Modified by: yangzilong + * @Email: yangzilong@objecteye.com + * @Description: + */ + +#include "./mq_manager.hpp" +#include "../common/logger.hpp" + + +#ifdef POST_USE_RABBITMQ + +namespace mq +{ + + Manager::Manager() + { + + }; + + bool Manager::add_conn(const key_t &key, const value_param_t& value_param) + { + if (task_status_to_mq_handle_.find(key) != task_status_to_mq_handle_.end()) + return false; + std::shared_ptr value = std::make_shared(); + if (!value->init(value_param)) + return false; + + task_status_to_mq_handle_[key] = value; + return true; + } + + bool Manager::del_conn(const key_t &key) + { + if (task_status_to_mq_handle_.find(key) == task_status_to_mq_handle_.end()) + return false; + task_status_to_mq_handle_.erase(key); + return true; + } + + bool Manager::publish(const key_t &key, const char *msg, bool verbose) + { + if (task_status_to_mq_handle_.find(key) == task_status_to_mq_handle_.end()) + return false; + + bool status; + if (!(status = task_status_to_mq_handle_[key]->sync_publish(msg))) + LOG_ERROR("rbMQ publish failed:{}", msg); + else + if (verbose) + LOG_DEBUG("rbMQ publish successful:{}", msg); + return status; + } + +} + + +#endif // #ifdef POST_USE_RABBITMQ \ No newline at end of file diff --git a/src/reprocessing_module/mq_manager.hpp b/src/reprocessing_module/mq_manager.hpp new file mode 100755 index 0000000..64ffe8f --- /dev/null +++ b/src/reprocessing_module/mq_manager.hpp @@ -0,0 +1,49 @@ +/* + * @Author: yangzilong + * @Date: 2021-12-15 14:52:35 + * @Last Modified by: yangzilong + * @Email: yangzilong@objecteye.com + * @Description: + */ + +#pragma once + +#include "./post_reprocessing.hpp" +#include +#include + +#ifdef POST_USE_RABBITMQ + +namespace mq +{ + typedef mq_type_t key_t; + typedef post_rabbitmq_reprocessing value_t; + typedef rabbitmq_conn_params_t value_param_t; + + class Manager + { + /** + * @brief is not thread safe. + * + */ + public: + + Manager(); + + bool add_conn(const key_t &key, const value_param_t& value_param); + + bool del_conn(const key_t &key); + + bool publish(const key_t &key, const char *msg, bool verbose = false); + + /* remove copy construct and copy assignment. */ + Manager(const Manager &) = delete; + Manager& operator=(const Manager &) = delete; + + private: + std::map> task_status_to_mq_handle_; + + }; +} // namespace mq + +#endif // #ifdef POST_USE_RABBITMQ diff --git a/src/reprocessing_module/post_reprocessing.cpp b/src/reprocessing_module/post_reprocessing.cpp new file mode 100755 index 0000000..ceddc97 --- /dev/null +++ b/src/reprocessing_module/post_reprocessing.cpp @@ -0,0 +1,134 @@ +#include "post_reprocessing.hpp" +#include "../common/logger.hpp" + +#ifdef POST_USE_RABBITMQ + + +namespace mq +{ + + post_rabbitmq_reprocessing::post_rabbitmq_reprocessing() + : rabbitmq_handle_(nullptr) + { +#ifdef _RBMQ_ASYNC_INTERFACE + is_run_.store(true); + run_thread_ = std::thread(std::bind(&post_rabbitmq_reprocessing::run, this)); +#endif + } + + post_rabbitmq_reprocessing::~post_rabbitmq_reprocessing() + { +#ifdef _RBMQ_ASYNC_INTERFACE + is_run_.store(false); + + if (run_thread_.joinable()) + run_thread_.join(); +#endif + if (rabbitmq_handle_ != nullptr) + rabbitmq_handle_->Disconnect(); + } + + post_rabbitmq_reprocessing::post_rabbitmq_reprocessing(post_rabbitmq_reprocessing &&other) + : params_(std::move(other.params_)) + , rabbitmq_handle_(std::move(other.rabbitmq_handle_)) + { + + } + + post_rabbitmq_reprocessing& post_rabbitmq_reprocessing::operator=(post_rabbitmq_reprocessing &&other) + { + if (this == &other) + return *this; + + this->params_ = std::move(other.params_); + this->rabbitmq_handle_ = std::move(other.rabbitmq_handle_); + return *this; + } + + bool post_rabbitmq_reprocessing::init(const rabbitmq_conn_params_t ¶ms) + { + rabbitmq_handle_.reset(CRabbitmqClient::get_instance()); + /* connection rabbitMQ. */ + { + int ret = -1; + if (0 != (ret = rabbitmq_handle_->Connect(params.ip, params.port, params.uname, params.passwd, params.vhost))) + { + LOG_ERROR("RabbitMQ Connection {}:{} failed error code is {}!!!", params.ip, params.port, ret); + return false; + } + + if (0 != (ret = rabbitmq_handle_->ExchangeDeclare(params.exchange, params.exchange_type, params.durable_exchange))) + { + LOG_ERROR("RabbitMQ Declare Exchange {} failed error code is {}!!!", params.exchange, ret); + return false; + } + + if (0 != (ret = rabbitmq_handle_->QueueDeclare(params.queue, params.durable_queue))) + { + LOG_ERROR("RabbitMQ Declare Queue {} failed error code is {}!!!", params.queue, ret); + return false; + } + + if (0 != (ret = rabbitmq_handle_->QueueBind(params.queue, params.exchange, params.routing_key))) + { + LOG_ERROR("RabbitMQ Queue Bind failed queue is {} exchange is {} route key is {} error code is {}!!!", params.queue, params.exchange, params.routing_key, ret); + return false; + } + } + + { + params_ = params; + } + + return true; + } + + bool post_rabbitmq_reprocessing::sync_publish(const std::string &msg) + { + if (nullptr == rabbitmq_handle_) + { + LOG_ERROR("call Init before please !!!"); + return false; + } + std::lock_guard lk(run_mutex_); + return rabbitmq_handle_->Publish(msg, params_.exchange, params_.routing_key) == 0; + } + +#ifdef _RBMQ_ASYNC_INTERFACE + bool post_rabbitmq_reprocessing::async_publish(const std::string &msg) + { + if (nullptr == rabbitmq_handle_) + { + LOG_ERROR("call Init before please !!!"); + return false; + } + std::lock_guard lk(run_mutex_); + message_buffer_.push(msg); + run_cv_.notify_one(); + return true; + } + + + void post_rabbitmq_reprocessing::run() + { + while (is_run_.load()) + { + std::unique_lock lk(run_mutex_); + run_cv_.wait(lk, + [this] { return !this->message_buffer_.empty(); }); + std::string msg = message_buffer_.front(); + message_buffer_.pop(); + + if (rabbitmq_handle_->Publish(msg, params_.exchange, params_.routing_key) != 0) + LOG_ERROR("Publish {} failed!", msg); + else + LOG_INFO("Publish {} successful!", msg); + } + } +#endif + +} + +#endif // #ifdef POST_USE_RABBITMQ + + diff --git a/src/reprocessing_module/post_reprocessing.hpp b/src/reprocessing_module/post_reprocessing.hpp new file mode 100755 index 0000000..5dc3bd5 --- /dev/null +++ b/src/reprocessing_module/post_reprocessing.hpp @@ -0,0 +1,75 @@ +/* + * @Author: yangzilong + * @Last Modified by: yangzilong + * @Date: 2021-11-24 19:05:28 + * @Email: yangzilong@objecteye.com + * @Description: + */ +#pragma once + +#include "../ai_platform/header.h" + +#ifdef POST_USE_RABBITMQ + +#include "json/json.h" +#include + +#include +#include + +#ifdef _RBMQ_ASYNC_INTERFACE +#include +#include +#include +#include +#endif + +#include "spdlog/spdlog.h" +#include "./rbmq/RabbitmqClient.hpp" + +namespace mq +{ + + class post_rabbitmq_reprocessing + { + /** + * @brief + * 1. move able only. + * 2. thread safe class. + * 3. support async api. + * */ + public: + post_rabbitmq_reprocessing(); + ~post_rabbitmq_reprocessing(); + + bool init(const rabbitmq_conn_params_t ¶ms); + bool sync_publish(const std::string &msg); +#ifdef _RBMQ_ASYNC_INTERFACE + bool async_publish(const std::string &msg); +#endif + + post_rabbitmq_reprocessing(post_rabbitmq_reprocessing &&other); + post_rabbitmq_reprocessing& operator=(post_rabbitmq_reprocessing &&other); + + /* remove copy construct and copy assignment. */ + post_rabbitmq_reprocessing(const post_rabbitmq_reprocessing &) = delete; + post_rabbitmq_reprocessing& operator=(const post_rabbitmq_reprocessing &) = delete; + + private: +#ifdef _RBMQ_ASYNC_INTERFACE + void run(); + std::thread run_thread_; + std::atomic_bool is_run_; + std::condition_variable run_cv_; + std::queue message_buffer_; +#endif + std::mutex run_mutex_; + rabbitmq_conn_params_t params_; + std::shared_ptr rabbitmq_handle_; + }; + +} +#endif // #ifdef POST_USE_RABBITMQ + + + diff --git a/src/reprocessing_module/rbmq/RabbitmqClient.hpp b/src/reprocessing_module/rbmq/RabbitmqClient.hpp new file mode 100755 index 0000000..791e1d8 --- /dev/null +++ b/src/reprocessing_module/rbmq/RabbitmqClient.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include + +typedef void (*RABBITMQ_CALLBACK)(void* contex, const char * msg); + +class CRabbitmqClient +{ +/** + * @brief not single instance; + * + */ +public: + static CRabbitmqClient* get_instance(); + static void destory(CRabbitmqClient *instance); + + + virtual int Connect(const std::string &strHostname, int iPort, const std::string &strUser, const std::string &strPasswd, const std::string &vhost = "/") = 0; + + /** + * @brief Disconnect 关闭连接 + * + * @return int 等于0值成功, 小于0代表错误 + */ + virtual int Disconnect() = 0; + + /** + * @brief ExchangeDeclare 声明exchange + * @param [in] strExchange + * @param [in] strType + * @return 等于0值代表成功创建exchange,小于0代表错误 + */ + virtual int ExchangeDeclare(const std::string &strExchange, const std::string &strType, const bool durable = false) = 0; + + /** + * @brief QueueDeclare 声明消息队列 + * @param [in] strQueueName 消息队列实例 + * @param + * @return 等于0值代表成功创建queue,小于0代表错误 + */ + virtual int QueueDeclare(const std::string &strQueueName, const bool durable = false) = 0; + + /** + * @brief QueueBind 将队列,交换机和绑定规则绑定起来形成一个路由表 + * @param [in] strQueueName 消息队列 + * @param [in] strExchange 交换机名称 + * @param [in] strBindKey 路由名称 “msg.#” “msg.weather.**” + * @return 等于0值代表成功绑定,小于0代表错误 + */ + virtual int QueueBind(const std::string &strQueueName, const std::string &strExchange, const std::string &strBindKey) = 0; + + /** + * @brief QueueUnbind 将队列,交换机和绑定规则绑定解除 + * @param [in] strQueueName 消息队列 + * @param [in] strExchange 交换机名称 + * @param [in] strBindKey 路由名称 “msg.#” “msg.weather.**” + * @return 等于0值代表成功绑定,小于0代表错误 + */ + virtual int QueueUnbind(const std::string &strQueueName, const std::string &strExchange, const std::string &strBindKey) = 0; + + /** + * @brief QueueDelete 删除消息队列。 + * @param [in] strQueueName 消息队列名称 + * @param [in] iIfUnused 消息队列是否在用,1 则论是否在用都删除 + * @return 等于0值代表成功删除queue,小于0代表错误 + */ + virtual int QueueDelete(const std::string &strQueueName, int iIfUnused) = 0; + + /** + * @brief Publish 发布消息 + * @param [in] strMessage 消息实体 + * @param [in] strExchange 交换器 + * @param [in] strRoutekey 路由规则 + * 1.Direct Exchange – 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。 + * 2.Fanout Exchange – 不处理路由键。将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。 + * 3.Topic Exchange – 将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。 + * 因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” 只会匹配到“audit.irs” + * @return 等于0值代表成功发送消息实体,小于0代表发送错误 + */ + virtual int Publish(const std::string &strMessage, const std::string &strExchange, const std::string &strRoutekey) = 0; + + /** + * @brief consumer 消费消息 + * @param [in] strQueueName 队列名称 + * @param [out] message_array 获取的消息实体 + * @param [int] GetNum 需要取得的消息个数 + * @param [int] timeout 取得的消息是延迟,若为NULL,表示持续取,无延迟,阻塞状态 + * @return 等于0值代表成功,小于0代表错误,错误信息从ErrorReturn返回 + */ + virtual int Consumer_limit(const std::string &strQueueName, std::vector &message_array, int GetNum = 1, struct timeval *timeout = NULL) = 0; + + /** + * @brief consumer 消费消息 + * @param [in] strQueueName 队列名称 + * @param [out] message_array 获取的消息实体 + * @param [int] GetNum 需要取得的消息个数 + * @param [int] timeout 取得的消息是延迟,若为NULL,表示持续取,无延迟,阻塞状态 + * @return 等于0值代表成功,小于0代表错误,错误信息从ErrorReturn返回 + */ + virtual int Consumer(const std::string &strQueueName, RABBITMQ_CALLBACK callback, void * contex, struct timeval *timeout = NULL) = 0; + + + +}; + diff --git a/src/reprocessing_module/rbmq/RabbitmqClientImpl.cpp b/src/reprocessing_module/rbmq/RabbitmqClientImpl.cpp new file mode 100755 index 0000000..f49281c --- /dev/null +++ b/src/reprocessing_module/rbmq/RabbitmqClientImpl.cpp @@ -0,0 +1,463 @@ +#include "RabbitmqClientImpl.hpp" +#include + + +CRabbitmqClientImpl::CRabbitmqClientImpl() +: m_strHostname("") +, m_iPort(0) +, m_strUser("") +, m_strPasswd("") +, m_iChannel(1) //默认用1号通道,通道无所谓 +, m_pSock(NULL) +, m_pConn(NULL) +, m_max_reconnection(5) +{ + +} + +CRabbitmqClientImpl::~CRabbitmqClientImpl() +{ + if (NULL != m_pConn) { + Disconnect(); + m_pConn = NULL; + } +} + +int CRabbitmqClientImpl::Connect(const string &strHostname, int iPort, const string &strUser, const string &strPasswd, const string &vhost) +{ + m_strHostname = strHostname; + m_iPort = iPort; + m_strUser = strUser; + m_strPasswd = strPasswd; + m_strVHost = vhost; + + m_pConn = amqp_new_connection(); + if (NULL == m_pConn) + { + spdlog::error("amqp new connection failed"); + return -1; + } + + m_pSock = amqp_tcp_socket_new(m_pConn); + if (NULL == m_pSock) + { + spdlog::error("amqp tcp new socket failed"); + return -2; + } + + if (0 > amqp_socket_open(m_pSock, m_strHostname.c_str(), m_iPort)) + { + spdlog::error("amqp socket open failed"); + return -3; + } + + error_code_t err = ErrorMsg(amqp_login(m_pConn, m_strVHost.c_str(), 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, m_strUser.c_str(), m_strPasswd.c_str()), "Logging in"); + if (error_code_t::NORMAL != err) + return -4; + + return 0; +} + +int CRabbitmqClientImpl::Disconnect() { + if (NULL != m_pConn) + { + + if (error_code_t::NORMAL != ErrorMsg(amqp_connection_close(m_pConn, AMQP_REPLY_SUCCESS), "Closing connection")) + return -1; + + int ret_code = 0; + if (0 > (ret_code = amqp_destroy_connection(m_pConn))) + { + fprintf(stderr, "%s: %s\n", "destory connection", amqp_error_string2(ret_code)); + return -2; + } + m_pConn = NULL; + } + + return 0; +} + +error_code_t CRabbitmqClientImpl::Reconnection() +{ + Disconnect(); + Connect(m_strHostname, m_iPort, m_strUser, m_strPasswd, m_strVHost); +} + + +int CRabbitmqClientImpl::ExchangeDeclare(const string &strExchange, const string &strType, const bool durable) +{ + amqp_channel_open(m_pConn, m_iChannel); + + amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str()); + amqp_bytes_t _type = amqp_cstring_bytes(strType.c_str()); + int _passive= 0; + amqp_exchange_declare(m_pConn, m_iChannel, _exchange, _type, _passive, durable, 0, 0, amqp_empty_table); + if (error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "exchange_declare")) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -1; + } + + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return 0; +} + +int CRabbitmqClientImpl::QueueDeclare(const string &strQueueName, const bool durable) { + if(NULL == m_pConn) { + spdlog::error("QueueDeclare m_pConn is null"); + return -1; + } + + amqp_channel_open(m_pConn, m_iChannel); + amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str()); + int32_t _passive = 0; + // int32_t _durable = 0; + int32_t _exclusive = 0; + //int32_t _auto_delete = 1; + int32_t _auto_delete = 0; + amqp_queue_declare(m_pConn, m_iChannel, _queue, _passive, durable, _exclusive, _auto_delete, amqp_empty_table); + if (error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_declare")) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -1; + } + + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return 0; +} + +int CRabbitmqClientImpl::QueueBind(const string &strQueueName, const string &strExchange, const string &strBindKey) { + if(NULL == m_pConn) { + spdlog::error("QueueBind m_pConn is null"); + return -1; + } + + amqp_channel_open(m_pConn, m_iChannel); + amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str()); + amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str()); + amqp_bytes_t _routkey = amqp_cstring_bytes(strBindKey.c_str()); + amqp_queue_bind(m_pConn, m_iChannel, _queue, _exchange, _routkey, amqp_empty_table); + if(error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_bind")) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -1; + } + + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return 0; +} + +int CRabbitmqClientImpl::QueueUnbind(const string &strQueueName, const string &strExchange, const string &strBindKey) { + if(NULL == m_pConn) { + spdlog::error("QueueUnbind m_pConn is null"); + return -1; + } + + amqp_channel_open(m_pConn, m_iChannel); + amqp_bytes_t _queue = amqp_cstring_bytes(strQueueName.c_str()); + amqp_bytes_t _exchange = amqp_cstring_bytes(strExchange.c_str()); + amqp_bytes_t _routkey = amqp_cstring_bytes(strBindKey.c_str()); + amqp_queue_unbind(m_pConn, m_iChannel, _queue, _exchange, _routkey, amqp_empty_table); + if(error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "queue_unbind")) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -1; + } + + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return 0; +} + +int CRabbitmqClientImpl::QueueDelete(const string &strQueueName, int iIfUnused) { + if(NULL == m_pConn) { + spdlog::error("QueueDelete m_pConn is null"); + return -1; + } + + amqp_channel_open(m_pConn, m_iChannel); + if(error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "open channel")) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -2; + } + + amqp_queue_delete(m_pConn, m_iChannel, amqp_cstring_bytes(strQueueName.c_str()), iIfUnused, 0); + if(error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "delete queue")) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -3; + } + + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return 0; +} + +int CRabbitmqClientImpl::Publish(const string &strMessage, const string &strExchange, const string &strRoutekey) { + if (NULL == m_pConn) + { + spdlog::error("publish m_pConn is null, publish failed"); + return -1; + } + +#if 1 + for (int i = 0; i < m_max_reconnection; ++i) + { + amqp_channel_open(m_pConn, m_iChannel); + if (error_code_t::NORMAL == ErrorMsg(amqp_get_rpc_reply(m_pConn), "publish open channel")) + goto _continue; + spdlog::error("Publish try {:d} reconnection", i+1); + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + Reconnection(); + } + return -2; +_continue: +#else + + amqp_channel_open(m_pConn, m_iChannel); + if (error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "publish open channel")) + { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -2; + } + +#endif + amqp_bytes_t message_bytes; + message_bytes.len = strMessage.length(); + message_bytes.bytes = (void *)(strMessage.c_str()); + + /* + amqp_basic_properties_t props; + props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG; + props.content_type = amqp_cstring_bytes(m_type.c_str()); + props.delivery_mode = m_durable; // persistent delivery mode + */ + + amqp_bytes_t exchange = amqp_cstring_bytes(strExchange.c_str()); + amqp_bytes_t routekey = amqp_cstring_bytes(strRoutekey.c_str()); + + + if (0 != amqp_basic_publish(m_pConn, m_iChannel, exchange, routekey, 0, 0, NULL, message_bytes)) + { + spdlog::error("publish amqp_basic_publish failed"); + if (error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "amqp_basic_publish")) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -3; + } + } + + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return 0; +} + +int CRabbitmqClientImpl::Consumer(const string &strQueueName, RABBITMQ_CALLBACK callback, void *contex, struct timeval *timeout) +{ + if (NULL == m_pConn) + { + spdlog::error("Consumer m_pConn is null, Consumer failed"); + return -1; + } + +#if 0 + for (int i = 0; i < m_max_connection; ++i) + { + amqp_channel_open(m_pConn, m_iChannel); + if (0 == ErrorMsg(amqp_get_rpc_reply(m_pConn), "consumer open channel")) + goto _continue; + spdlog::error("Consumer try {:d} reconnection", i+1); + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + Disconnect(); + Connect(m_strHostname, m_iPort, m_strUser, m_strPasswd, m_strVHost); + } + + return -2; + + +_continue: + +#else + + amqp_channel_open(m_pConn, m_iChannel); + if (error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "Consumer open channel")) + { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -2; + } + +#endif + + int GetNum = 1; + amqp_basic_qos(m_pConn, m_iChannel, 0, GetNum, 0); + int ack = 1; // no_ack 是否需要确认消息后再从队列中删除消息 + amqp_bytes_t queuename= amqp_cstring_bytes(strQueueName.c_str()); + amqp_basic_consume(m_pConn, m_iChannel, queuename, amqp_empty_bytes, 0, ack, 0, amqp_empty_table); + + if (error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "Consuming")) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -3; + } + + int hasget = 0; + amqp_rpc_reply_t res; + amqp_envelope_t envelope; + + while (1) + { + amqp_maybe_release_buffers(m_pConn); + res = amqp_consume_message(m_pConn, &envelope, timeout, 0); + if (AMQP_RESPONSE_NORMAL != res.reply_type) { + + spdlog::error("Consumer amqp_channel_close failed then continue"); +#if 1 + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + if (0 == hasget) + return -res.reply_type; + else + return 0; +#endif + } + + char *temp = new char[envelope.message.body.len + 1](); + memcpy(temp, (char *)envelope.message.body.bytes, sizeof(char)*envelope.message.body.len); + amqp_destroy_envelope(&envelope); + callback(contex, temp); + hasget++; + usleep(1); + } + + return 0; +} + + +int CRabbitmqClientImpl::Consumer_limit(const string &strQueueName, vector &message_array, int GetNum, struct timeval *timeout) +{ + if (NULL == m_pConn) { + spdlog::error("Consumer m_pConn is null, Consumer failed"); + return -1; + } + +#if 0 + for (int i = 0; i < m_max_connection; ++i) + { + amqp_channel_open(m_pConn, m_iChannel); + if (0 == ErrorMsg(amqp_get_rpc_reply(m_pConn), "consumer open channel")) + goto _continue; + spdlog::error("Consumer_limit try {:d} reconnection", i+1); + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + Disconnect(); + Connect(m_strHostname, m_iPort, m_strUser, m_strPasswd, m_strVHost); + } + + return -2; + + +_continue: + +#else + + amqp_channel_open(m_pConn, m_iChannel); + if (error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "Consumer_limit open channel")) + { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -2; + } + +#endif + + amqp_basic_qos(m_pConn, m_iChannel, 0, GetNum, 0); + int ack = 1; // no_ack 是否需要确认消息后再从队列中删除消息 + amqp_bytes_t queuename= amqp_cstring_bytes(strQueueName.c_str()); + amqp_basic_consume(m_pConn, m_iChannel, queuename, amqp_empty_bytes, 0, ack, 0, amqp_empty_table); + + if (error_code_t::NORMAL != ErrorMsg(amqp_get_rpc_reply(m_pConn), "Consuming")) + { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -3; + } + + int hasget = 0; + amqp_rpc_reply_t res; + amqp_envelope_t envelope; + while (GetNum > 0) + { + amqp_maybe_release_buffers(m_pConn); + res = amqp_consume_message(m_pConn, &envelope, timeout, 0); + if (AMQP_RESPONSE_NORMAL != res.reply_type) { + spdlog::error("Consumer amqp_channel_close failed then continue"); +#if 1 + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + if (0 == hasget) + return -res.reply_type; + else + return 0; +#endif + } + + string str((char *)envelope.message.body.bytes, (char *)envelope.message.body.bytes + envelope.message.body.len); + message_array.push_back(str); + int rtn = amqp_basic_ack(m_pConn, m_iChannel, envelope.delivery_tag, 1); + amqp_destroy_envelope(&envelope); + if (rtn != 0) { + amqp_channel_close(m_pConn, m_iChannel, AMQP_REPLY_SUCCESS); + return -4; + } + + GetNum--; + hasget++; + usleep(1); + } + + return 0; +} + +error_code_t CRabbitmqClientImpl::ErrorMsg(amqp_rpc_reply_t x, char const *context) +{ + switch (x.reply_type) + { + case AMQP_RESPONSE_NORMAL: + return error_code_t::NORMAL; + + case AMQP_RESPONSE_NONE: + spdlog::error("{:s}: missing RPC reply type!", context); + return error_code_t::RESPONSE_NONE; + + case AMQP_RESPONSE_LIBRARY_EXCEPTION: + spdlog::error("{:s}: {:s}", context, amqp_error_string2(x.library_error)); + return error_code_t::LIBRARY_EXCEPTION; + + case AMQP_RESPONSE_SERVER_EXCEPTION: + switch (x.reply.id) { + case AMQP_CONNECTION_CLOSE_METHOD: { + amqp_connection_close_t *m = (amqp_connection_close_t *)x.reply.decoded; + std::printf("%s: server connection error %uh, message: %.*s", + context, m->reply_code, (int)m->reply_text.len, + (char *)m->reply_text.bytes); + return error_code_t::CONNECTION_CLOSED; + } + case AMQP_CHANNEL_CLOSE_METHOD: { + amqp_channel_close_t *m = (amqp_channel_close_t *)x.reply.decoded; + std::printf("%s: server channel error %uh, message: %.*s", + context, m->reply_code, (int)m->reply_text.len, + (char *)m->reply_text.bytes); + return error_code_t::CHANNEL_CLOSED; + } + default: + std::printf("%s: unknown server error, method id 0x%08X", + context, x.reply.id); + return error_code_t::UNKNOWN; + } + } + return error_code_t::NORMAL; +} + +CRabbitmqClient* CRabbitmqClient::get_instance() +{ + CRabbitmqClient* instance_ptr = nullptr; + if (instance_ptr == nullptr) + instance_ptr = new CRabbitmqClientImpl(); + return instance_ptr; +} + + +void CRabbitmqClient::destory(CRabbitmqClient* instance) +{ + if (instance != nullptr) + { + delete instance; + instance = nullptr; + } +} + diff --git a/src/reprocessing_module/rbmq/RabbitmqClientImpl.hpp b/src/reprocessing_module/rbmq/RabbitmqClientImpl.hpp new file mode 100755 index 0000000..3d6adbf --- /dev/null +++ b/src/reprocessing_module/rbmq/RabbitmqClientImpl.hpp @@ -0,0 +1,130 @@ +#pragma once +#include "RabbitmqClient.hpp" + +#include +#include +#include +#include +#include "amqp_tcp_socket.h" +#include + + +using std::string; +using std::vector; + +typedef void (*RABBITMQ_CALLBACK)(void* contex, const char * msg); + +enum class error_code_t +{ + UNKNOWN = -1, + NORMAL = 0, + CONNECTION_CLOSED, + CHANNEL_CLOSED, + RESPONSE_NONE, + LIBRARY_EXCEPTION, +}; + +class CRabbitmqClientImpl: virtual public CRabbitmqClient{ +public: + CRabbitmqClientImpl(); + ~CRabbitmqClientImpl(); + + virtual int Connect(const string &strHostname, int iPort, const string &strUser, const string &strPasswd, const string &vhost = "/"); + virtual int Disconnect(); + + /** + * @brief ExchangeDeclare 声明exchange + * @param [in] strExchange + * @param [in] strType + * @return 等于0值代表成功创建exchange,小于0代表错误 + */ + virtual int ExchangeDeclare(const string &strExchange, const string &strType, const bool durable = false); + + /** + * @brief QueueDeclare 声明消息队列 + * @param [in] strQueueName 消息队列实例 + * @param + * @return 等于0值代表成功创建queue,小于0代表错误 + */ + virtual int QueueDeclare(const string &strQueueName, const bool durable = false); + + /** + * @brief QueueBind 将队列,交换机和绑定规则绑定起来形成一个路由表 + * @param [in] strQueueName 消息队列 + * @param [in] strExchange 交换机名称 + * @param [in] strBindKey 路由名称 “msg.#” “msg.weather.**” + * @return 等于0值代表成功绑定,小于0代表错误 + */ + virtual int QueueBind(const string &strQueueName, const string &strExchange, const string &strBindKey); + + /** + * @brief QueueUnbind 将队列,交换机和绑定规则绑定解除 + * @param [in] strQueueName 消息队列 + * @param [in] strExchange 交换机名称 + * @param [in] strBindKey 路由名称 “msg.#” “msg.weather.**” + * @return 等于0值代表成功绑定,小于0代表错误 + */ + virtual int QueueUnbind(const string &strQueueName, const string &strExchange, const string &strBindKey); + + /** + * @brief QueueDelete 删除消息队列。 + * @param [in] strQueueName 消息队列名称 + * @param [in] iIfUnused 消息队列是否在用,1 则论是否在用都删除 + * @return 等于0值代表成功删除queue,小于0代表错误 + */ + virtual int QueueDelete(const string &strQueueName, int iIfUnused); + + /** + * @brief Publish 发布消息 + * @param [in] strMessage 消息实体 + * @param [in] strExchange 交换器 + * @param [in] strRoutekey 路由规则 + * 1.Direct Exchange – 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。 + * 2.Fanout Exchange – 不处理路由键。将队列绑定到交换机上。一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。 + * 3.Topic Exchange – 将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词。 + * 因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” 只会匹配到“audit.irs” + * @return 等于0值代表成功发送消息实体,小于0代表发送错误 + */ + virtual int Publish(const string &strMessage, const string &strExchange, const string &strRoutekey); + + /** + * @brief consumer 消费消息 + * @param [in] strQueueName 队列名称 + * @param [out] message_array 获取的消息实体 + * @param [int] GetNum 需要取得的消息个数 + * @param [int] timeout 取得的消息是延迟,若为NULL,表示持续取,无延迟,阻塞状态 + * @return 等于0值代表成功,小于0代表错误,错误信息从ErrorReturn返回 + */ + virtual int Consumer_limit(const string &strQueueName, vector &message_array, int GetNum = 1, struct timeval *timeout = NULL); + + /** + * @brief consumer 消费消息 + * @param [in] strQueueName 队列名称 + * @param [out] message_array 获取的消息实体 + * @param [int] GetNum 需要取得的消息个数 + * @param [int] timeout 取得的消息是延迟,若为NULL,表示持续取,无延迟,阻塞状态 + * @return 等于0值代表成功,小于0代表错误,错误信息从ErrorReturn返回 + */ + virtual int Consumer(const string &strQueueName, RABBITMQ_CALLBACK callback, void * contex, struct timeval *timeout = NULL); + + + CRabbitmqClientImpl(const CRabbitmqClientImpl &lh) = delete; + void operator=(const CRabbitmqClientImpl &lh) = delete; + +private: + error_code_t ErrorMsg(amqp_rpc_reply_t x, char const *context); + + error_code_t Reconnection(); + + string m_strHostname; // amqp主机 + int m_iPort; // amqp端口 + string m_strUser; + string m_strPasswd; + string m_strVHost; + int m_iChannel; + int m_max_reconnection; + + amqp_socket_t *m_pSock; + amqp_connection_state_t m_pConn; + +}; diff --git a/src/reprocessing_module/rbmq/common.h b/src/reprocessing_module/rbmq/common.h new file mode 100755 index 0000000..217fb5d --- /dev/null +++ b/src/reprocessing_module/rbmq/common.h @@ -0,0 +1,30 @@ +/* + * @Author: yangzilong + * @Date: 2021-12-07 16:39:17 + * @Last Modified by: yangzilong + * @Last Modified time: Do not edit + * @Email: yangzilong@objecteye.com + * @Description: + */ + +#pragma once + + +typedef struct rabbitmq_conn_params_t +{ + int port; + // char *ip[12+3+1]; + const char *ip; + const char *uname; + const char *passwd; + const char *vhost; + + const char *exchange; + const char *exchange_type; + const char *queue; + const char *routing_key; + + bool durable_exchange, durable_queue; +} rabbitmq_conn_params_t; + + diff --git a/src/reprocessing_module/snapshot_reprocessing.cpp b/src/reprocessing_module/snapshot_reprocessing.cpp index 16f9f67..86721dd 100644 --- a/src/reprocessing_module/snapshot_reprocessing.cpp +++ b/src/reprocessing_module/snapshot_reprocessing.cpp @@ -3,6 +3,7 @@ #include "../common/logger.hpp" #include "../ai_platform/mvpt_process_assist.h" #include "../decoder/interface/DeviceMemory.hpp" +#include "../helpers/img_util.h" snapshot_reprocessing::snapshot_reprocessing(int devId) @@ -49,6 +50,16 @@ vector snapshot_reprocessing::get_vehicle_snapshot(vectorbasic_param || !cur_task_params->basic_param->adapt_param) + { + continue; + } + + // 多边形区域 + auto adapt_param = cur_task_params->basic_param->adapt_param; + if (adapt_param->points_count <= 0) { + continue; + } // 同一目标间隔多少帧保存 int snap_frame_interval = ((algor_config_param_snapshot*)cur_task_params->algor_param)->snap_frame_interval; @@ -61,9 +72,14 @@ vector snapshot_reprocessing::get_vehicle_snapshot(vector 0 && det_obj.num % snap_frame_interval >= skip_frame){ continue; } + + sy_point center; + center.x_ = (det_obj.left + det_obj.right) * 0.5; + center.y_ = det_obj.bottom; + int type_index = det_obj.index; if ((type_index == 4 || type_index == 5 || type_index == 6 || type_index ==7 || type_index ==8) - && snapshot_legal_inarea(cur_task_params->basic_param->algor_valid_rect, det_obj.left, det_obj.top, det_obj.right, det_obj.bottom)) + && common::isInPolygon(adapt_param->points, adapt_param->points_count, center)) { video_object_info obj_info; obj_info.top = det_obj.top; @@ -202,6 +218,30 @@ void snapshot_reprocessing::update_bestsnapshot(vector vec_devMem index = total_snapshot_info[new_obj].index.index; } + algorithm_type_t algor_type; + if (index ==0) algor_type = algorithm_type_t::HUMAN_SNAPSHOT; + if (index ==1 || index ==2 || index ==3) algor_type = algorithm_type_t::NONMOTOR_VEHICLE_SNAPSHOT; + if (index ==4 || index ==5 || index ==6 || index ==7 || index ==8) algor_type = algorithm_type_t::VEHICLE_SNAPSHOT; + if (!(algor_config_param.count(task_id) && algor_param.count(task_id) && algor_param[task_id].count(algor_type))) + continue; + task_param_manager::algo_param_type_t_* cur_task_params = algor_param[task_id][algor_type]; + if (!cur_task_params || !cur_task_params->basic_param || !cur_task_params->basic_param->adapt_param) { + continue; + } + + // 多边形区域 + auto adapt_param = cur_task_params->basic_param->adapt_param; + if (adapt_param->points_count <= 0) { + continue; + } + + sy_point center; + center.x_ = (obj_info.left + obj_info.right) * 0.5; + center.y_ = obj_info.bottom; + if (!common::isInPolygon(adapt_param->points, adapt_param->points_count, center)) { + continue; + } + int cur_real_width = (obj_info.right - obj_info.left); int cur_real_height = (obj_info.bottom - obj_info.top); int cur_real_index = obj_info.index; @@ -220,17 +260,6 @@ void snapshot_reprocessing::update_bestsnapshot(vector vec_devMem { /* manager insert new object. */ /* 判断目标合法 */ - algorithm_type_t algor_type; - if (index ==0) algor_type = algorithm_type_t::HUMAN_SNAPSHOT; - if (index ==1 || index ==2 || index ==3) algor_type = algorithm_type_t::NONMOTOR_VEHICLE_SNAPSHOT; - if (index ==4 || index ==5 || index ==6 || index ==7 || index ==8) algor_type = algorithm_type_t::VEHICLE_SNAPSHOT; - if (!(algor_config_param.count(task_id) && algor_param.count(task_id) && algor_param[task_id].count(algor_type))) - continue; - task_param_manager::algo_param_type_t_* cur_task_params = algor_param[task_id][algor_type]; - if (!snapshot_legal_inarea(cur_task_params->basic_param->algor_valid_rect,obj_info.left, obj_info.top, obj_info.right, obj_info.bottom)){ - continue; - } - if(!snapshot_legal_minarea(index, cur_real_width, cur_real_height)){ continue; } @@ -265,15 +294,6 @@ void snapshot_reprocessing::update_bestsnapshot(vector vec_devMem } else { total_snapshot_info[new_obj].last_area = (obj_info.right - obj_info.left) * (obj_info.bottom - obj_info.top); - algorithm_type_t algor_type; - if (index ==0) algor_type = algorithm_type_t::HUMAN_SNAPSHOT; - if (index ==1 || index ==2 || index ==3) algor_type = algorithm_type_t::NONMOTOR_VEHICLE_SNAPSHOT; - if (index ==4 || index ==5 || index ==6 || index ==7 || index ==8) algor_type = algorithm_type_t::VEHICLE_SNAPSHOT; - if (!(algor_config_param.count(task_id) && algor_param.count(task_id) && algor_param[task_id].count(algor_type))) - continue; - task_param_manager::algo_param_type_t_* cur_task_params = algor_param[task_id][algor_type]; - if (!snapshot_legal_inarea(cur_task_params->basic_param->algor_valid_rect,obj_info.left, obj_info.top, obj_info.right, obj_info.bottom)) - continue; //--------------------------------------------------------------- if (!best_snapshot_judge_algor(new_obj, total_snapshot_info[new_obj], obj_info.left, obj_info.top, cur_real_width, cur_real_height, frame_width, frame_height)) @@ -330,6 +350,431 @@ void snapshot_reprocessing::update_bestsnapshot(vector vec_devMem } } + +/* 获取农村违法分析要求的目标快照图--轨迹起始 最佳 轨迹结束 */ +void snapshot_reprocessing::update_village_bestsnapshot(vector vec_devMem, vector &ol_det_result, vector>& delete_object_id){ + map && algor_config_param = m_task_param_manager->get_task_algor_params(); + map> && algor_param = m_task_param_manager->get_task_other_params(); + + VPCUtil* pVpcUtil = VPCUtil::getInstance(); + + for (size_t i = 0; i < vec_devMem.size(); i++){ + + onelevel_det_result det_result = ol_det_result[i]; + if (0 == det_result.obj_count){ + continue; + } + + DeviceMemory* memPtr = vec_devMem[i]; + + string task_id = memPtr->getId(); + int frame_height = memPtr->getHeight(); + int frame_width = memPtr->getWidth(); + + vector vec_obj_info; + vector last_vec_obj_info; + for (int c = 0; c < det_result.obj_count; c++){ + + det_objinfo obj_info = det_result.obj[c]; + OBJ_KEY new_obj = { task_id, obj_info.id }; + + int index = 0; + + /* 投票确定目标index */ + if (total_village_snapshot_info.find(new_obj) == total_village_snapshot_info.end()){ + index = obj_info.index; + } else { + index = total_village_snapshot_info[new_obj].snapShots[1].index.index; + } + + int cur_real_width = (obj_info.right - obj_info.left); + int cur_real_height = (obj_info.bottom - obj_info.top); + int cur_real_index = obj_info.index; + + int expansion_width = cur_real_width * EXPANSION_PROPORTION; + int expansion_height = cur_real_height * EXPANSION_PROPORTION; + // DEBUG----------------------------------------------------------------- + // 0-行人 1-自行车 2-摩托车 3-三轮车 4-小型车 5-大车 6-卡车 7-拖拉机 8-中巴 + if(index ==0 || index ==1 || index ==2 || index ==3) { //行人和非机动车外扩指定像素即可 + expansion_width = 10; + expansion_height = 10; + } + + /* 若该目标第一次出现 */ + if (total_village_snapshot_info.find(new_obj) == total_village_snapshot_info.end()) + { + if (total_village_snapshot_info.size() > 400) + {//确保显存不会无限增长 + return; + } + + /* manager insert new object. */ + /* 判断目标合法 */ + if (!(algor_config_param.count(task_id) && algor_param.count(task_id))) + continue; + if (!(algor_param[task_id].count(algorithm_type_t::TRICYCLE_MANNED) || algor_param[task_id].count(algorithm_type_t::TRUCK_MANNED) || + algor_param[task_id].count(algorithm_type_t::NONMOTOR_VEHICLE_NOHELMET) || algor_param[task_id].count(algorithm_type_t::NONMOTOR_VEHICLE_OVERMAN) || + algor_param[task_id].count(algorithm_type_t::NONMOTOR_VEHICLE_USEPHONE) || algor_param[task_id].count(algorithm_type_t::NONMOTOR_VEHICLE_REFIT) || + algor_param[task_id].count(algorithm_type_t::PERSON_RUNNING_REDLIGHTS) || algor_param[task_id].count(algorithm_type_t::NONMOTOR_RUNNING_REDLIGHTS) || + algor_param[task_id].count(algorithm_type_t::PERSON_IN_VEHICLELANE) || algor_param[task_id].count(algorithm_type_t::NONMOTOR_IN_VEHICLELANE) || + algor_param[task_id].count(algorithm_type_t::NONMOTOR_CEOSSPARKLINE) || algor_param[task_id].count(algorithm_type_t::PERSON_CROSS) || + algor_param[task_id].count(algorithm_type_t::NONMOTOR_WRONGDIRECTION) || algor_param[task_id].count(algorithm_type_t::VEHICLE_WRONGDIRECTION) || + algor_param[task_id].count(algorithm_type_t::VEHICLE_SOLIDLINETURNAROUND) || algor_param[task_id].count(algorithm_type_t::VEHICLE_NOTGIVEWAY) || + algor_param[task_id].count(algorithm_type_t::VEHICLE_NOTDECELERATION))) + continue; + + if(!snapshot_legal_minarea(index, cur_real_width, cur_real_height)){ + continue; + } + // 过滤边缘位置 + if(obj_info.left < 80 || obj_info.top < 50 || (obj_info.right > frame_width - 80) || (obj_info.bottom > frame_height - 50)){ + continue; + } + total_village_snapshot_info[new_obj].exists[1] = true; + /* 存入当前抠图目标参数 flags用于判断目标从画面什么位置出现 方便之后排除出画面边缘的快照图 */ + total_village_snapshot_info[new_obj].snapShots[1].index.count++; + total_village_snapshot_info[new_obj].snapShots[1].index.index = cur_real_index; + total_village_snapshot_info[new_obj].snapShots[1].confidence = obj_info.confidence; + total_village_snapshot_info[new_obj].snapShots[1].flags[0] = obj_info.left < minDistance[0] + SCALE_OUT ? 0 : 1; //left + total_village_snapshot_info[new_obj].snapShots[1].flags[1] = obj_info.top < minDistance[1] + SCALE_OUT ? 0 : 1; //top + total_village_snapshot_info[new_obj].snapShots[1].flags[2] = obj_info.right > frame_width - minDistance[2] - SCALE_OUT ? 0 : 1; //right + total_village_snapshot_info[new_obj].snapShots[1].flags[3] = obj_info.bottom > frame_height - minDistance[3] - SCALE_OUT ? 0 : 1; //bottom + + int cur_left = max(obj_info.left - 10, 0); + int cur_top = max(obj_info.top - 10, 0); + int cur_right = min(obj_info.right + 10, frame_width - 1); + int cur_bottom = min(obj_info.bottom + 10, frame_height - 1); + total_village_snapshot_info[new_obj].snapShots[1].obj_pos = { cur_left, cur_top, cur_right - cur_left, cur_bottom - cur_top }; //debug by zsh 推出的坐标外扩10像素 + total_village_snapshot_info[new_obj].snapShots[1].last_area = total_village_snapshot_info[new_obj].snapShots[1].max_area = (cur_right - cur_left) * (cur_bottom - cur_top); + + video_object_info info; + info.left = max(obj_info.left - expansion_width, 0); + info.top = max(obj_info.top - expansion_height, 0); + info.right = min(obj_info.right + expansion_width, frame_width - 1); + info.bottom = min(obj_info.bottom + expansion_height, frame_height - 1); + strcpy(info.task_id, task_id.c_str()); + info.object_id = obj_info.id; + info.confidence = obj_info.confidence; + info.index = index; + + vec_obj_info.push_back(info);//用于最佳抓拍图 + + // 首张抓拍图:切图+信息存储 + vpc_img_info crop_img = pVpcUtil->crop(memPtr, info); + total_village_snapshot_info[new_obj].exists[0] = true; + total_village_snapshot_info[new_obj].snapShots[0].index.index = cur_real_index; + total_village_snapshot_info[new_obj].snapShots[0].confidence = obj_info.confidence; + total_village_snapshot_info[new_obj].snapShots[0].obj_pos = { cur_left, cur_top, cur_right - cur_left, cur_bottom - cur_top }; + total_village_snapshot_info[new_obj].snapShots[0].snapShot = VPCUtil::vpc_devMem2vpcImg(memPtr); + total_village_snapshot_info[new_obj].snapShots[0].snapShotLittle = crop_img; + + // 缓存末张抓拍图 + total_village_snapshot_info[new_obj].exists[2] = true; + total_village_snapshot_info[new_obj].snapShots[2].index.index = cur_real_index; + total_village_snapshot_info[new_obj].snapShots[2].confidence = obj_info.confidence; + total_village_snapshot_info[new_obj].snapShots[2].obj_pos = { cur_left, cur_top, cur_right - cur_left, cur_bottom - cur_top }; + last_vec_obj_info.push_back(info); + + } else { + total_village_snapshot_info[new_obj].snapShots[1].last_area = (obj_info.right - obj_info.left) * (obj_info.bottom - obj_info.top); + + if (!(algor_config_param.count(task_id) && algor_param.count(task_id))) + continue; + if (!(algor_param[task_id].count(algorithm_type_t::TRICYCLE_MANNED) || algor_param[task_id].count(algorithm_type_t::TRUCK_MANNED) || + algor_param[task_id].count(algorithm_type_t::NONMOTOR_VEHICLE_NOHELMET) || algor_param[task_id].count(algorithm_type_t::NONMOTOR_VEHICLE_OVERMAN) || + algor_param[task_id].count(algorithm_type_t::NONMOTOR_VEHICLE_USEPHONE) || algor_param[task_id].count(algorithm_type_t::NONMOTOR_VEHICLE_REFIT) || + algor_param[task_id].count(algorithm_type_t::PERSON_RUNNING_REDLIGHTS) || algor_param[task_id].count(algorithm_type_t::NONMOTOR_RUNNING_REDLIGHTS) || + algor_param[task_id].count(algorithm_type_t::PERSON_IN_VEHICLELANE) || algor_param[task_id].count(algorithm_type_t::NONMOTOR_IN_VEHICLELANE) || + algor_param[task_id].count(algorithm_type_t::NONMOTOR_CEOSSPARKLINE) || algor_param[task_id].count(algorithm_type_t::PERSON_CROSS) || + algor_param[task_id].count(algorithm_type_t::NONMOTOR_WRONGDIRECTION) || algor_param[task_id].count(algorithm_type_t::VEHICLE_WRONGDIRECTION) || + algor_param[task_id].count(algorithm_type_t::VEHICLE_SOLIDLINETURNAROUND) || algor_param[task_id].count(algorithm_type_t::VEHICLE_NOTGIVEWAY) || + algor_param[task_id].count(algorithm_type_t::VEHICLE_NOTDECELERATION))) + continue; + + // 过滤边缘位置 + if(obj_info.left < 80 || obj_info.top < 50 || (obj_info.right > frame_width - 80) || (obj_info.bottom > frame_height - 50)){ + continue; + } + + int cur_left = max(obj_info.left - 10, 0); + int cur_top = max(obj_info.top - 10, 0); + int cur_right = min(obj_info.right + 10, frame_width - 1); + int cur_bottom = min(obj_info.bottom + 10, frame_height - 1); + + video_object_info info; + info.left = max(obj_info.left - expansion_width, 0); + info.top = max(obj_info.top - expansion_height, 0); + info.right = min(obj_info.right + expansion_width, frame_width - 1); + info.bottom = min(obj_info.bottom + expansion_height, frame_height - 1); + strcpy(info.task_id, task_id.c_str()); + info.object_id = obj_info.id; + info.confidence = obj_info.confidence; + info.index = index; + + // 缓存末张抓拍图 + total_village_snapshot_info[new_obj].snapShots[2].index.index = cur_real_index; + total_village_snapshot_info[new_obj].snapShots[2].confidence = obj_info.confidence; + total_village_snapshot_info[new_obj].snapShots[2].obj_pos = { cur_left, cur_top, cur_right - cur_left, cur_bottom - cur_top }; + last_vec_obj_info.push_back(info); + //--------------------------------------------------------------- + if (!best_snapshot_judge_algor(new_obj, total_village_snapshot_info[new_obj].snapShots[1], obj_info.left, obj_info.top, + cur_real_width, cur_real_height, frame_width, frame_height)) + { + continue; + } + /* 若更优于之前的快照 做快照的更新 */ + if (total_village_snapshot_info[new_obj].snapShots[1].index.count == 0) + { + total_village_snapshot_info[new_obj].snapShots[1].index.count++; + total_village_snapshot_info[new_obj].snapShots[1].index.index = cur_real_index; + } + else + { + if (total_village_snapshot_info[new_obj].snapShots[1].index.index == cur_real_index) + total_village_snapshot_info[new_obj].snapShots[1].index.count++; + else + total_village_snapshot_info[new_obj].snapShots[1].index.count--; + } + + total_village_snapshot_info[new_obj].snapShots[1].obj_pos = { cur_left, cur_top, cur_right - cur_left, cur_bottom - cur_top }; //debug by zsh 推出的坐标外扩10像素 + total_village_snapshot_info[new_obj].snapShots[1].last_area = total_village_snapshot_info[new_obj].snapShots[1].max_area = (cur_right - cur_left) * (cur_bottom - cur_top); + + + vec_obj_info.push_back(info);//用于最佳抓拍图 + } + } + + vector imgList = pVpcUtil->crop_batch(memPtr, vec_obj_info); + vec_obj_info.clear(); + for (size_t i = 0; i < imgList.size(); i++) { + vpc_img_info obj_info = imgList[i]; + OBJ_KEY objKey = { obj_info.task_id, obj_info.object_id }; + VPCUtil::vpc_img_release(total_village_snapshot_info[objKey].snapShots[1].snapShot); + total_village_snapshot_info[objKey].snapShots[1].snapShot = VPCUtil::vpc_devMem2vpcImg(memPtr); + VPCUtil::vpc_img_release(total_village_snapshot_info[objKey].snapShots[1].snapShotLittle); + total_village_snapshot_info[objKey].snapShots[1].snapShotLittle = obj_info; + } + imgList.clear(); + + vector last_imgList = pVpcUtil->crop_batch(memPtr, last_vec_obj_info); + last_vec_obj_info.clear(); + for (size_t i = 0; i < last_imgList.size(); i++) { + vpc_img_info obj_info = last_imgList[i]; + OBJ_KEY objKey = { obj_info.task_id, obj_info.object_id }; + VPCUtil::vpc_img_release(total_village_snapshot_info[objKey].snapShots[2].snapShot); + total_village_snapshot_info[objKey].snapShots[2].snapShot = VPCUtil::vpc_devMem2vpcImg(memPtr); + VPCUtil::vpc_img_release(total_village_snapshot_info[objKey].snapShots[2].snapShotLittle); + total_village_snapshot_info[objKey].snapShots[2].snapShotLittle = obj_info; + } + last_imgList.clear(); + } +} + +map snapshot_reprocessing::get_total_village_snapshot_info(){ + return total_village_snapshot_info; +} + +bool snapshot_reprocessing::best_face_snapshot_judge_algor_v2(const OBJ_KEY& obj_key, const OBJ_VALUE& obj_value, int left, int top, int width, int height, int image_width, int image_height, float roll, float yaw, float pitch) +{ + return snapshot_legal_pos(obj_value.flags, left, top, left + width, top + height, image_width, image_height) + && snapshot_legal_inarea(width, height) + && snapshot_legal_area(obj_value.max_area, obj_value.last_area, left, top, left + width, top + height) + && snapshot_legal_pose(obj_value.roll, obj_value.yaw, obj_value.pitch, roll, yaw, pitch); +} + +//人脸快照保存更新 +int snapshot_reprocessing::update_face_bestsnapshot(vector vec_devMem, vector &ol_det_result, vector>& delete_object_id) +{ + //230327added + map && algor_config_param = m_task_param_manager->get_task_algor_params(); + map> && algor_param = m_task_param_manager->get_task_other_params(); + + VPCUtil* pVpcUtil = VPCUtil::getInstance(); + for(int idx=0; idx < vec_devMem.size(); idx++){ + + DeviceMemory* memPtr = vec_devMem[idx]; + string task_id = memPtr->getId(); + int frame_height = memPtr->getHeight(); + int frame_width = memPtr->getWidth(); + + if (0 == ol_det_result[idx].obj_count) { + continue; + } + + LOG_DEBUG("{}: {}",task_id,ol_det_result[idx].obj_count); + + int copy_obj_count = 0; //用于记录该路有多少个目标需要进行显存图像的更新 + vector vec_obj_info; + for (int c = 0; c < ol_det_result[idx].obj_count; c++) { + + det_objinfo obj_info = ol_det_result[idx].obj[c]; + OBJ_KEY new_obj = { task_id, obj_info.id }; + + if (obj_info.confidence < 0.6) + continue; + //--------------------------------------------- + //230327 增加指定区域过滤------------------------------------------ + if (!(algor_config_param.count(task_id) && algor_param.count(task_id) && algor_param[task_id].count(algorithm_type_t::FACE_SNAPSHOT))) + continue; + + task_param_manager::algo_param_type_t_* cur_task_params = algor_param[task_id][algorithm_type_t::FACE_SNAPSHOT]; + if (!cur_task_params || !cur_task_params->basic_param || !cur_task_params->basic_param->adapt_param) { + continue; + } + + auto adapt_param = cur_task_params->basic_param->adapt_param; + if (adapt_param->points_count <= 0) { + continue; + } + + //增加指定区域过滤------------------------------------------ + sy_point center; + center.x_ = (obj_info.left + obj_info.right) * 0.5; + center.y_ = obj_info.bottom; + if (!common::isInPolygon(adapt_param->points, adapt_param->points_count, center)) { + continue; + } + + int cur_real_width = (obj_info.right - obj_info.left); + int cur_real_height = (obj_info.bottom - obj_info.top); + int cur_real_index = obj_info.index; + LOG_DEBUG(" {}: {} roll:{} yaw:{} pitch:{}",task_id, obj_info.id, fabs(obj_info.roll),fabs(obj_info.yaw),fabs(obj_info.pitch)); + // 该目标的第一张 + if (total_face_snapshot_info.find(new_obj) == total_face_snapshot_info.end()){ + + /* manager insert new object. */ + // 有效区域和最小面积过滤 + if (cur_real_width * cur_real_height < 30 * 30) + { + continue; + } + + //--------------------------------------------------------------- + + LOG_DEBUG(" {}: {}",task_id, obj_info.id); + total_face_snapshot_info[new_obj].index.count++; + total_face_snapshot_info[new_obj].index.index = cur_real_index; //debug by zsh + total_face_snapshot_info[new_obj].confidence = obj_info.confidence; + // 人脸姿态角 added by zsh 220719------------------------------------------- + total_face_snapshot_info[new_obj].roll = obj_info.roll; + total_face_snapshot_info[new_obj].yaw = obj_info.yaw; + total_face_snapshot_info[new_obj].pitch = obj_info.pitch; + //------------------------------------------------------------------------- + + //判断是否有余地外扩 + total_face_snapshot_info[new_obj].flags[0] = obj_info.left < minDistance[0] + SCALE_OUT ? 0 : 1; //left + total_face_snapshot_info[new_obj].flags[1] = obj_info.top < minDistance[1] + SCALE_OUT ? 0 : 1; //top + total_face_snapshot_info[new_obj].flags[2] = obj_info.right > frame_width - minDistance[2] - SCALE_OUT ? 0 : 1; //right + total_face_snapshot_info[new_obj].flags[3] = obj_info.bottom > frame_height - minDistance[3] - SCALE_OUT ? 0 : 1; //bottom + + int cur_left = max(obj_info.left - 10, 0); + int cur_top = max(obj_info.top - 10, 0); + int cur_right = min(obj_info.right + 10, frame_width - 1); + int cur_bottom = min(obj_info.bottom + 10, frame_height - 1); + total_face_snapshot_info[new_obj].last_area = total_face_snapshot_info[new_obj].max_area = (cur_right - cur_left) * (cur_bottom - cur_top); + + + //人脸 按长边2倍外扩 --modified by zsh------------------------------------------------------- + int cur_real_max_length = cur_real_width > cur_real_height ? cur_real_width:cur_real_height; + int expansion_width = cur_real_max_length * FACE_EXPANSION_PROPORTION; + int expansion_height = cur_real_max_length * FACE_EXPANSION_PROPORTION; + + video_object_info info; + info.left = max(obj_info.left - expansion_width, 0); + info.top = max(obj_info.top - expansion_height, 0); + info.right = min(obj_info.right + expansion_width, frame_width - 1); + info.bottom = min(obj_info.bottom + expansion_height, frame_height - 1); + strcpy(info.task_id, task_id.c_str()); + info.object_id = obj_info.id; + info.confidence = obj_info.confidence; + info.index = obj_info.index; + + vec_obj_info.push_back(info); + + total_face_snapshot_info[new_obj].obj_pos = { info.left , info.top ,info.right - info.left , info.bottom - info.top }; + + // 存人脸关键点、检测框及大图 + memcpy(total_face_snapshot_info[new_obj].landmark_point, obj_info.landmark_point, sizeof(sy_point) * 25); + total_face_snapshot_info[new_obj].position = { obj_info.left, obj_info.top, obj_info.right - obj_info.left, obj_info.bottom - obj_info.top }; + } + else + { + // 最佳快照判断 + if (!best_face_snapshot_judge_algor_v2(new_obj, total_face_snapshot_info[new_obj], obj_info.left, obj_info.top, + cur_real_width, cur_real_height, frame_width, frame_height, obj_info.roll, obj_info.yaw, obj_info.pitch )) + continue; + + // 满足更新条件则进行更新 + if (total_face_snapshot_info[new_obj].index.count == 0) + { + total_face_snapshot_info[new_obj].index.count++; + total_face_snapshot_info[new_obj].index.index = cur_real_index; + } + else + { + if (total_face_snapshot_info[new_obj].index.index == cur_real_index) + total_face_snapshot_info[new_obj].index.count++; + else + total_face_snapshot_info[new_obj].index.count--; + } + + // 人脸姿态角 added by zsh 220719------------------------------------------- + total_face_snapshot_info[new_obj].roll = obj_info.roll; + total_face_snapshot_info[new_obj].yaw = obj_info.yaw; + total_face_snapshot_info[new_obj].pitch = obj_info.pitch; + //------------------------------------------------------------------------- + + int cur_left = max(obj_info.left - 10, 0); + int cur_top = max(obj_info.top - 10, 0); + int cur_right = min(obj_info.right + 10, frame_width - 1); + int cur_bottom = min(obj_info.bottom + 10, frame_height - 1); + // total_face_snapshot_info[new_obj].obj_pos = { cur_left, cur_top, cur_right - cur_left, cur_bottom - cur_top }; //debug by zsh 推出的坐标外扩10像素 + total_face_snapshot_info[new_obj].last_area = total_face_snapshot_info[new_obj].max_area = (cur_right - cur_left) * (cur_bottom - cur_top); + + //人脸 按长边2倍外扩 --modified by zsh------------------------------------------------------- + int cur_real_max_length = cur_real_width > cur_real_height ? cur_real_width:cur_real_height; + int expansion_width = cur_real_max_length * FACE_EXPANSION_PROPORTION; + int expansion_height = cur_real_max_length * FACE_EXPANSION_PROPORTION; + + video_object_info info; + info.left = max(obj_info.left - expansion_width, 0); + info.top = max(obj_info.top - expansion_height, 0); + info.right = min(obj_info.right + expansion_width, frame_width - 1); + info.bottom = min(obj_info.bottom + expansion_height, frame_height - 1); + strcpy(info.task_id, task_id.c_str()); + info.object_id = obj_info.id; + info.confidence = obj_info.confidence; + info.index = obj_info.index; + + vec_obj_info.push_back(info); + + total_face_snapshot_info[new_obj].obj_pos = { info.left , info.top ,info.right - info.left , info.bottom - info.top }; + + //存人脸关键点、检测框及大图 + memcpy(total_face_snapshot_info[new_obj].landmark_point, obj_info.landmark_point, sizeof(sy_point) * 25); + total_face_snapshot_info[new_obj].position = { obj_info.left, obj_info.top, obj_info.right - obj_info.left, obj_info.bottom - obj_info.top }; + } + } + + LOG_DEBUG("total_face_snapshot_info size: {}", total_face_snapshot_info.size()); + + vector imgList = pVpcUtil->crop_batch(memPtr, vec_obj_info); + vec_obj_info.clear(); + + for (size_t i = 0; i < imgList.size(); i++) { + vpc_img_info obj_info = imgList[i]; + OBJ_KEY objKey = { obj_info.task_id, obj_info.object_id }; + VPCUtil::vpc_img_release(total_face_snapshot_info[objKey].snapShot); + total_face_snapshot_info[objKey].snapShot = VPCUtil::vpc_devMem2vpcImg(memPtr); + VPCUtil::vpc_img_release(total_face_snapshot_info[objKey].snapShotLittle); + total_face_snapshot_info[objKey].snapShotLittle = obj_info; + } + imgList.clear(); + } + + return 0; +} + map snapshot_reprocessing::get_total_snapshot_info(){ return total_snapshot_info; } @@ -367,7 +812,90 @@ void snapshot_reprocessing::release_finished_locus_snapshot(const string taskid, return; } - for(auto ss = total_snapshot_info.begin(); ss != total_snapshot_info.end(); ss++) + for(auto ss = total_snapshot_info.begin(); ss != total_snapshot_info.end();) + { + if (strcmp(ss->first.video_id.c_str(), taskid.c_str()) == 0) + { + if (bRelease){ + VPCUtil::vpc_img_release(ss->second.snapShot); + VPCUtil::vpc_img_release(ss->second.snapShotLittle); + } + total_snapshot_info.erase(ss++); + } + else ss++; + } + return; +} + + +void snapshot_reprocessing::release_village_finished_locus_snapshot(const string taskid, const int obj_id, bool bRelease) +{ + LOG_DEBUG("task_id {} delete obj_id {}", taskid, obj_id); //221026 + if (obj_id != -1) + { + OBJ_KEY cur_key = { taskid , obj_id }; + auto it = total_village_snapshot_info.find(cur_key); + if (it == total_village_snapshot_info.end()){ + return; + } + + if (bRelease){ + for (int i = 0; i < 3; i++) { + OBJ_VALUE ss = total_village_snapshot_info[cur_key].snapShots[i]; + VPCUtil::vpc_img_release(ss.snapShot); + VPCUtil::vpc_img_release(ss.snapShotLittle); + } + + } + + total_village_snapshot_info.erase(cur_key); + return; + } + + for(auto ss = total_village_snapshot_info.begin(); ss != total_village_snapshot_info.end();) + { + if (strcmp(ss->first.video_id.c_str(), taskid.c_str()) == 0) + { + if (bRelease){ + for (int i = 0; i < 3; i++) { + VPCUtil::vpc_img_release(ss->second.snapShots[i].snapShot); + VPCUtil::vpc_img_release(ss->second.snapShots[i].snapShotLittle); + } + } + total_village_snapshot_info.erase(ss++); + } + else ss++; + } + return; +} + + +map snapshot_reprocessing::get_total_face_snapshot_info(){ + return total_face_snapshot_info; +} + +void snapshot_reprocessing::release_finished_face_locus_snapshot(const string taskid, const int obj_id, bool bRelease) { + + LOG_DEBUG("task_id {} delete obj_id {}", taskid, obj_id); //221026 + if (obj_id != -1) { + OBJ_KEY cur_key = { taskid , obj_id }; + auto it = total_face_snapshot_info.find(cur_key); + if (it == total_face_snapshot_info.end()){ + return; + } + + if (bRelease){ + OBJ_VALUE ss = total_face_snapshot_info[cur_key]; + + VPCUtil::vpc_img_release(ss.snapShot); + VPCUtil::vpc_img_release(ss.snapShotLittle); + } + + total_face_snapshot_info.erase(cur_key); + return; + } + + for(auto ss = total_face_snapshot_info.begin(); ss != total_face_snapshot_info.end();) { if (strcmp(ss->first.video_id.c_str(), taskid.c_str()) == 0) { @@ -375,7 +903,9 @@ void snapshot_reprocessing::release_finished_locus_snapshot(const string taskid, VPCUtil::vpc_img_release(ss->second.snapShot); VPCUtil::vpc_img_release(ss->second.snapShotLittle); } - total_snapshot_info.erase(ss); + total_face_snapshot_info.erase(ss++); } + else ss++; } + return; } \ No newline at end of file diff --git a/src/reprocessing_module/snapshot_reprocessing.h b/src/reprocessing_module/snapshot_reprocessing.h index 836b45a..3171da8 100644 --- a/src/reprocessing_module/snapshot_reprocessing.h +++ b/src/reprocessing_module/snapshot_reprocessing.h @@ -54,7 +54,11 @@ struct OBJ_VALUE { float yaw = 0.0; float pitch = 0.0; //------------------------------- +}; +struct OBJ_VALUES { + OBJ_VALUE snapShots[3]; //缓存三张抓拍图 0-轨迹首张 1-轨迹最佳 2-轨迹末张 + bool exists[3] = {false, false, false}; //标识对应抓拍图是否存在 }; class snapshot_reprocessing @@ -72,13 +76,24 @@ public: void update_bestsnapshot(vector vec_devMem, vector &ol_det_result, vector>& delete_object_id); map get_total_snapshot_info(); - void release_finished_locus_snapshot(const string taskid, const int obj_id, bool bRelease); + int update_face_bestsnapshot(vector vec_devMem, vector &ol_det_result, vector>& delete_object_id); + map get_total_face_snapshot_info(); + + void update_village_bestsnapshot(vector vec_devMem, vector &ol_det_result, vector>& delete_object_id); + map get_total_village_snapshot_info(); + + void release_finished_locus_snapshot(const string taskid, const int objid = -1, bool bRelease = true); //-1为删除该路所有任务的快照图 + void release_village_finished_locus_snapshot(const string taskid, const int objid = -1, bool bRelease = true); + void release_finished_face_locus_snapshot(const string taskid, const int objid = -1, bool bRelease = true); private: bool best_snapshot_judge_algor(const OBJ_KEY& obj_key, const OBJ_VALUE& obj_value, int left, int top, int width, int height, int image_width, int image_height); + bool best_face_snapshot_judge_algor_v2(const OBJ_KEY& obj_key, const OBJ_VALUE& obj_value, int left, int top, int width, int height, int image_width, int image_height, float roll, float yaw, float pitch); private: map total_snapshot_info; + map total_face_snapshot_info; + map total_village_snapshot_info; map> algor_index_table; task_param_manager *m_task_param_manager; diff --git a/src/util/common_tool.cpp b/src/util/common_tool.cpp new file mode 100644 index 0000000..a73b21d --- /dev/null +++ b/src/util/common_tool.cpp @@ -0,0 +1,24 @@ +#include "common_tool.h" + + +namespace common { + + bool is_intersect(jxline myline1, jxline myline2) + { + // 快速排斥实验 + if (myline1.get_max_x() < myline2.get_min_x() || + myline2.get_max_x() < myline1.get_min_x() || + myline1.get_max_y() < myline2.get_min_y() || + myline2.get_max_y() < myline1.get_min_y()) + return false; + + // 跨立实验(叉积异号) + if (((((float)myline1.xa - (float)myline2.xa)*((float)myline2.yb - (float)myline2.ya) - ((float)myline1.ya - (float)myline2.ya)*((float)myline2.xb - (float)myline2.xa))* + (((float)myline1.xb - (float)myline2.xa)*((float)myline2.yb - (float)myline2.ya) - ((float)myline1.yb - (float)myline2.ya)*((float)myline2.xb - (float)myline2.xa))) > 0 || + ((((float)myline2.xa - (float)myline1.xa)*((float)myline1.yb - (float)myline1.ya) - ((float)myline2.ya - (float)myline1.ya)*((float)myline1.xb - (float)myline1.xa))* + (((float)myline2.xb - (float)myline1.xa)*((float)myline1.yb - (float)myline1.ya) - ((float)myline2.yb - (float)myline1.ya)*((float)myline1.xb - (float)myline1.xa))) > 0) + return false; + + return true; + } +} diff --git a/src/util/common_tool.h b/src/util/common_tool.h new file mode 100644 index 0000000..16ae420 --- /dev/null +++ b/src/util/common_tool.h @@ -0,0 +1,43 @@ +#ifndef __COMMON_TOOL_H__ +#define __COMMON_TOOL_H__ + + +struct jxline +{ + int xa; + int ya; + int xb; + int yb; + + jxline() {} + jxline(int xa, int ya, int xb, int yb) + { + this->xa = xa; + this->ya = ya; + this->xb = xb; + this->yb = yb; + } + int get_max_x() + { + return xa > xb ? xa : xb; + } + int get_min_x() + { + return xa > xb ? xb : xa; + } + int get_max_y() + { + return ya > yb ? ya : yb; + } + int get_min_y() + { + return ya > yb ? yb : ya; + } +}; + +namespace common { + bool is_intersect(jxline myline1, jxline myline2); +} + + +#endif \ No newline at end of file -- libgit2 0.21.4