123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- #include "AbandObjApp.h"
- #include "DetUtils.h"
- NAMESPACE_MAS_BEGIN
- NAMESPACE_ABANDOBJ_BEGIN
- tzc::Mutex AbandObjApp::_mutex;
- AbandObjApp* AbandObjApp::_instance = nullptr;
- AbandObjApp* AbandObjApp::Instance()
- {
- if (!_instance)
- {
- _mutex.Lock();
- if (!_instance)
- {
- _instance = new AbandObjApp();
- TZLogInfo("AbandObjApp Instance created~~~");
- }
- _mutex.Unlock();
- }
- ++(_instance->m_usecnt);
- return _instance;
- }
- void AbandObjApp::DestroyInstance()
- {
- tzc::ScopedLock lock(_mutex);
- if ((_instance->m_usecnt) < 0)
- {
- TZLogWarn("AbandObjApp Instance does not exist!!!");
- _instance->m_usecnt = 0;
- }
- else if ((_instance->m_usecnt) == 0)
- {
- TZ_delete(_instance);
- TZLogInfo("AbandObjApp Instance destroyed~~~");
- }
- else
- {
- TZLogWarn("AbandObjApp still in use by %d objects!", _instance->m_usecnt);
- TZ_delete(_instance);
- TZLogInfo("AbandObjApp Instance destroyed~~~");
- }
- }
- TZ_INT AbandObjApp::Initialize(const std::string& initParam)
- {
- if (m_inited)
- {
- TZLogInfo("AbandObjApp has been initialized~~~");
- return MEC_OK;
- }
- AbandObjBuild buildParam;
- AbandObjBuild::fromJson(initParam, buildParam);
- m_factor = buildParam.factor;
- m_shortTermRate = buildParam.short_term_rate;
- m_shortTermHistory = buildParam.short_term_history;
- m_longTermRate = buildParam.long_term_rate;
- m_longTermHistory = buildParam.long_term_history;
- m_varThreshold = buildParam.var_threshold;
- m_detectShadows = buildParam.detect_shadows;
- m_iouThreshold = buildParam.iou_threshold;
- m_areaThreshold = buildParam.area_threshold;
- m_perimeterThreshold = buildParam.perimeter_threshold;
- if (buildParam.algo == "MOG2")
- {
- m_pLongBG = cv::createBackgroundSubtractorMOG2(m_longTermHistory,
- m_varThreshold,
- m_detectShadows);
- m_pShortBG = cv::createBackgroundSubtractorMOG2(m_shortTermHistory,
- m_varThreshold,
- m_detectShadows);
- }
- else
- {
- TZLogError("Invalid algorithm name!!!");
- return MEC_FAILED;
- }
- m_inited = TRUE;
- TZLogInfo("AbandObjApp Initialized~~~");
- return MEC_OK;
- }
- TZ_INT AbandObjApp::SetDetectCfg(const std::string& initParam)
- {
- AbandObjCfg cfgParam;
- AbandObjCfg::fromJson(initParam, cfgParam);
- m_factor = cfgParam.factor;
- m_shortTermRate = cfgParam.short_term_rate;
- m_shortTermHistory = cfgParam.short_term_history;
- m_longTermRate = cfgParam.long_term_rate;
- m_longTermHistory = cfgParam.long_term_history;
- m_varThreshold = cfgParam.var_threshold;
- m_detectShadows = cfgParam.detect_shadows;
- m_iouThreshold = cfgParam.iou_threshold;
- m_areaThreshold = cfgParam.area_threshold;
- m_perimeterThreshold = cfgParam.perimeter_threshold;
- if (cfgParam.algo == "MOG2")
- {
- m_pLongBG = cv::createBackgroundSubtractorMOG2(m_longTermHistory,
- m_varThreshold,
- m_detectShadows);
- m_pShortBG = cv::createBackgroundSubtractorMOG2(m_shortTermHistory,
- m_varThreshold,
- m_detectShadows);
- }
- else
- {
- TZLogError("Invalid algorithm name!!!");
- return MEC_FAILED;
- }
- return MEC_OK;
- }
- TZ_INT AbandObjApp::Dispose()
- {
- if (!m_inited)
- {
- return MEC_NOT_INITED;
- }
- _mutex.Lock();
- --(m_usecnt);
- TZLogInfo("AbandObjApp usecnt -1, now = %d~~~", m_usecnt);
- TZ_BOOL empty = (m_usecnt == 0);
- _mutex.Unlock();
- if (empty)
- {
- m_inited = FALSE;
- TZLogInfo("AbandObjApp Dispose~~~");
- this->DestroyInstance();
- }
- return MEC_OK;
- }
- TZ_INT AbandObjApp::DoDetect(cv::Mat& input, std::vector<Proposal>& propRes)
- {
- cv::Mat image;
- cv::resize(input, image, cv::Size(input.cols / m_factor, input.rows / m_factor));
- cv::Mat ltMask, stMask, subMask;
- // 高斯模糊
- cv::GaussianBlur(image, image, cv::Size(5, 5), 0);
- // 转换为灰度图
- cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
- // 更新背景模型并获取前景掩码
- m_pLongBG->apply(image, ltMask, m_longTermRate);
- m_pShortBG->apply(image, stMask, m_shortTermRate);
- // 计算长期掩码减去短期掩码,得到差分掩码
- cv::subtract(ltMask, stMask, subMask);
- // 对差分掩码进行去噪处理
- // 先腐蚀再膨胀(开操作)
- cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(5, 5));
- cv::erode(subMask, subMask, kernel, cv::Point(-1, -1), 2, 1, 1);
- kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
- cv::dilate(subMask, subMask, cv::Mat(), cv::Point(-1, -1), 2, 1, 1);
- // 高斯模糊进一步平滑掩码
- cv::GaussianBlur(subMask, subMask, cv::Size(49, 49), 7);
- // 将低于阈值的像素设为0,进一步清理噪点
- subMask.setTo(0, subMask <= 5);
- // 查找轮廓
- std::vector<std::vector<cv::Point>> contours;
- cv::findContours(subMask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
- // 遍历所有轮廓
- for (size_t i = 0; i < contours.size(); i++) {
- double area = cv::contourArea(contours[i]);
- double perimeter = cv::arcLength(contours[i], true);
- // 过滤掉面积或周长过小的轮廓
- if (area > m_areaThreshold && perimeter > m_perimeterThreshold) {
- // 绘制轮廓
- cv::drawContours(image, contours, i, cv::Scalar(0, 0, 255), 2);
- // 获取轮廓的边界矩形
- cv::Rect rect = cv::boundingRect(contours[i]);
- // 绘制矩形
- cv::rectangle(image, rect, cv::Scalar(0, 255, 0), 2);
- // 创建proposal对象
- Proposal p;
- p.x = rect.x * m_factor; // 恢复到原始尺寸
- p.y = rect.y * m_factor;
- p.w = rect.width * m_factor;
- p.h = rect.height * m_factor;
- p.life = 10; // 初始生命周期
- p.status = Active; // 初始状态
- // 检查当前proposal是否与已有proposal重叠
- for (size_t j = 0; j < m_proposals.size(); j++) {
- AreaBox boxA, boxB;
- boxA.LTX = p.x;
- boxA.LTY = p.y;
- boxA.RBX = p.x + p.w;
- boxA.RBY = p.y + p.h;
- boxB.LTX = m_proposals[j].x;
- boxB.LTY = m_proposals[j].y;
- boxB.RBX = m_proposals[j].x + m_proposals[j].w;
- boxB.RBY = m_proposals[j].y + m_proposals[j].h;
- if (!detutils::IsIoULeqThreshold(boxA, boxB, m_iouThreshold)) {
- p.status = Overlap; // 重叠,不添加新的proposal
- m_proposals[j].life++; // 延长已有proposal的生命周期
- if (m_proposals[j].status == Accepted){
- continue; // 已经进行过检测
- }
- m_proposals[j].status = Active; // 标记为需要检测的有效proposal
- }
- }
- // 如果没有与任何proposal重叠,则添加为新的proposal
- if (p.status == Active){
- m_proposals.push_back(p);
- }
- }
- }
- // 遍历所有proposal,更新其状态
- for (size_t i = 0; i < m_proposals.size(); i++) {
- if (m_proposals[i].status == Active) { // 需要检测的proposal
- if (m_proposals[i].life > 60) { // 生存超过60帧
- // 处理proposal区域
- //Mat roi = solve_proposal(origin_frame, proposals[i]);
- // TODO: 对roi进行CLIP视觉特征提取和结果保存
- propRes.push_back(m_proposals[i]);
- m_proposals[i].status = Accepted; // 标记为已检测
- }
- } else {
- // 减少proposal的生命周期
- m_proposals[i].life--;
- if (m_proposals[i].life == 0) {
- // 生命周期结束,删除proposal
- m_proposals.erase(m_proposals.begin() + i);
- i--; // 调整索引
- }
- }
- }
- return MEC_OK;
- }
- AbandObjApp::AbandObjApp()
- : m_inited(FALSE),
- m_usecnt(0) {}
- AbandObjApp::~AbandObjApp()
- {
- this->Dispose();
- }
- NAMESPACE_ABANDOBJ_END
- NAMESPACE_MAS_END
|