/* * @Description: * @Version: 1.0 * @Autor: lishengyin * @Date: 2022-03-09 10:58:34 * @LastEditors: lishengyin * @LastEditTime: 2022-09-21 14:14:27 */ #include "InfineFilter.hpp" namespace gsd { /** * @description: 获取ptr * @param {*} * @return {*} */ std::shared_ptr InfineFilter::getPtr(){ static std::shared_ptr m_infineFilter = nullptr; if(m_infineFilter == nullptr) m_infineFilter = std::shared_ptr(new InfineFilter); return m_infineFilter; } /** * @description: 判定结果 * @param {*} * @return {*} */ int8_t InfineFilter::judgementResult(std::shared_ptr& cnStreamInferData){ int8_t result = ERR; // 过滤小目标 MinBBoxFilter(cnStreamInferData); int result1; int result2; switch (filterLevel) { case 0: result = OK; break; case 1: result = this->LastOneJudgment(cnStreamInferData); break; case 2: result1 = this->IntervalJudgment(); result2 = this->LastOneJudgment(cnStreamInferData); result = (result1 == OK && result2 == OK ? OK : ERR); break; case 3: result = this->LastOneJudgment(cnStreamInferData); if(result == ERR) break; this->SimilarityJudgment(cnStreamInferData); if(cnStreamInferData->Objects.size() == 0) result = ERR; break; default: break; } return result; } /** * @description: 最小BBox过滤器 * @return {*} */ int8_t InfineFilter::MinBBoxFilter(std::shared_ptr& cnStreamInferData){ if(this->bboxSize == 0) return OK; vector::iterator> ret; for(auto iter = cnStreamInferData->Objects.begin(); iter != cnStreamInferData->Objects.end(); iter++){ double t = (iter->BBox.h * (double)cnStreamInferData->width) * (iter->BBox.w * (double)1920); if(t < (double)bboxSize) ret.push_back(iter); } for(auto iter = ret.begin(); iter != ret.end(); iter++){ cnStreamInferData->Objects.erase(*iter); } return OK; } /** * @description: 获取是否相似 * @param {InferInfo} infer1 * @param {InferInfo} infer2 * @return {*} */ int8_t InfineFilter::CalculateSimilarity(InferInfo& infer1, InferInfo& infer2, std::shared_ptr& cnStreamInferData){ // Label if(infer1.Label != infer2.Label) return ERR; // Source // BBOX // double difference = fabs(infer1.BBox.x - infer2.BBox.x); // if(difference > 10) return ERR; // difference = fabs(infer1.BBox.y - infer2.BBox.y ); // if(difference > 10) return ERR; // difference = fabs(infer1.BBox.w - infer2.BBox.w ); // if(difference > 10) return ERR; // difference = fabs(infer1.BBox.h - infer2.BBox.h ); // if(difference > 10) return ERR; auto result = this->getIou(infer1, infer2, cnStreamInferData); if(result < 0.5) return ERR; return OK; } /** * @description: 设置灵敏度 * @param {int} FilterLevel * @return {*} */ int8_t InfineFilter::setFilterLevel(int FilterLevel){ if(filterLevel < 0 || filterLevel > 3) return ERR; this->filterLevel = FilterLevel; return OK; } /** * @description: 设置时间间隔 * @param {int} Interval * @return {*} */ int8_t InfineFilter::setInterval(int Interval){ if(Interval < 0 || Interval > 60000) return ERR; this->interval = Interval; return OK; } /** * @description: 设置超时时间 * @param {int} timeOut * @return {*} */ int8_t InfineFilter::setTimeOut(int timeOut){ if(timeOut < 0) return ERR; this->TimeOut = timeOut; return OK; } /** * @description: 与上一次的结果判断 * @param {*} * @return {*} */ int8_t InfineFilter::LastOneJudgment(std::shared_ptr& cnStreamInferData){ static std::shared_ptr old = nullptr; if(cnStreamInferData->Objects.size() == 0) return OK; if(old == nullptr) { old = cnStreamInferData; return OK; } // 判断是否为同一个视频内 if(old->videoPath == cnStreamInferData->videoPath){ // 分析结果数量 int num = 0; if(old->Objects.size() == cnStreamInferData->Objects.size()){ for(auto iter1 = old->Objects.begin(); iter1 != old->Objects.end(); iter1++){ for(auto iter2 = cnStreamInferData->Objects.begin(); iter2 != cnStreamInferData->Objects.end(); iter2++){ if(CalculateSimilarity(*iter1, *iter2, cnStreamInferData) == OK) num++; } } } if(num == old->Objects.size() && num != 0) { return ERR; } } if(cnStreamInferData->Objects.size() != 0) old = cnStreamInferData; return OK; } /** * @description: 时间间隔判定 * @param {*} * @return {*} */ int8_t InfineFilter::IntervalJudgment(){ static std::shared_ptr ticker = nullptr; if(ticker == nullptr) { ticker = std::make_shared(); return OK; } if(ticker->elapsedTime() >= config::getPtr()->InferInterval){ ticker->resetTime(); return OK; } return ERR; } /** * @description: 历史判定 * @param {*} * @return {*} */ int8_t InfineFilter::HistoricalJudgment(std::shared_ptr& cnStreamInferData){ // 历史检查 this->HistoricalCheck(); auto task = [&](){ HistoryData historyData; historyData.ticker = std::make_shared(); historyData.CnStreamInferData = std::make_shared(); historyData.CnStreamInferData->StreamName = cnStreamInferData->StreamName; historyData.CnStreamInferData->FrameCount = cnStreamInferData->FrameCount; historyData.CnStreamInferData->width = cnStreamInferData->width; historyData.CnStreamInferData->height = cnStreamInferData->height; historyData.CnStreamInferData->Objects = cnStreamInferData->Objects; historyData.CnStreamInferData->videoPath = cnStreamInferData->videoPath; this->HistoryDatas.push_back(historyData); }; if(HistoryDatas.empty()){ task(); return OK; } for(auto iter = HistoryDatas.begin(); iter != HistoryDatas.end(); iter++){ int num = 0; if(iter->CnStreamInferData->Objects.size() == cnStreamInferData->Objects.size()){ for(auto iter1 = iter->CnStreamInferData->Objects.begin(); iter1 != iter->CnStreamInferData->Objects.end(); iter1++){ for(auto iter2 = cnStreamInferData->Objects.begin(); iter2 != cnStreamInferData->Objects.end(); iter2++){ if(CalculateSimilarity(*iter1, *iter2, cnStreamInferData) == OK) num++; } } } if(num == iter->CnStreamInferData->Objects.size()) { iter->ticker->resetTime(); return ERR; } } task(); return OK; } /** * @description: 历史检查 * @param {*} * @return {*} */ void InfineFilter::HistoricalCheck(){ if(filterLevel != 3) return; vector::iterator> ret; for(auto iter = this->HistoryDatas.begin(); iter != this->HistoryDatas.end(); iter++){ if(iter->ticker != nullptr && iter->ticker->elapsedTime() > TimeOut){ ret.push_back(iter); } } if(ret.empty()) return; for(auto iter = ret.begin(); iter != ret.end(); iter++){ this->HistoryDatas.erase(*iter); } } /** * @description: 相似度对比 * @return {*} */ int8_t InfineFilter::SimilarityJudgment(std::shared_ptr& cnStreamInferData){ this->SimilarityCheck(); auto task = [&](){ HistoryData historyData; historyData.CnStreamInferData = std::make_shared(); historyData.CnStreamInferData->StreamName = cnStreamInferData->StreamName; historyData.CnStreamInferData->FrameCount = cnStreamInferData->FrameCount; historyData.CnStreamInferData->width = cnStreamInferData->width; historyData.CnStreamInferData->height = cnStreamInferData->height; historyData.CnStreamInferData->Objects = cnStreamInferData->Objects; historyData.CnStreamInferData->videoPath = cnStreamInferData->videoPath; LatestDatas.push(historyData); if(LatestDatas.size() >= 3) LatestDatas.pop(); }; if(LatestDatas.empty()){ task(); return OK; } auto iter_front = LatestDatas.front(); vector::iterator> result; bool IsResult = false; // 对比前两帧 for(auto iter = cnStreamInferData->Objects.begin(); iter != cnStreamInferData->Objects.end(); iter++){ IsResult = false; for(auto iter1 : iter_front.CnStreamInferData->Objects){ if(CalculateSimilarity(*iter, iter1, cnStreamInferData) == OK){ SimilarityData data; data.ticker = std::make_shared(); data.info = *iter; this->SimilarityDatas.push_back(data); result.push_back(iter); IsResult = true; break; } } if(IsResult) continue; if(LatestDatas.size() <= 1) continue; auto iter_back = LatestDatas.back(); for(auto iter1 : iter_back.CnStreamInferData->Objects){ if(CalculateSimilarity(*iter, iter1, cnStreamInferData) == OK){ SimilarityData data; data.ticker = std::make_shared(); data.info = *iter; this->SimilarityDatas.push_back(data); result.push_back(iter); break; } } } for(auto iter = result.begin(); iter != result.end(); iter++){ cnStreamInferData->Objects.erase(*iter); } result.clear(); // 对比相似库 for(auto iter = cnStreamInferData->Objects.begin(); iter != cnStreamInferData->Objects.end(); iter++){ for(auto iter1 = this->SimilarityDatas.begin(); iter1 != this->SimilarityDatas.end(); iter1++){ if(CalculateSimilarity(*iter, iter1->info, cnStreamInferData) == OK){ iter1->info = *iter; iter1->ticker->resetTime(); result.push_back(iter); break; } } } // clear for(auto iter = result.begin(); iter != result.end(); iter++){ cnStreamInferData->Objects.erase(*iter); } task(); return OK; } /** * @description: 相似库对比 * @return {*} */ int8_t InfineFilter::SimilarityResult(std::shared_ptr& cnStreamInferData){ static queue nx_latestDatas; auto task = [&](){ HistoryData historyData; historyData.CnStreamInferData = std::make_shared(); historyData.CnStreamInferData->StreamName = cnStreamInferData->StreamName; historyData.CnStreamInferData->FrameCount = cnStreamInferData->FrameCount; historyData.CnStreamInferData->width = cnStreamInferData->width; historyData.CnStreamInferData->height = cnStreamInferData->height; historyData.CnStreamInferData->Objects = cnStreamInferData->Objects; historyData.CnStreamInferData->videoPath = cnStreamInferData->videoPath; nx_latestDatas.push(historyData); if(nx_latestDatas.size() >= 3) nx_latestDatas.pop(); }; vector::iterator> result; if(nx_latestDatas.empty()){ task(); if(this->SimilarityDatas.empty()) return OK; } else{ bool IsResult = false; auto iter_front = nx_latestDatas.front(); for(auto iter = cnStreamInferData->Objects.begin(); iter != cnStreamInferData->Objects.end(); iter++){ IsResult = false; for(auto iter1 : iter_front.CnStreamInferData->Objects){ if(CalculateSimilarity(*iter, iter1, cnStreamInferData) == OK){ SimilarityData data; data.ticker = std::make_shared(); data.info = *iter; this->SimilarityDatas.push_back(data); result.push_back(iter); IsResult = true; break; } } if(IsResult) continue; if(nx_latestDatas.size() <= 1) continue; auto iter_back = nx_latestDatas.back(); for(auto iter1 : iter_back.CnStreamInferData->Objects){ if(CalculateSimilarity(*iter, iter1, cnStreamInferData) == OK){ SimilarityData data; data.ticker = std::make_shared(); data.info = *iter; this->SimilarityDatas.push_back(data); result.push_back(iter); break; } } } for(auto iter = result.begin(); iter != result.end(); iter++){ cnStreamInferData->Objects.erase(*iter); } result.clear(); task(); } if(this->SimilarityDatas.empty()) return OK; for(auto iter = cnStreamInferData->Objects.begin(); iter != cnStreamInferData->Objects.end(); iter++){ for(auto iter1 = this->SimilarityDatas.begin(); iter1 != this->SimilarityDatas.end(); iter1++){ if(CalculateSimilarity(*iter, iter1->info, cnStreamInferData) == OK){ iter1->info = *iter; iter1->ticker->resetTime(); result.push_back(iter); break; } } } if(result.empty()) return OK; // clear for(auto iter = result.begin(); iter != result.end(); iter++){ cnStreamInferData->Objects.erase(*iter); } return OK; } /** * @description: 时间对比 * @return {*} */ void InfineFilter::SimilarityCheck(){ if(filterLevel != 3) return; for(auto iter = this->SimilarityDatas.begin(); iter != this->SimilarityDatas.end();){ if(iter->ticker != nullptr && iter->ticker->elapsedTime() > TimeOut){ iter = this->SimilarityDatas.erase(iter); }else iter++; } } /** * @description: 获取Iou * @return {*} */ float InfineFilter::getIou(InferInfo infer1, InferInfo infer2,std::shared_ptr& cnStreamInferData){ int max_x = std::max(infer1.BBox.x * cnStreamInferData->width, infer2.BBox.x * cnStreamInferData->width); int min_x = std::min((infer1.BBox.x + infer1.BBox.w) * cnStreamInferData->width , (infer2.BBox.x + infer2.BBox.w) * cnStreamInferData->width); int max_y = std::max(infer1.BBox.y * cnStreamInferData->height, infer2.BBox.y * cnStreamInferData->height); int min_y = std::min((infer1.BBox.y + infer1.BBox.h) * cnStreamInferData->height, (infer2.BBox.y + infer2.BBox.h) * cnStreamInferData->height); if(min_x <= max_x || min_y <= max_y) return 0; float over_area = (min_x - max_x) * (min_y - max_y); // 计算重叠面积 float area_a = (infer1.BBox.w * cnStreamInferData->width) * (infer1.BBox.h * cnStreamInferData->height); float area_b = (infer2.BBox.w * cnStreamInferData->width) * (infer2.BBox.h * cnStreamInferData->height); float iou = over_area / (area_a + area_b - over_area); return iou; } } // namespace gsd