#include "PreProcessModel.h"
|
#include <future>
|
|
// 获取当前时间并格式化为指定格式的字符串
|
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);
|
}
|
|
/// <summary>
|
/// 根据提升机暂停和运动的比例,来最终判断是否运动
|
/// </summary>
|
/// <returns>0:运动 1:静止 -1:无法判断</returns>
|
int fnJudeRatio(std::queue<int> 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<double>(count0) / queueSize;
|
double ratio1 = static_cast<double>(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<std::codecvt_utf8_utf16<wchar_t>> 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<cv::Mat>& imagesBelt, int& beltCount, RUN& rBelt, std::vector<cv::Point> 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);
|
}
|
}
|
|
/// <summary>
|
/// 提升机变动检测 modelId = 2
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="imMatF">提升机用帧队列</param>
|
/// <param name="hat">模型引用</param>
|
double PreProcessModel::fnImRecProByModelTSJ(Mat& imMat, std::vector<cv::Mat>& imagesTsj, int& tsjCount, RUN& rTSJ, std::queue<int>& quTSJ, std::vector<cv::Point> 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);
|
}
|
}
|
|
/// <summary>
|
/// 人员识别,安全帽识别 modelId = 3
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="hat">模型引用</param>
|
vector<double> PreProcessModel::fnImRecProByModelHAT(Mat& imMat, HAT& hat, std::vector<cv::Point> vertices, std::vector<cv::Point> workvertices)
|
{
|
try
|
{
|
vector<double> 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<Box> boxes;
|
// 调用 detect 函数获取检测到的边界框
|
hat.detect(frame, boxes);
|
|
//多边形区域
|
//std::vector<cv::Point> 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<double> PreProcessModel::fnImRecProByModelHAT1(Mat& imMat, HAT& hat, std::vector<cv::Point> vertices, std::vector<cv::Point> workvertices,std::vector<std::vector<int>> c_list,std::string lable_title,std::string color_result)
|
{
|
try
|
{
|
vector<double> 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<Box> boxes;
|
// 调用 detect 函数获取检测到的边界框
|
hat.detect(frame, boxes);
|
|
//多边形区域
|
//std::vector<cv::Point> 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);
|
}
|
}
|
|
/// <summary>
|
/// 堆煤检测,返回煤炭占比 modelId = 6
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="dm">模型引用</param>
|
double PreProcessModel::fnImRecProByModelDM(Mat& imMat, DMJC& dm, std::vector<cv::Point> 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);
|
}
|
}
|
|
/// <summary>
|
/// 皮带跑偏,大块异物 modelId = 7-1
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="hat">模型引用</param>
|
vector<double> PreProcessModel::fnImRecProByModelBeltJC(Mat& imMat, HAT& hat, std::vector<cv::Point> vertices)
|
{
|
try
|
{
|
vector<double> 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<Box> boxes;
|
// 调用 detect 函数获取检测到的边界框
|
hat.detect(frame, boxes);
|
|
//多边形区域
|
//std::vector<cv::Point> 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);
|
}
|
}
|
|
/// <summary>
|
/// 皮带跑偏,大块异物,新处理方法 modelId = 7-2
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="hat">模型引用</param>
|
vector<double> PreProcessModel::fnImRecProByModelBeltJC2(Mat& imMat, BELT& belt, std::vector<cv::Point> leftvertices, std::vector<cv::Point> rightvertices,std::vector<cv::Point> vertices)
|
{
|
try
|
{
|
vector<double> 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<Box> boxes;
|
// 调用 detect 函数获取检测到的边界框
|
unbalance = belt.detect(frame, boxes);
|
|
//多边形区域
|
//std::vector<cv::Point> 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);
|
}
|
}
|
|
/// <summary>
|
/// 乘猴车携带大件 modelId = 8
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="hat">模型引用</param>
|
vector<double> PreProcessModel::fnImRecProByModelHATHC(Mat& imMat, HAT& hat, std::vector<cv::Point> vertices)
|
{
|
try
|
{
|
vector<double> result;
|
|
//定义接受帧
|
cv::Mat frame = imMat;
|
|
//获取视频帧的宽度和高度和帧率
|
int frame_width = frame.cols;
|
int frame_height = frame.rows;
|
double frameRate = 25;
|
|
// 创建一个空的边界框向量
|
std::vector<Box> boxes;
|
// 调用 detect 函数获取检测到的边界框
|
hat.detect(frame, boxes);
|
|
//多边形区域
|
//std::vector<cv::Point> 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);
|
}
|
}
|
|
/// <summary>
|
/// 睡岗处理 modelId = 9
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="hat">模型引用</param>
|
vector<double> PreProcessModel::fnImRecProByModelHATSleep(Mat& imMat, HAT& hat)
|
{
|
try
|
{
|
vector<double> result;
|
//定义接受帧
|
cv::Mat frame = imMat;
|
|
//获取视频帧的宽度和高度和帧率
|
int frame_width = frame.cols;
|
int frame_height = frame.rows;
|
|
// 创建一个空的边界框向量
|
std::vector<Box> 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);
|
}
|
}
|
|
/// <summary>
|
/// 人员穿戴
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="hat">模型引用</param>
|
|
vector<double> PreProcessModel::fnImRecProByModelWear(Mat& imMat, HAT& hatWear, clasification& cfWear,std::vector<cv::Point> vertices)
|
{
|
try
|
{
|
vector<double> 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<Box> boxes;
|
// 调用 detect 函数获取检测到的边界框
|
hatWear.detect(frame, boxes);
|
|
// 定义要测试的点
|
cv::Point testPoint;
|
cv::Scalar sl = Scalar(0, 255, 0);//默认标框颜色
|
|
// 设置原图中四点的坐标
|
std::vector<cv::Point2f> srcPoints;
|
// 设置目标图像的大小和四个点的坐标
|
std::vector<cv::Point2f> 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);
|
}
|
}
|
|
/// <summary>
|
/// 烟火
|
/// </summary>
|
/// <param name="imMat">视频流Mat</param>
|
/// <param name="hat">模型引用</param>
|
vector<double> PreProcessModel::fnImRecProByModelFire(Mat& imMat, HAT& hat)
|
{
|
try
|
{
|
vector<double> result;
|
double fire = 0;// 火焰数量
|
double smoke = 0;//烟数量
|
//定义接受帧
|
cv::Mat frame = imMat;
|
|
//获取视频帧的宽度和高度和帧率
|
int frame_width = frame.cols;
|
int frame_height = frame.rows;
|
|
// 创建一个空的边界框向量
|
std::vector<Box> 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);
|
}
|
}
|