#include "PreProcessModel.h" #include // 获取当前时间并格式化为指定格式的字符串 std::string getCurrentDateTime1(const std::string& format) { // 获取当前时间 time_t now = time(0); // 转换为本地时间 tm* local_time = localtime(&now); // 定义存储时间字符串的缓冲区 char buffer[80]; // 格式化时间为字符串 strftime(buffer, sizeof(buffer), format.c_str(), local_time); // 返回格式化后的时间字符串 return std::string(buffer); } /// /// 根据提升机暂停和运动的比例,来最终判断是否运动 /// /// 0:运动 1:静止 -1:无法判断 int fnJudeRatio(std::queue quTSJ) { // 计算队列中 0 和 1 的数量 int count0 = 0;//运动个数 int count1 = 0;//静止个数 int queueSize = quTSJ.size(); // 队列长度 while (!quTSJ.empty()) { if (quTSJ.front() == 0) { count0++; } else { count1++; } quTSJ.pop(); } //cout << getCurrentDateTime1("%Y%m%d%H%M%S") << endl; /*cout << "------------" << endl; cout << count0 << endl; cout << count1 << endl;*/ // 计算比例 double ratio0 = static_cast(count0) / queueSize; double ratio1 = static_cast(count1) / queueSize; if (ratio0 > 0.6) { return 0; } else if (ratio1 > 0.6) { return 1; } else { return -1; } } int ToWchar(char* &src, wchar_t* &dest, const char *locale = "zh_CN.utf8") { if (src == NULL) { dest = NULL; return 0; } // 根据环境变量设置locale setlocale(LC_CTYPE, locale); // 得到转化为需要的宽字符大小 int w_size = mbstowcs(NULL, src, 0) + 1; // w_size = 0 说明mbstowcs返回值为-1。即在运行过程中遇到了非法字符(很有可能使locale // 没有设置正确) if (w_size == 0) { dest = NULL; return -1; } //wcout << "w_size" << w_size << endl; dest = new wchar_t[w_size]; if (!dest) { return -1; } int ret = mbstowcs(dest, src, strlen(src)+1); if (ret <= 0) { return -1; } return 0; } // 在图像上绘制带有背景的文本 void drawTextWithBackground(Mat& image, const string& text, int txalign, const Point& orgxy, const Point& orgwh, Scalar bgColor) { try { CvxText chinese = CvxText("SimHei.ttf"); //设置位置和字体参数 Scalar textColor(255, 255, 255);//白色文本 //Scalar bgColor(0, 255, 0);//绿色背景 int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX; double fontScale = 0.2; int thickness = 1; // 获取文字长度大小 Size textSize = getTextSize(text, fontFace, fontScale, thickness, 0); //计算文本背景矩形框的大小 //Rect backgroundRect(orgxy.x, orgxy.y - textSize.height - 30, orgwh.x, textSize.height + 30); if (text.length() >= 6) { Rect backgroundRect(orgxy.x, orgxy.y - textSize.height - 30, orgwh.x + textSize.width + 30, textSize.height + 30); //绘制文本背景 cv::rectangle(image, backgroundRect, bgColor, FILLED); } else { Rect backgroundRect(orgxy.x, orgxy.y - textSize.height - 30, orgwh.x, textSize.height + 30); //绘制文本背景 cv::rectangle(image, backgroundRect, bgColor, FILLED); } //绘制文本背景 //rectangle(image, backgroundRect, bgColor, FILLED); //CvxText chinese(ttfFont); //设置字体的大小 / 空白比例 / 间隔比较 / 旋转角度 //Scalar size(30, 0.5, 0, 0); Scalar size(25, 0, 0.1, 0); float p = 1.0f; //设置字体的透明度 //设置字体 chinese.setFont(nullptr, &size, nullptr, &p); switch (txalign) { case 1://文字左对齐 //绘制文本 //chinese.putText(image, text.c_str(), cv::Point(orgxy.x + 5, (orgxy.y - (orgwh.y / 2) - 2)), textColor); chinese.putText(image, text.c_str(), cv::Point(orgxy.x + 5, orgxy.y - 8), textColor); break; case 2://文字居中 //绘制文本 chinese.putText(image, text.c_str(), cv::Point(orgxy.x + 5 + (orgwh.x - textSize.width) / 2, (orgxy.y - 2)), textColor); break; case 3://文字右对齐 //绘制文本 chinese.putText(image, text.c_str(), cv::Point(orgxy.x + 5 + (orgwh.x - textSize.width), (orgxy.y - 2)), textColor); break; default://默认不支持中文 //绘制文本 putText(image, text.c_str(), cv::Point(orgxy.x + (orgwh.x - textSize.width) / 2, (orgxy.y - (orgwh.y / 2) - 2)), fontFace, 1, textColor, 2); break; } } catch (const std::exception& ex) { std::string errorMessage = "drawTextWithBackground-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } // 在图像上绘制带有背景的文本 void drawTextWithBackgroundWstr(Mat& image, const string& _text, int txalign, const Point& orgxy, const Point& orgwh, Scalar bgColor) { try { std::wstring_convert> converter; std::wstring text = converter.from_bytes(_text); CvxText chinese = CvxText("SimHei.ttf"); //设置位置和字体参数 Scalar textColor(255, 255, 255);//白色文本 //Scalar bgColor(0, 255, 0);//绿色背景 int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX; double fontScale = 0.2; int thickness = 1; // 获取文字长度大小 Size textSize = getTextSize(_text, fontFace, fontScale, thickness, 0); //计算文本背景矩形框的大小 //Rect backgroundRect(orgxy.x, orgxy.y - textSize.height - 30, orgwh.x, textSize.height + 30); if (text.length() >= 6) { Rect backgroundRect(orgxy.x, orgxy.y - textSize.height - 30, orgwh.x + textSize.width + 30, textSize.height + 30); //绘制文本背景 cv::rectangle(image, backgroundRect, bgColor, FILLED); } else { Rect backgroundRect(orgxy.x, orgxy.y - textSize.height - 30, orgwh.x, textSize.height + 30); //绘制文本背景 cv::rectangle(image, backgroundRect, bgColor, FILLED); } //绘制文本背景 //rectangle(image, backgroundRect, bgColor, FILLED); //CvxText chinese(ttfFont); //设置字体的大小 / 空白比例 / 间隔比较 / 旋转角度 //Scalar size(30, 0.5, 0, 0); Scalar size(25, 0, 0.1, 0); float p = 1.0f; //设置字体的透明度 //设置字体 chinese.setFont(nullptr, &size, nullptr, &p); switch (txalign) { case 1://文字左对齐 //绘制文本 //chinese.putText(image, text.c_str(), cv::Point(orgxy.x + 5, (orgxy.y - (orgwh.y / 2) - 2)), textColor); chinese.putText(image, text.c_str(), cv::Point(orgxy.x + 5, orgxy.y - 8), textColor); break; case 2://文字居中 //绘制文本 chinese.putText(image, text.c_str(), cv::Point(orgxy.x + 5 + (orgwh.x - textSize.width) / 2, (orgxy.y - 2)), textColor); break; case 3://文字右对齐 //绘制文本 chinese.putText(image, text.c_str(), cv::Point(orgxy.x + 5 + (orgwh.x - textSize.width), (orgxy.y - 2)), textColor); break; default://默认不支持中文 //绘制文本 putText(image, _text.c_str(), cv::Point(orgxy.x + (orgwh.x - textSize.width) / 2, (orgxy.y - (orgwh.y / 2) - 2)), fontFace, 1, textColor, 2); break; } } catch (const std::exception& ex) { std::string errorMessage = "drawTextWithBackground-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } //皮带运行状态检测 modelId = 1 double PreProcessModel::fnBeltMoveRec(Mat& imMat, std::vector& imagesBelt, int& beltCount, RUN& rBelt, std::vector vertices) { try { int result = 0;//0运行 1停止 -1未检查 //定义接受帧 cv::Mat frame = imMat; // 在视频帧上添加矩形框 rectangle(frame, cv::Point(vertices[0].x, vertices[0].y), cv::Point(vertices[1].x, vertices[1].y), cv::Scalar(255, 255, 0), 1); if (imagesBelt.size() >= 3)//长度大于3自动去掉头部帧 { imagesBelt.erase(imagesBelt.begin()); } if (imagesBelt.size() < 3 && (beltCount % 10 == 0))//取第间隔10帧取一次 { imagesBelt.push_back(frame); } if (imagesBelt.size() == 3)//取满3帧,调用模型 { //result = rBelt.detect(imagesBelt); imagesBelt.clear(); beltCount++; return result; } if (beltCount > 10000) beltCount = 0; beltCount = beltCount + 1; frame.release(); return -1; } catch (const std::exception& ex) { std::string errorMessage = "fnBeltMoveRec-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 提升机变动检测 modelId = 2 /// /// 视频流Mat /// 提升机用帧队列 /// 模型引用 double PreProcessModel::fnImRecProByModelTSJ(Mat& imMat, std::vector& imagesTsj, int& tsjCount, RUN& rTSJ, std::queue& quTSJ, std::vector vertices) { try { int lastresult = -1;//最终判断结果 0运行 1停止 -1 无法判断 int result = 0;//0运行 1停止 -1无法判断 //定义接受帧 cv::Mat frame = imMat; // 在视频帧上添加矩形框 rectangle(frame, cv::Point(vertices[0].x, vertices[0].y), cv::Point(vertices[1].x, vertices[1].y), cv::Scalar(255, 255, 0), 2); //if (imagesTsj.size() >= 3)//长度大于3自动去掉头部帧 //{ // imagesTsj.erase(imagesTsj.begin()); //} if (imagesTsj.size() < 3 && (tsjCount % 20 == 0))//取第间隔10帧取一次,帧率为15,间隔30帧,也就是2秒 { imagesTsj.push_back(frame); } if (imagesTsj.size() == 3)//取满3帧,调用模型 { result = rTSJ.detect(imagesTsj); std::string text; if (result == 0) { text = "run"; } else { text = "stop"; } //显示结果 cv::putText(frame, text, cv::Point(vertices[0].x, vertices[0].y - 5), 2, 4, cv::Scalar(255, 255, 255), 4); imagesTsj.clear(); tsjCount++; //把判断结果存入队列 if (quTSJ.size() < 30) { quTSJ.push(result); } else { //足够30个结果,就进行总判断处理 lastresult = fnJudeRatio(quTSJ); quTSJ.pop();//去掉头部第一个元素 } return lastresult;//返回结果 } if (tsjCount > 10000) tsjCount = 0; tsjCount = tsjCount + 1; frame.release(); return lastresult; } catch (const std::exception& ex) { imagesTsj.clear();// 清空帧容器 tsjCount = 0;// 计数归零 std::string errorMessage = "fnImRecProByModelTSJ-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 人员识别,安全帽识别 modelId = 3 /// /// 视频流Mat /// 模型引用 vector PreProcessModel::fnImRecProByModelHAT(Mat& imMat, HAT& hat, std::vector vertices, std::vector workvertices) { try { vector result; string titleperson = "人 员"; double distance = -1;//0:危险区域边界线上 >1:危险区域内 <1:危险区域外 double workdistance = -1;//0:工作区域边界线上 >1:工作区域内 <1:工作区域外 double workpersons = 0;//工作区域人的数量 double wearHat = 0;//0:全部佩戴安全帽 1:未佩戴安全帽的人的数量 //定义接受帧 cv::Mat frame = imMat; //获取视频帧的宽度和高度和帧率 int frame_width = frame.cols; int frame_height = frame.rows; double frameRate = 25; // 创建一个空的边界框向量 std::vector boxes; // 调用 detect 函数获取检测到的边界框 hat.detect(frame, boxes); //多边形区域 //std::vector vertices = stringToPoints(area); // 绘制多边形 cv::polylines(frame, vertices, true, cv::Scalar(0, 0, 255), 1); // 定义要测试的点 cv::Point testPoint; cv::Scalar sl;//标框颜色 // 使用索引遍历boxes for (int i = 0; i < boxes.size(); i++) { switch (boxes[i].class_id) { case 0: //如果标注了危险区域 if (vertices.size()>0) { distance = cv::pointPolygonTest(vertices, testPoint, false);//危险区域判断 if (distance > 0)//危险区域内有个人,画红色 { sl = Scalar(0, 0, 255); titleperson = "闯 入"; } else { sl = Scalar(0, 255, 0); titleperson = "人 员"; } } //如果标注了工作区域 if (workvertices.size()>0) { workdistance = cv::pointPolygonTest(workvertices, testPoint, false);//脱岗离岗判断 if (workdistance >= 0)//工作区域内有个人 { workpersons++; } } //标注人形 drawTextWithBackgroundWstr(frame, titleperson, 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sl); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sl, 1); break; //case 1: // //标注帽子 // drawTextWithBackgroundWstr(frame, "安全帽", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); // //在视频帧上添加矩形框 // rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); // break; case 2: //如果标注了工作区域 if (workvertices.size() > 0) { workdistance = cv::pointPolygonTest(workvertices, testPoint, false);//脱岗离岗判断 if (workdistance >= 0)//工作区域内有个人 { workpersons++; } } //wearHat++;//未佩戴安全帽的人的数量 //标注头部 drawTextWithBackgroundWstr(frame, "头", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); break; default: break; } } if (workpersons <= 0 && workvertices.size() > 0) { drawTextWithBackgroundWstr(frame,"离 岗", 2, cv::Point(workvertices[0].x, workvertices[0].y), cv::Point(workvertices[1].x - workvertices[0].x, workvertices[1].y - workvertices[0].y), Scalar(255, 255, 0)); // 绘制多边形,工作区域 cv::polylines(frame, workvertices, true, cv::Scalar(255, 255, 0), 2); } frame.release(); result.push_back(distance);//有人进入危险区域 result.push_back(wearHat);//未带安全帽人员数量 result.push_back(workpersons);//工作区域人员数量 return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelHAT-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } vector PreProcessModel::fnImRecProByModelHAT1(Mat& imMat, HAT& hat, std::vector vertices, std::vector workvertices,std::vector> c_list,std::string lable_title,std::string color_result) { try { vector result; string titleperson = "人 员"; double distance = -1;//0:危险区域边界线上 >1:危险区域内 <1:危险区域外 double workdistance = -1;//0:工作区域边界线上 >1:工作区域内 <1:工作区域外 double workpersons = 0;//工作区域人的数量 double wearHat = 0;//0:全部佩戴安全帽 1:未佩戴安全帽的人的数量 //定义接受帧 cv::Mat frame = imMat; //获取视频帧的宽度和高度和帧率 int frame_width = frame.cols; int frame_height = frame.rows; double frameRate = 25; // 创建一个空的边界框向量 std::vector boxes; // 调用 detect 函数获取检测到的边界框 hat.detect(frame, boxes); //多边形区域 //std::vector vertices = stringToPoints(area); // 绘制多边形 cv::polylines(frame, vertices, true, cv::Scalar(0, 0, 255), 1); drawTextWithBackgroundWstr(frame, lable_title, 1, cv::Point(vertices[0].x, vertices[0].y), cv::Point(150, 40), Scalar(c_list[0][0], c_list[0][1], c_list[0][2])); // 定义要测试的点 cv::Point testPoint; cv::Scalar sl;//标框颜色 // 使用索引遍历boxes for (int i = 0; i < boxes.size(); i++) { switch (boxes[i].class_id) { case 0: //如果标注了危险区域 if (vertices.size()>0) { distance = cv::pointPolygonTest(vertices, testPoint, false);//危险区域判断 if (distance > 0)//危险区域内有个人,画红色 { if(color_result == "false") { sl = Scalar(255, 0, 0); } else { sl = Scalar(0, 0, 255); } titleperson = "闯 入"; } else { if(color_result == "false") { sl = Scalar(255, 0, 0); } else { sl = Scalar(0, 0, 255); } titleperson = "人 员"; } } //如果标注了工作区域 if (workvertices.size()>0) { workdistance = cv::pointPolygonTest(workvertices, testPoint, false);//脱岗离岗判断 if (workdistance >= 0)//工作区域内有个人 { workpersons++; } } //标注人形 drawTextWithBackgroundWstr(frame, titleperson, 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sl); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sl, 1); break; //case 1: // //标注帽子 // drawTextWithBackgroundWstr(frame, "安全帽", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); // //在视频帧上添加矩形框 // rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); // break; case 2: //如果标注了工作区域 if (workvertices.size() > 0) { workdistance = cv::pointPolygonTest(workvertices, testPoint, false);//脱岗离岗判断 if (workdistance >= 0)//工作区域内有个人 { workpersons++; } } //wearHat++;//未佩戴安全帽的人的数量 //标注头部 drawTextWithBackgroundWstr(frame, "头", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); break; default: break; } } if (workpersons <= 0 && workvertices.size() > 0) { drawTextWithBackgroundWstr(frame,"离 岗", 2, cv::Point(workvertices[0].x, workvertices[0].y), cv::Point(workvertices[1].x - workvertices[0].x, workvertices[1].y - workvertices[0].y), Scalar(255, 255, 0)); // 绘制多边形,工作区域 cv::polylines(frame, workvertices, true, cv::Scalar(255, 255, 0), 2); } frame.release(); result.push_back(distance);//有人进入危险区域 result.push_back(wearHat);//未带安全帽人员数量 result.push_back(workpersons);//工作区域人员数量 return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelHAT-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } ///摄像头遮挡算法 modelId = 4 double PreProcessModel::fnCameraCoverRec(Mat imMat, Cover cover) { try { cv::Mat image, standard; image = imMat;//被判断图 int result = cover.detect(image); return result;//返回1是遮挡,0是不遮挡 } catch (const std::exception& ex) { std::string errorMessage = "fnCameraCoverRec-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } ///摄像头移动算法 modelId = 5 double PreProcessModel::fnCameraMoveRec(Mat imMat, Camera cam) { try { cv::Mat image, standard; image = imMat;//被判断图 standard = cam.stdMat;//参考图 int result = cam.detect(image, standard); return result;//返回1是移动,0是不移动 } catch (const std::exception& ex) { std::string errorMessage = "fnCameraMoveRec-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 堆煤检测,返回煤炭占比 modelId = 6 /// /// 视频流Mat /// 模型引用 double PreProcessModel::fnImRecProByModelDM(Mat& imMat, DMJC& dm, std::vector vertices) { try { double result = 0; // 定义接受帧 cv::Mat frame = imMat; // 调用煤流模型后的返回图片 cv::Mat frameout; // 外层矩形区域 cv::Rect rect(vertices[0].x, vertices[0].y, vertices[2].x - vertices[0].x, vertices[2].y - vertices[0].y); // 截取外层矩形区域 cv::Mat croppedFrame = frame(rect).clone(); //result = dm.detect(frame);// 返回指定区域煤占比 result = dm.detect_pic(croppedFrame, frameout); // 合并图片 // 在大图像上定义ROI(感兴趣区域) cv::Mat roi = frame(cv::Rect(vertices[0].x, vertices[0].y, frameout.cols, frameout.rows)); // 将小图像复制到ROI frameout.copyTo(roi); // 煤炭占比 drawTextWithBackgroundWstr(frame, std::to_string(result), 0, cv::Point(vertices[0].x, vertices[0].y), cv::Point(vertices[1].x - vertices[0].x, vertices[1].y - vertices[0].y), Scalar(255, 255, 0)); // 在视频帧上添加矩形框 //rectangle(frame, cv::Point(vertices[0].x, vertices[0].y), cv::Point(vertices[2].x, vertices[3].y), cv::Scalar(255, 255, 0), 2); croppedFrame.release(); frameout.release(); return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelDM-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 皮带跑偏,大块异物 modelId = 7-1 /// /// 视频流Mat /// 模型引用 vector PreProcessModel::fnImRecProByModelBeltJC(Mat& imMat, HAT& hat, std::vector vertices) { try { vector result; cv::Scalar sGreen = Scalar(0, 255, 0);;//绿色框 cv::Scalar sRed = Scalar(0, 0, 255);//红色框 cv::Scalar sPurple = Scalar(255, 0, 255);//紫色框 //定义接受帧 cv::Mat frame = imMat; //获取视频帧的宽度和高度和帧率 int frame_width = frame.cols; int frame_height = frame.rows; double frameRate = 25; // 创建一个空的边界框向量 std::vector boxes; // 调用 detect 函数获取检测到的边界框 hat.detect(frame, boxes); //多边形区域 //std::vector vertices = stringToPoints(area); // 绘制多边形 cv::polylines(frame, vertices, true, sGreen, 2); // 定义要测试的点 cv::Point testPoint; cv::Scalar sl;//标框颜色 // 使用索引遍历boxes for (int i = 0; i < boxes.size(); i++) { switch (boxes[i].class_id) { case 0: //人形中心点 testPoint.x = boxes[i].x + boxes[i].width / 2; testPoint.y = boxes[i].y + boxes[i].height / 2; if (cv::pointPolygonTest(vertices, testPoint, false) > 0)//区域内有个人,画红色 { //标注大媒块 drawTextWithBackgroundWstr(frame, "大 煤 块", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sPurple); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sPurple, 1); } break; case 2: case 3: case 4: case 5: //人形中心点 testPoint.x = boxes[i].x + boxes[i].width / 2; testPoint.y = boxes[i].y + boxes[i].height / 2; if (cv::pointPolygonTest(vertices, testPoint, false) > 0)//区域内有个人,画红色 { //标注异物 drawTextWithBackgroundWstr(frame, "异物", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sRed); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sRed, 1); } break; default: break; } } frame.release(); return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelBeltJC-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 皮带跑偏,大块异物,新处理方法 modelId = 7-2 /// /// 视频流Mat /// 模型引用 vector PreProcessModel::fnImRecProByModelBeltJC2(Mat& imMat, BELT& belt, std::vector leftvertices, std::vector rightvertices,std::vector vertices) { try { vector result; int bigcoal = 0;//0:无大煤块 1:有大煤块 int unbalance = 1;//0:偏载 1:不偏载 int foreign = 0;//0:无异物 1:有异物 cv::Scalar sGreen = Scalar(0, 255, 0);;//绿色框 cv::Scalar sRed = Scalar(0, 0, 255);//红色框 cv::Scalar sPurple = Scalar(255, 0, 255);//紫色框 // 画图 cv::Scalar roller_color(238, 130, 238); // 托辊区域线颜色 cv::Scalar roller_color2(203, 192, 255); // 托辊框的颜色 cv::Scalar belt_color(255, 0, 255); // 皮带区域线颜色 cv::Scalar belt_color2(0, 0, 255); // 异物框的颜色 //定义接受帧 cv::Mat frame = imMat; //获取视频帧的宽度和高度和帧率 int frame_width = frame.cols; int frame_height = frame.rows; double frameRate = 25; // 创建一个空的边界框向量 std::vector boxes; // 调用 detect 函数获取检测到的边界框 unbalance = belt.detect(frame, boxes); //多边形区域 //std::vector vertices = stringToPoints(area); // 绘制多边形 //cv::polylines(frame, vertices, true, sGreen, 2); polylines(frame, leftvertices, true, roller_color, 5, 8, 0); polylines(frame, rightvertices, true, roller_color, 5, 8, 0); polylines(frame, vertices, true, belt_color, 5, 8, 0); // 定义要测试的点 cv::Point testPoint; cv::Scalar sl;//标框颜色 // 使用索引遍历boxes for (int i = 0; i < boxes.size(); i++) { // 设置文本起始坐标(左下角坐标) cv::Point textOrg(boxes[i].x - boxes[i].width / 2, boxes[i].y - boxes[i].height / 2 - 10); switch (boxes[i].class_id) { case 0://大煤块 //中心点 testPoint.x = boxes[i].x + boxes[i].width / 2; testPoint.y = boxes[i].y + boxes[i].height / 2; if (cv::pointPolygonTest(vertices, testPoint, false) > 0)//进入区域后再画框 { //标注大煤块 drawTextWithBackgroundWstr(frame, "大煤块", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sPurple); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sPurple, 1); } bigcoal = 1; break; case 1: cv::rectangle(frame, cv::Point(boxes[i].x - boxes[i].width / 2, boxes[i].y - boxes[i].height / 2), cv::Point(boxes[i].x + boxes[i].width / 2, boxes[i].y + boxes[i].height / 2), roller_color2, 3); //标注托辊 drawTextWithBackgroundWstr(frame, "托辊", 2, cv::Point(boxes[i].x - boxes[i].width / 2, boxes[i].y - boxes[i].height / 2), cv::Point(boxes[i].width, boxes[i].height), sPurple); break; case 2: case 3: case 4: case 5: //中心点 testPoint.x = boxes[i].x + boxes[i].width / 2; testPoint.y = boxes[i].y + boxes[i].height / 2; if (cv::pointPolygonTest(vertices, testPoint, false) > 0)//区域内,画红色 { //标注异物 drawTextWithBackgroundWstr(frame, "异物", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sRed); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sRed, 1); } foreign = 1; break; default: break; } } frame.release(); //foreign = 1;//test result.push_back(bigcoal);//大煤块 result.push_back(unbalance);//偏载 result.push_back(foreign);//异物 return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelBeltJC2-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 乘猴车携带大件 modelId = 8 /// /// 视频流Mat /// 模型引用 vector PreProcessModel::fnImRecProByModelHATHC(Mat& imMat, HAT& hat, std::vector vertices) { try { vector result; //定义接受帧 cv::Mat frame = imMat; //获取视频帧的宽度和高度和帧率 int frame_width = frame.cols; int frame_height = frame.rows; double frameRate = 25; // 创建一个空的边界框向量 std::vector boxes; // 调用 detect 函数获取检测到的边界框 hat.detect(frame, boxes); //多边形区域 //std::vector vertices = stringToPoints(area); // 绘制多边形 //cv::polylines(frame, vertices, true, cv::Scalar(0, 0, 255), 2); // 定义要测试的点 cv::Scalar sl;//标框颜色 // 使用索引遍历boxes for (int i = 0; i < boxes.size(); i++) { switch (boxes[i].class_id) { case 0: sl = Scalar(0, 0, 255); //标注人形 drawTextWithBackgroundWstr(frame, "携 带 大 件", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sl); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sl, 1); break; //case 1: // //标注帽子 // drawTextWithBackgroundWstr(frame, "安全帽", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); // //在视频帧上添加矩形框 // rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); // break; //case 2: // wearHat++;//未佩戴安全帽的人的数量 // //标注头部 // drawTextWithBackgroundWstr(frame, "头", 3, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); // rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); // break; default: break; } } frame.release(); result.push_back(boxes.size());//返回携带大件人数 return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelHAT-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 睡岗处理 modelId = 9 /// /// 视频流Mat /// 模型引用 vector PreProcessModel::fnImRecProByModelHATSleep(Mat& imMat, HAT& hat) { try { vector result; //定义接受帧 cv::Mat frame = imMat; //获取视频帧的宽度和高度和帧率 int frame_width = frame.cols; int frame_height = frame.rows; // 创建一个空的边界框向量 std::vector boxes; // 调用 detect 函数获取检测到的边界框 hat.detect(frame, boxes); // 定义要测试的点 cv::Scalar sl;//标框颜色 // 使用索引遍历boxes for (int i = 0; i < boxes.size(); i++) { sl = Scalar(0, 0, 255); //标注人形 drawTextWithBackgroundWstr(frame, "睡 岗", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sl); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sl, 1); } frame.release(); result.push_back(boxes.size());//返回睡岗人员的数量 return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelHATSleep-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 人员穿戴 /// /// 视频流Mat /// 模型引用 vector PreProcessModel::fnImRecProByModelWear(Mat& imMat, HAT& hatWear, clasification& cfWear,std::vector vertices) { try { vector result; string title = "人员"; double checkpersons = 0;//检测区域正在检测的人员数量,默认是0 double resclothes = 0;//工作服 0:不穿工作服 1:穿工作服 double reshat = 0;//安全吗 0:不带安全帽 1:带安全帽 double respager = 0;//自救器 0:不携带自救器 1:带自救器 double resshoes = 0;//鞋 0:不穿鞋 1:穿鞋 //定义接受帧 cv::Mat frame = imMat; // 创建一个空的边界框向量 std::vector boxes; // 调用 detect 函数获取检测到的边界框 hatWear.detect(frame, boxes); // 定义要测试的点 cv::Point testPoint; cv::Scalar sl = Scalar(0, 255, 0);//默认标框颜色 // 设置原图中四点的坐标 std::vector srcPoints; // 设置目标图像的大小和四个点的坐标 std::vector dstPoints; // 计算透视变换矩阵 cv::Mat transform; // 应用透视变换 cv::Mat dst; // 使用索引遍历boxes for (int i = 0; i < boxes.size(); i++) { //标框中心点 testPoint.x = boxes[i].x + boxes[i].width / 2; testPoint.y = boxes[i].y + boxes[i].height / 2; switch (boxes[i].class_id) { case 0://人 if (cv::pointPolygonTest(vertices, testPoint, false) > 0)//进入检测区域内有人 { title = "人"; //personflg = true;//检测到人进入检测区域 checkpersons = 1; //标注人形 drawTextWithBackgroundWstr(frame, title, 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sl); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sl, 1); //截取人员图片处理 srcPoints.push_back(cv::Point2f(boxes[i].x, boxes[i].y)); // 左上角 srcPoints.push_back(cv::Point2f(boxes[i].x + boxes[i].width, boxes[i].y)); // 右上角 srcPoints.push_back(cv::Point2f(boxes[i].x + boxes[i].width, boxes[i].y + boxes[i].height)); // 右下角 srcPoints.push_back(cv::Point2f(boxes[i].x, boxes[i].y + boxes[i].height)); // 左下角 dstPoints.push_back(cv::Point2f(0, 0)); dstPoints.push_back(cv::Point2f(boxes[i].width, 0)); dstPoints.push_back(cv::Point2f(boxes[i].width, boxes[i].height)); dstPoints.push_back(cv::Point2f(0, boxes[i].height)); // 计算透视变换矩阵 transform = cv::getPerspectiveTransform(srcPoints, dstPoints); cv::warpPerspective(frame, dst, transform, cv::Size(boxes[i].width, boxes[i].height)); } break; case 1://安全帽 if (cv::pointPolygonTest(vertices, testPoint, false) > 0)//是否在检测区域内 { title = "安全帽"; reshat = 1; //标注帽子 drawTextWithBackgroundWstr(frame, title, 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); } break; //case 2://头部 // //标注头部 // drawTextWithBackgroundWstr(frame, "头", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); // rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); // break; case 3://自救器 if (cv::pointPolygonTest(vertices, testPoint, false) > 0)//是否在检测区域内 { title = "自救器"; respager = 1; //标注自救器 drawTextWithBackgroundWstr(frame, title, 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); } break; case 4://鞋 if (cv::pointPolygonTest(vertices, testPoint, false) > 0)//是否在检测区域内 { title = "鞋"; resshoes = 1; //标注鞋 drawTextWithBackgroundWstr(frame, title, 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), cv::Scalar(0, 255, 0)); rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), cv::Scalar(0, 255, 0), 1); } break; default: break; } } if (!dst.empty()) { if (cfWear.detect(dst) == 0) { resclothes = 1;//穿了工作服 } else { resclothes = 0;//未穿工作服 } //cv::imshow("Cropped Image", dst); //waitKey(10); } // 绘制多边形检测区域 cv::polylines(frame, vertices, true, cv::Scalar(0, 0, 255), 2); //cv::imshow("Cropped Image", frame); //waitKey(10); frame.release(); result.push_back(checkpersons);//检测区域人员数量 result.push_back(reshat);//安全帽 result.push_back(respager);//自救器 result.push_back(resshoes);//鞋 result.push_back(resclothes);//工作服 return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelHATWear-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } } /// /// 烟火 /// /// 视频流Mat /// 模型引用 vector PreProcessModel::fnImRecProByModelFire(Mat& imMat, HAT& hat) { try { vector result; double fire = 0;// 火焰数量 double smoke = 0;//烟数量 //定义接受帧 cv::Mat frame = imMat; //获取视频帧的宽度和高度和帧率 int frame_width = frame.cols; int frame_height = frame.rows; // 创建一个空的边界框向量 std::vector boxes; // 调用 detect 函数获取检测到的边界框 hat.detect(frame, boxes); // 定义要测试的点 cv::Scalar sl;//标框颜色 sl = Scalar(0, 0, 255); // 使用索引遍历boxes for (int i = 0; i < boxes.size(); i++) { switch (boxes[i].class_id) { case 0: fire++; //标注火 drawTextWithBackgroundWstr(frame, "火", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sl); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sl, 1); break; case 1: smoke++; //标注烟 drawTextWithBackgroundWstr(frame, "烟", 2, cv::Point(boxes[i].x, boxes[i].y), cv::Point(boxes[i].width, boxes[i].height), sl); //在视频帧上添加矩形框 rectangle(frame, cv::Point(boxes[i].x, boxes[i].y), cv::Point((boxes[i].x + boxes[i].width), (boxes[i].y + boxes[i].height)), sl, 1); break; default: break; } } frame.release(); result.push_back(fire);//返回火数量 result.push_back(smoke);//返回烟数量 return result; } catch (const std::exception& ex) { std::string errorMessage = "fnImRecProByModelHATSleep-"; errorMessage += ex.what(); cout << errorMessage << endl; throw std::runtime_error(errorMessage); } }