123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- /*
- * @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> InfineFilter::getPtr(){
- static std::shared_ptr<InfineFilter> m_infineFilter = nullptr;
- if(m_infineFilter == nullptr) m_infineFilter = std::shared_ptr<InfineFilter>(new InfineFilter);
- return m_infineFilter;
- }
- /**
- * @description: 判定结果
- * @param {*}
- * @return {*}
- */
- int8_t InfineFilter::judgementResult(std::shared_ptr<CNStreamInferData>& 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>& cnStreamInferData){
- if(this->bboxSize == 0) return OK;
- vector<std::vector<InferInfo>::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>& 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>& cnStreamInferData){
- static std::shared_ptr<CNStreamInferData> 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> ticker = nullptr;
- if(ticker == nullptr) {
- ticker = std::make_shared<Ticker>();
- 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>& cnStreamInferData){
- // 历史检查
- this->HistoricalCheck();
- auto task = [&](){
- HistoryData historyData;
- historyData.ticker = std::make_shared<Ticker>();
- historyData.CnStreamInferData = std::make_shared<CNStreamInferData>();
- 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<vector<HistoryData>::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>& cnStreamInferData){
- this->SimilarityCheck();
- auto task = [&](){
- HistoryData historyData;
- historyData.CnStreamInferData = std::make_shared<CNStreamInferData>();
- 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<vector<InferInfo>::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<Ticker>();
- 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<Ticker>();
- 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>& cnStreamInferData){
- static queue<HistoryData> nx_latestDatas;
- auto task = [&](){
- HistoryData historyData;
- historyData.CnStreamInferData = std::make_shared<CNStreamInferData>();
- 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<vector<InferInfo>::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<Ticker>();
- 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<Ticker>();
- 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>& 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
|