|
@@ -4,15 +4,15 @@
|
|
|
* @Autor: lishengyin
|
|
|
* @Date: 2022-03-22 14:00:46
|
|
|
* @LastEditors: lishengyin
|
|
|
- * @LastEditTime: 2022-07-21 14:17:36
|
|
|
+ * @LastEditTime: 2022-08-31 15:58:56
|
|
|
*/
|
|
|
#include "InfineFilter.h"
|
|
|
|
|
|
namespace cnstream{
|
|
|
|
|
|
bool InfineFilter::Open(cnstream::ModuleParamSet paramSet){
|
|
|
- if (paramSet.find("FilterId") != paramSet.end()) {
|
|
|
- std::string json = paramSet["FilterId"];
|
|
|
+ if (paramSet.find("labels") != paramSet.end()) {
|
|
|
+ std::string json = paramSet["labels"];
|
|
|
rapidjson::Document doc;
|
|
|
if (doc.Parse<rapidjson::kParseCommentsFlag>(json.c_str()).HasParseError()) {
|
|
|
return false;
|
|
@@ -79,6 +79,11 @@ namespace cnstream{
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @description: Process
|
|
|
+ * @param {shared_ptr<cnstream::CNFrameInfo>} data
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
int InfineFilter::Process(std::shared_ptr<cnstream::CNFrameInfo> data){
|
|
|
CNDataFramePtr frame = data->collection.Get<CNDataFramePtr>(kCNDataFrameTag);
|
|
|
if (frame->width < 0 || frame->height < 0) {
|
|
@@ -95,138 +100,151 @@ namespace cnstream{
|
|
|
this->TransmitData(data);
|
|
|
return 0;
|
|
|
}
|
|
|
+ cv::Mat img = frame->ImageBGR();
|
|
|
+ filter(img, objs_holder);
|
|
|
|
|
|
- // 异类过滤器
|
|
|
- this->AlienFilter(frame->ImageBGR(), objs_holder);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- // 过滤某些Id
|
|
|
- for(auto iter = objs_holder->objs_.begin(); iter != objs_holder->objs_.end(); ){
|
|
|
- std::shared_ptr<cnstream::CNInferObject> object = *iter;
|
|
|
- if (!object) continue;
|
|
|
- auto it = find(this->labels.begin(), this->labels.end(), object->id);
|
|
|
- if(it != this->labels.end()){
|
|
|
- iter = objs_holder->objs_.erase(iter);
|
|
|
- }else{
|
|
|
- iter++;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * @description: 过滤器 过滤器优先级: 比例过滤器 > 异类过滤器 > 夜间过滤器
|
|
|
+ * @param {Mat&} image
|
|
|
+ * @param {CNInferObjsPtr} objs_holder
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+ bool InfineFilter::filter(cv::Mat& image, CNInferObjsPtr objs_holder){
|
|
|
+
|
|
|
+ // 比例过滤器
|
|
|
+ if(this->proportionalFilter(image, objs_holder) == false) {
|
|
|
+ objs_holder->objs_.clear();
|
|
|
}
|
|
|
|
|
|
- if(!this->Night_Filter) return 0;
|
|
|
- if(!getNight()) return 0;
|
|
|
-
|
|
|
- // 过滤星星、月亮、飞机
|
|
|
+ // 异类过滤器
|
|
|
+ this->AlienFilter(objs_holder);
|
|
|
+
|
|
|
+ // 夜间过滤器
|
|
|
+ this->nightFilter(image, objs_holder);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @description: 异类过滤器 labels以外的定义为异物
|
|
|
+ * @param {CNInferObjsPtr&} objs_holder
|
|
|
+ * @return {*}
|
|
|
+ */
|
|
|
+ bool InfineFilter::AlienFilter(CNInferObjsPtr& objs_holder){
|
|
|
+ if(objs_holder->objs_.size() == 0 || labels.empty()) return false;
|
|
|
for(auto iter = objs_holder->objs_.begin(); iter != objs_holder->objs_.end();){
|
|
|
std::shared_ptr<cnstream::CNInferObject> object = *iter;
|
|
|
- if (!object) continue;
|
|
|
- if(!this->filter(frame->ImageBGR(), object)){
|
|
|
- iter = objs_holder->objs_.erase(iter);
|
|
|
- }else{
|
|
|
- iter++;
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
+ if(!object) continue;
|
|
|
+ auto it = find(labels.begin(), labels.end(),object->id);
|
|
|
+ if(it == this->labels.end()) objs_holder->objs_.erase(iter);
|
|
|
+ else iter++;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @description: 过滤器
|
|
|
- * @param {Mat} image
|
|
|
+ * @description: 比例过滤器
|
|
|
+ * @param {Mat&} image
|
|
|
+ * @param {CNInferObjsPtr} objs_holder
|
|
|
* @return {*}
|
|
|
*/
|
|
|
- bool InfineFilter::filter(cv::Mat image, std::shared_ptr<cnstream::CNInferObject>& object){
|
|
|
- cv::Mat img = image.clone();
|
|
|
- // 腐蚀
|
|
|
- erode(img, img, cv::Mat());
|
|
|
-
|
|
|
- cv::Rect rect = cv::Rect(object->bbox.x * image.cols,object->bbox.y * image.rows, object->bbox.w * image.cols, object->bbox.h * image.rows);
|
|
|
- cv::Mat dst = img(rect);
|
|
|
- cv::Mat imgThresholded;
|
|
|
- // 转换为二值图
|
|
|
- cv::inRange(dst, cv::Scalar(128, 128, 128), cv::Scalar(255, 255, 255), imgThresholded);
|
|
|
- cv::threshold(imgThresholded, imgThresholded, 1, 255, cv::THRESH_BINARY);
|
|
|
-
|
|
|
- // 寻找轮廓
|
|
|
- vector<vector<cv::Point>> contours;
|
|
|
- vector<cv::Vec4i> hierarchy;
|
|
|
- cv::findContours(imgThresholded, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
|
|
|
-
|
|
|
- if(contours.empty()) return true;
|
|
|
- // 获取最大轮廓
|
|
|
- double max_area = cv::contourArea(cv::InputArray(contours[0]), false);
|
|
|
- for(unsigned long long i = 1; i < contours.size(); i++){
|
|
|
- double temp_area = cv::contourArea(cv::InputArray(contours[i]), false);
|
|
|
- if(max_area < temp_area){
|
|
|
- max_area = temp_area;
|
|
|
+ bool InfineFilter::proportionalFilter(cv::Mat& image, CNInferObjsPtr objs_holder){
|
|
|
+ int target_num = 0, Alien_num = 0;
|
|
|
+ if(objs_holder->objs_.empty() || AlienLabels.empty() || labels.empty()) return true;
|
|
|
+ for(auto iter = objs_holder->objs_.begin(); iter != objs_holder->objs_.end(); iter++){
|
|
|
+ std::shared_ptr<cnstream::CNInferObject> object = *iter;
|
|
|
+ auto it = find(labels.begin(), labels.end(), object->id);
|
|
|
+ if(it != this->labels.end()){
|
|
|
+ target_num++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ it = find(AlienLabels.begin(), AlienLabels.end(), object->id);
|
|
|
+ if(it != this->AlienLabels.end()){
|
|
|
+ Alien_num++;
|
|
|
}
|
|
|
}
|
|
|
- double b = max_area / (object->bbox.w * image.cols * object->bbox.h * image.rows);
|
|
|
- // 计算轮廓比例
|
|
|
- if(b > 0.5){
|
|
|
- if(saveFilterResult){
|
|
|
+ double Proportion = (double)Alien_num / (double)(target_num + Alien_num);
|
|
|
+ if(Proportion < Proportion_th) return true;
|
|
|
+ if(this->saveFilterResult){
|
|
|
+ cv::Mat img = image.clone();
|
|
|
+ for(auto iter = objs_holder->objs_.begin(); iter != objs_holder->objs_.end(); iter++){
|
|
|
+ std::shared_ptr<cnstream::CNInferObject> object = *iter;
|
|
|
cv::Point top_left;
|
|
|
cv::Point bottom_right;
|
|
|
top_left.x = object->bbox.x * image.cols;
|
|
|
top_left.y = object->bbox.y * image.rows;
|
|
|
bottom_right.x = top_left.x + (object->bbox.w * image.cols);
|
|
|
bottom_right.y = top_left.y + (object->bbox.h * image.rows);
|
|
|
- cv::Point logo_pos(5, image.rows - 5);
|
|
|
+ cv::Point logo_pos(top_left.x - 5, bottom_right.y- 5);
|
|
|
cv::Scalar color(200, 200, 200);
|
|
|
- cv::putText(img, std::to_string(b), logo_pos, 0, 1, color, 2);
|
|
|
+ cv::putText(img, object->id, logo_pos, 0, 1, color, 2);
|
|
|
cv::rectangle(img, top_left, bottom_right, cv::Scalar(0, 255, 0), 4);
|
|
|
- if(opendir(this->files.c_str()) == NULL){
|
|
|
- mkdir((this->files).c_str(),S_IRWXU|S_IRWXG|S_IRWXO);
|
|
|
- }
|
|
|
- cv::imwrite(this->files + getTime() + ".jpg", img);
|
|
|
}
|
|
|
- return false;
|
|
|
+ cv::resize(img, img, cv::Size(960, 540));
|
|
|
+ std::string Dir = this->files + "/proportionalFilter/";
|
|
|
+ if(opendir(Dir.c_str()) == NULL){
|
|
|
+ mkdir((Dir).c_str(),S_IRWXU|S_IRWXG|S_IRWXO);
|
|
|
+ }
|
|
|
+ cv::imwrite(Dir + getTime() + ".jpg", img);
|
|
|
}
|
|
|
- return true;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @description: 异类过滤器
|
|
|
- * @param {Mat} image
|
|
|
+ * @description: 夜间过滤器
|
|
|
+ * @param {Mat&} image
|
|
|
+ * @param {CNInferObjsPtr} objs_holder
|
|
|
* @return {*}
|
|
|
- */
|
|
|
- bool InfineFilter::AlienFilter(cv::Mat image, CNInferObjsPtr& objs_holder){
|
|
|
- // 计算占比
|
|
|
- int num = 0;
|
|
|
- if(objs_holder->objs_.size() == 0) return true;
|
|
|
- for(auto iter = objs_holder->objs_.begin(); iter != objs_holder->objs_.end(); ){
|
|
|
+ */
|
|
|
+ bool InfineFilter::nightFilter(cv::Mat& image, CNInferObjsPtr objs_holder){
|
|
|
+ vector<CNInferBoundingBox> result;
|
|
|
+ if(objs_holder->objs_.size() == 0) return false;
|
|
|
+ if(!this->getNight()) return false;
|
|
|
+ cv::Mat img = image.clone();
|
|
|
+ cv::erode(img, img, cv::Mat());
|
|
|
+ for(auto iter = objs_holder->objs_.begin(); iter != objs_holder->objs_.end();){
|
|
|
std::shared_ptr<cnstream::CNInferObject> object = *iter;
|
|
|
- if (!object) continue;
|
|
|
- auto it = find(this->AlienLabels.begin(), this->AlienLabels.end(), object->id);
|
|
|
- if(it != this->AlienLabels.end()){
|
|
|
- num++;
|
|
|
- }
|
|
|
- }
|
|
|
- double Proportion = (double)num / (double)(objs_holder->objs_.size());
|
|
|
- if(Proportion > this->Proportion_th) {
|
|
|
- if(this->saveFilterResult){
|
|
|
- cv::Mat img = image.clone();
|
|
|
- for(auto iter = objs_holder->objs_.begin(); iter != objs_holder->objs_.end(); iter++){
|
|
|
- std::shared_ptr<cnstream::CNInferObject> object = *iter;
|
|
|
- if (!object) continue;
|
|
|
- cv::Point top_left;
|
|
|
- cv::Point bottom_right;
|
|
|
- top_left.x = object->bbox.x * image.cols;
|
|
|
- top_left.y = object->bbox.y * image.rows;
|
|
|
- bottom_right.x = top_left.x + (object->bbox.w * image.cols);
|
|
|
- bottom_right.y = top_left.y + (object->bbox.h * image.rows);
|
|
|
- cv::Point logo_pos(5, image.rows - 5);
|
|
|
- cv::Scalar color(200, 200, 200);
|
|
|
- cv::putText(img, object->id, logo_pos, 0, 1, color, 2);
|
|
|
- cv::rectangle(img, top_left, bottom_right, cv::Scalar(0, 255, 0), 4);
|
|
|
+ cv::Rect rect = cv::Rect(object->bbox.x * image.cols,object->bbox.y * image.rows, object->bbox.w * image.cols, object->bbox.h * image.rows);
|
|
|
+ cv::Mat dst = img(rect);
|
|
|
+ cv::Mat imgThresholded;
|
|
|
+ cv::inRange(dst, cv::Scalar(128, 128, 128), cv::Scalar(255, 255, 255), imgThresholded);
|
|
|
+ cv::threshold(imgThresholded, imgThresholded, 1, 255, cv::THRESH_BINARY);
|
|
|
+ vector<vector<cv::Point>> contours;
|
|
|
+ vector<cv::Vec4i> hierarchy;
|
|
|
+ cv::findContours(imgThresholded, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
|
|
|
+ if(contours.empty()) continue;
|
|
|
+ double max_area = cv::contourArea(cv::InputArray(contours[0]), false);
|
|
|
+ for(unsigned long long i = 1; i < contours.size(); i++){
|
|
|
+ double temp_area = cv::contourArea(cv::InputArray(contours[i]), false);
|
|
|
+ if(max_area < temp_area){
|
|
|
+ max_area = temp_area;
|
|
|
}
|
|
|
- if(opendir(this->files.c_str()) == NULL){
|
|
|
- mkdir((this->files).c_str(),S_IRWXU|S_IRWXG|S_IRWXO);
|
|
|
- }
|
|
|
- cv::imwrite(this->files + getTime() + "Alien.jpg", img);
|
|
|
}
|
|
|
+ double b = max_area / (object->bbox.w * image.cols * object->bbox.h * image.rows);
|
|
|
+ if(b > Night_th){
|
|
|
+ iter = objs_holder->objs_.erase(iter);
|
|
|
+ result.push_back(object->bbox);
|
|
|
+ }else iter++;
|
|
|
}
|
|
|
+ if(result.empty() || !this->saveFilterResult) return true;
|
|
|
+ for(auto iter = result.begin(); iter != result.end(); iter++){
|
|
|
+ cv::Point top_left;
|
|
|
+ cv::Point bottom_right;
|
|
|
+ bottom_right.x = top_left.x + (iter->w * image.cols);
|
|
|
+ bottom_right.y = top_left.y + (iter->h * image.rows);
|
|
|
+ cv::rectangle(img, top_left, bottom_right, cv::Scalar(0, 255, 0), 4);
|
|
|
+ }
|
|
|
+ cv::resize(img, img, cv::Size(960, 540));
|
|
|
+ if(opendir(this->files.c_str()) == NULL){
|
|
|
+ mkdir((this->files).c_str(),S_IRWXU|S_IRWXG|S_IRWXO);
|
|
|
+ }
|
|
|
+ cv::imwrite(this->files + getTime() + ".jpg", img);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* @description: 判断时间是否为晚上
|
|
|
* @param {*}
|