#include "PreProcessFn.h"
|
#include "PreProcessModel.h"
|
|
#pragma comment(lib,"libmysql")
|
#include <boost/log/trivial.hpp>
|
#include <boost/log/utility/setup/file.hpp>
|
#include <boost/log/expressions.hpp>
|
#include <boost/filesystem.hpp>
|
#include <mysql/mysql.h>
|
#include <future>
|
#include "iostream"
|
|
#include <string>
|
#include <locale>
|
#include <codecvt>
|
#include "cls/CRabbitmqClient.h"
|
#include <bitset>
|
#include <opencv2/imgcodecs/legacy/constants_c.h>
|
#include "base/base64.h"
|
#include "cls/warningfile.h"
|
#include <filesystem> // C++17 中的文件系统库
|
#include <boost/uuid/uuid.hpp>
|
#include <boost/uuid/uuid_generators.hpp>
|
|
#include <curl/curl.h>
|
|
namespace fs = boost::filesystem;
|
std::mutex mtx;// 全局互斥锁,用于保护队列
|
PreProcessModel ppm = PreProcessModel();
|
|
PreProcessFn::PreProcessFn()
|
{
|
}
|
|
PreProcessFn::~PreProcessFn(void)
|
{
|
}
|
|
// 创建录像异步任务的 future 对象
|
std::future<void> video_writer_future;
|
|
int* stringToIntArray(std::string input) {
|
for (int i = 0; i < input.size(); i++) {
|
if (input[i] == ';') {
|
input[i] = ',';
|
}
|
}
|
|
std::vector<int> result;
|
std::stringstream ss(input);
|
std::string token;
|
|
// 从输入字符串中解析整数,并存储到结果向量中
|
while (getline(ss, token, ',')) {
|
result.push_back(std::stoi(token));
|
}
|
|
// 动态分配内存以存储整数数组
|
int* beltregion = new int[result.size()];
|
|
// 将结果向量中的整数复制到动态分配的数组中
|
for (int i = 0; i < result.size(); i++)
|
{
|
beltregion[i] = result[i];
|
}
|
|
return beltregion;
|
}
|
|
std::vector<cv::Point> stringToPoints(const std::string& input) {
|
std::vector<cv::Point> points;
|
std::stringstream ss(input);
|
|
int x, y;
|
char discard;
|
while (ss >> x >> discard >> y >> discard) {
|
points.push_back(cv::Point(x, y));
|
// Check for the ';' delimiter
|
if (ss.peek() == ';') {
|
ss.ignore();
|
}
|
}
|
|
return points;
|
}
|
|
// 获取当前时间并格式化为指定格式的字符串
|
std::string getCurrentDateTime(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);
|
}
|
|
// 获取当前时间,包括毫秒
|
std::string getCurrentDateTimeWithMilliseconds(const std::string& format) {
|
// 获取当前时间点
|
auto now = std::chrono::system_clock::now();
|
// 将时间点转换为时间戳
|
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
|
auto ms_part = now_ms.time_since_epoch().count() % 1000;
|
|
// 转换为本地时间
|
std::time_t now_time = std::chrono::system_clock::to_time_t(now);
|
std::tm* local_time = std::localtime(&now_time);
|
|
// 定义存储时间字符串的缓冲区
|
char buffer[80];
|
// 格式化时间为字符串,包括毫秒
|
std::strftime(buffer, sizeof(buffer), format.c_str(), local_time);
|
|
// 将毫秒部分添加到字符串中
|
std::string result(buffer);
|
result += std::to_string(ms_part);
|
|
return result;
|
}
|
|
//imgType 包括png bmp jpg jpeg等opencv能够进行编码解码的文件
|
std::string Mat2Base64(const cv::Mat& image, std::string imgType) {
|
//Mat转base64
|
std::vector<uchar> buf;
|
cv::imencode(imgType, image, buf);
|
std::string img_data = base64_encode(buf.data(), buf.size(), false);
|
return img_data;
|
}
|
|
//imgType 包括png bmp jpg jpeg等opencv能够进行编码解码的文件
|
std::string Mat2Bin(const cv::Mat& image, std::string imgType) {
|
//Mat转base64
|
std::vector<uchar> buf;
|
cv::imencode(imgType, image, buf);
|
std::string img_data = base64_encode(buf.data(), buf.size(), false);
|
return img_data;
|
}
|
|
string fnWarningFileToJson(warningfile wf)
|
{
|
// 创建 Json::Value 对象
|
Json::Value root;
|
root["coalCode"] = wf.getCoalCode();
|
root["cameraCode"] = wf.getCameraCode();
|
root["cameraName"] = wf.getCameraName();
|
root["analyse"] = wf.getAnalyse();
|
root["analyseResult"] = wf.getAnalyseResult();
|
root["warningTime"] = wf.getWarningTime();
|
root["recordFileName"] = wf.getRecordFileName();
|
root["recordImgFileName"] = wf.getrecordImgFileName();
|
root["rtspUrl"] = wf.getRtspUrl();
|
root["duration"] = wf.getDuration();
|
|
// 使用 Json::FastWriter 将 Json::Value 对象转换为 JSON 字符串
|
Json::FastWriter writer;
|
return writer.write(root);
|
}
|
|
//创建文件夹 年 月 日
|
string fnCreateFileFolder(string hdPath)
|
{
|
// 获取当前系统时钟的当前时间点
|
auto now = std::chrono::system_clock::now();
|
// 将当前时间点转换为 time_t 类型
|
std::time_t time_now = std::chrono::system_clock::to_time_t(now);
|
// 将 time_t 类型的时间转换为本地时间
|
std::tm local_time = *std::localtime(&time_now);
|
|
std::string year_folder = std::to_string(local_time.tm_year + 1900);
|
std::string month_folder = std::to_string(local_time.tm_mon + 1);
|
std::string day_folder = std::to_string(local_time.tm_mday);
|
|
std::string folder_path = hdPath + "/" + year_folder + "/" + month_folder + "/" + day_folder + "/";
|
|
// // 检查文件夹是否已存在
|
if (!fs::exists(folder_path.c_str())) {
|
// 不存在则创建文件夹
|
fs::create_directories(folder_path.c_str());
|
//std::cout << "已创建文件夹:" << folder_path << std::endl;
|
}
|
return folder_path;//返回文件夹路径
|
|
}
|
|
/// <summary>
|
/// 判断结果比例
|
/// </summary>
|
/// <returns></returns>
|
int fnJudeRatio(vector<int> vec, int ftype,double ratio)
|
{
|
// 计算队列中 0 和 1 的数量
|
double count0 = 0;//0的个数
|
double count1 = 0;//1的个数
|
|
double vecSize = vec.size();
|
for (int i = 0; i < vec.size(); ++i) {
|
if (vec[i] == 0) {
|
count0++;
|
}
|
else {
|
count1++;
|
}
|
}
|
|
//cout << getCurrentDateTime1("%Y%m%d%H%M%S") << endl;
|
/*cout << "------------" << endl;
|
cout << count0 << endl;
|
cout << count1 << endl;*/
|
|
// 计算比例
|
double ratio0 = count0 / vecSize;
|
double ratio1 = count1 / vecSize;
|
|
switch (ftype)
|
{
|
case 0:
|
if (ratio0 >= ratio)
|
{
|
return 0;
|
}
|
else
|
{
|
return 1;
|
}
|
break;
|
case 1:
|
if (ratio1 >= ratio)
|
{
|
return 1;
|
}
|
else
|
{
|
return 0;
|
}
|
break;
|
|
default:
|
return -1;
|
break;
|
}
|
}
|
|
/// <summary>
|
/// 录像并保存报警信息至MySql模块
|
/// </summary>
|
void fnVideoRecordToMysql(Mat frame, int Alarm, VideoWriter& video_writer, std::chrono::system_clock::time_point start_time, warningfile wf, MYSQL* mysql, int _recordtime)
|
{
|
// 当前时间
|
double seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - start_time).count();
|
//cout << start_time << endl;
|
//cout << current_time << endl;
|
// 如果录制时间超过 10 秒,则停止录制
|
if (seconds >= _recordtime) {
|
cout << "已录制 10 秒视频,停止录制" << endl;
|
video_writer.release();
|
}
|
else
|
{
|
video_writer.write(frame);//录像处理
|
}
|
|
if (Alarm == 1)//报警信息保存至mysql
|
{
|
// 记录报警的时候,同时写入redis数据库
|
wf.setWarningTime(getCurrentDateTime("%Y-%m-%d %H:%M:%S"));
|
|
// 构建插入 SQL 语句
|
std::stringstream ss;
|
ss << "INSERT INTO alarmevent (AlarmType, AlarmName, CameraCode, AlarmState, AlarmPic, AlarmVideo, AlarmTime) VALUES ('"
|
<< wf.getAnalyse() << "', '"
|
<< wf.getAnalyseResult() << "', "
|
<< wf.getCameraCode() << ", '"
|
<< "0" << "', '"
|
<< wf.getrecordImgFileName() << "', '"
|
<< wf.getRecordFileName() << "', '"
|
<< wf.getWarningTime() << "')";
|
|
std::string query = ss.str();
|
// 执行插入语句
|
if (mysql_query(mysql, query.c_str()))
|
{
|
string err_string = mysql_error(mysql);
|
cout << err_string << endl;
|
}
|
}
|
}
|
|
/// <summary>
|
/// 录像并保存报警信息至MySql模块,录像为以前时间段
|
/// </summary>
|
void fnVideoRecordToMysql2(vector<Mat> vecVideo, int Alarm, VideoWriter& video_writer, warningfile wf, MYSQL* mysql)
|
{
|
for (int i = 0; i < vecVideo.size(); i++) {
|
video_writer.write(vecVideo[i]);//录像处理
|
}
|
|
video_writer.release();
|
|
if (Alarm == 1)//报警信息保存至mysql
|
{
|
// 记录报警的时候,同时写入redis数据库
|
wf.setWarningTime(getCurrentDateTime("%Y-%m-%d %H:%M:%S"));
|
|
// 构建插入 SQL 语句
|
std::stringstream ss;
|
ss << "INSERT INTO alarmevent (AlarmType, AlarmName, CameraCode, AlarmState, AlarmPic, AlarmVideo, AlarmTime) VALUES ('"
|
<< wf.getAnalyse() << "', '"
|
<< wf.getAnalyseResult() << "', '"
|
<< wf.getCameraCode() << "', '"
|
<< "0" << "', '"
|
<< wf.getrecordImgFileName() << "', '"
|
<< wf.getRecordFileName() << "', '"
|
<< wf.getWarningTime() << "')";
|
|
std::string query = ss.str();
|
// 执行插入语句
|
if (mysql_query(mysql, query.c_str()))
|
{
|
string err_string = mysql_error(mysql);
|
cout << err_string << endl;
|
}
|
}
|
}
|
|
// 回调函数,用于将返回的数据存储在 std::string 中
|
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
|
((std::string*)userp)->append((char*)contents, size * nmemb);
|
return size * nmemb;
|
}
|
|
string join(const vector<string>& sequence, const string& separator)
|
{
|
std::string result;
|
for (size_t i = 0; i < sequence.size(); ++i)
|
result += sequence[i] + ((i != sequence.size() - 1) ? separator : "");
|
return result;
|
}
|
|
/// @brief 视频流拉取处理
|
/// @param _rtspUrl 视频流源地址
|
/// @param queJC 未处理的视频流帧队列
|
void PreProcessFn::fnGetVideoMatToQueue(string rtspUrl,queue<Mat>& queJC)
|
{
|
VideoCapture rtspStream(rtspUrl.c_str());// 连接RTSP流,软解码
|
//Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(rtspUrl);
|
|
int count = 0;
|
long currentFrame = 1;
|
long skip_frame_num = skipN;//跳帧间隔设置(每1帧)
|
|
while (!asyncStop)
|
{
|
//std::cout << "当前线程待处理队列数据数量0000:" << queJC.size() << std::endl;
|
//cout << getCurrentDateTime("%Y%m%d%H%M%S") << endl;
|
//cout << skip_frame_num << endl;
|
|
try
|
{
|
if (queJC.size() > 500)
|
{
|
cout << "获取视频时,存在内存溢出风险!" << endl;
|
}
|
|
|
if (currentFrame % skip_frame_num == 0) //跳帧处理
|
{
|
Mat frame;
|
|
//cv::cuda::GpuMat d_frame;
|
|
//////软解码
|
if (!rtspStream.isOpened()) {
|
rtspStream.open(rtspUrl.c_str());
|
if (!rtspStream.isOpened()) {
|
|
std::this_thread::sleep_for(std::chrono::seconds(5));// 等待一段时间后重试连接
|
//log.Log(rtspUrl + ":重启连接失败,请等待" + "\n");
|
continue;
|
}
|
cout << rtspUrl + ":重启连接完成," + to_string(count) + "\n" << endl;
|
//log.Log(rtspUrl + ":重启连接完成," + to_string(count) + "\n");
|
count = 0;//重连计数复位
|
}
|
|
//读取视频帧
|
if (!rtspStream.read(frame))
|
{
|
if (count > 3)
|
{
|
cout << rtspUrl + ":连接释放,重新连接!" + "\n";
|
//log.Log(rtspUrl + ":连接释放,重新连接!" + "\n");
|
rtspStream.release();
|
//rtspStream.open(rtspUrl.c_str());
|
count = 0;//重连计数复位
|
}
|
else
|
{
|
std::this_thread::sleep_for(std::chrono::seconds(1));// 延迟1秒再去取帧
|
cout << rtspUrl + ":" + to_string(count) << endl;
|
count++;
|
}
|
continue;
|
}
|
|
////
|
|
//硬解码
|
//读取视频帧
|
// if (!d_reader->nextFrame(d_frame))
|
// {
|
// d_reader = cv::cudacodec::createVideoReader(rtspUrl);
|
// continue;
|
// }
|
|
// d_frame.download(frame);
|
// //cout << "gpu" << endl;
|
// d_frame.release();
|
|
///
|
|
if (frame.empty())
|
{
|
std::cout << "空帧,废弃" << std::endl;
|
continue;
|
}
|
|
//加锁,防止别的系统操作这段内存
|
std::unique_lock<std::mutex> lck(mtx);
|
queJC.push(frame); // 推入待处理队列
|
lck.unlock();
|
|
|
//cv::imwrite("./img/" + std::to_string(currentFrame)+".jpg", frame);
|
//cv::imshow(rtspUrl, queJC.front());//展示帧图片
|
//cv::imshow(rtspUrl, frame);//展示帧图片
|
//waitKey(5);
|
|
//std::this_thread::sleep_for(std::chrono::milliseconds(100));// 延迟等待一段时间
|
|
frame.release();
|
}
|
|
if (currentFrame > 10000) {
|
currentFrame = 0;
|
}
|
|
currentFrame++;
|
|
}
|
catch (const std::exception& ex)
|
{
|
std::string errorMessage = "拉流失败-";
|
errorMessage += ex.what();
|
continue;
|
}
|
}
|
|
//d_reader.release();
|
rtspStream.release();
|
}
|
|
std::string jsontostr(Json::Value& json)
|
{
|
string return_str;
|
if(!json.isNull()&&!json.empty())
|
{
|
for (int i = 0; i < json.size(); i++)
|
{
|
return_str += json[i].asString()+",";
|
}
|
if (!return_str.empty() && return_str.back() == ',') {
|
return_str.pop_back();
|
}
|
|
}
|
else
|
{
|
return_str = "";
|
}
|
return return_str;
|
}
|
|
/// @brief 视频帧处理函数
|
/// @param ipcsNode 摄像机节点
|
/// @param modelArray 模型列表
|
/// @param queJC 未处理的视频流帧队列
|
/// @param queJC2 处理完的视频流帧队列
|
void PreProcessFn::fnImRecognitionPro(const Json::Value& ipcsNode, Json::Value modelArray, queue<Mat>& queJC, queue<Mat>& queJC2)
|
{
|
std::string ipccode = ipcsNode["code"].asString();//摄像机编码
|
std::string ipcname = ipcsNode["name"].asString();//摄像机名称
|
std::string ipcrtsppath = ipcsNode["video"].asString();//视频rtsp源
|
// std::string skipN = ipcsNode["skipN"].asString();//跳帧
|
// int skipN = ipcsNode["skipN"].asString();//跳帧
|
//mysql连接初始化
|
MYSQL* mysql = mysql_init(nullptr);
|
if (!mysql_real_connect(mysql, mysqlpath.c_str(), mysqluser.c_str(), mysqlpass.c_str(), mysqldatabase.c_str(), stoi(mysqlport), NULL, 0))
|
{
|
std::cout << "连接 MySQL 数据库失败: " << mysql_error(mysql) << std::endl;
|
//mysql_close(mysql); // 关闭连接
|
//std::exit(0);//数据库连接错误,退出程序
|
}
|
else
|
{
|
std::cout << "连接 MySQL 数据库成功。" << std::endl;
|
mysql_set_character_set(mysql, "utf8mb4");
|
//mysql_query(mysql, "SET NAMES GB2312");//解决中文乱码问题
|
}
|
|
std::string limitDM = "1";//堆煤限定阈值,超过阈值进行报警,配置文件赋值,每个摄像头都不一样
|
|
//新增模型处理 ------第1步
|
//检测区域设定
|
std::vector<Point> areaBelt;//皮带运行检测区域
|
std::vector<Point> areaTSJ;//提升机检测区域
|
std::vector<Point> areaPerson;//人员检测区域
|
std::vector<Point> workareaPerson;//工作区域人员检测区域
|
std::vector<Point> leftareaBeltJC;//左侧皮带检测区域
|
std::vector<Point> rightareaBeltJC;//右侧皮带检测区域
|
std::vector<Point> areaBeltJC;//皮带检测区域
|
std::vector<Point> areaHC;//猴车
|
std::vector<Point> areaSleep;//睡岗
|
std::vector<Point> areaDM;//堆煤检测区域
|
std::vector<Point> areaWear;//穿戴检测区域
|
std::vector<Point> areaFire;//烟火检测区域
|
std::vector<Point> detectarea;//检测区域
|
std::vector<Point> flowarea;//皮带外围区域
|
std::vector<Point> flowrelate;//皮带相对区域
|
std::vector<Point> leftarea;//左侧区域
|
std::vector<Point> rightarea;//右侧区域
|
std::vector<Point> beltarea;//中间区域
|
std::vector<Point> workarea;//工作区域
|
|
|
//模型处理 ------第2步
|
RUN rBelt;//皮带运行模型
|
rBelt.analysis1 = "0001";//运行
|
rBelt.analysis2 = "0002";//停止
|
|
RUN rTSJ;//提升机检测模型
|
rTSJ.analysis1 = "0001";//运行
|
rTSJ.analysis2 = "0002";//停止
|
|
HAT hatJC;//目标检测模型
|
Cover cover;//摄像头遮挡算法
|
Camera camera;//摄像头移动算法
|
DMJC dm;//堆煤检测模型
|
BELT beltJC;//皮带跑偏,大块异物
|
HAT hatHC;//乘猴车携带大件模型
|
HAT hatSleep;//睡岗
|
HAT hatWear ;//穿戴模型1
|
clasification cfWear;//穿戴模型2
|
HAT hatFire;//烟火模型
|
|
//各模型录像保存路径 ------第3步
|
string videoPathBelt = "";//皮带运行挡录像保存路径
|
string videoPathTSJ = "";// 提升机录像保存路径
|
string videoPathPerson = "";// 人员闯入录像保存路径
|
string videoPathBeltJC = "";// 皮带检测录像保存路径
|
string videoPathCameraCover = "";// 摄像头遮挡录像保存路径
|
string videoPathCameraMove = "";// 摄像头移动录像保存路径
|
string videoPathDM = "";// 堆煤录像保存路径
|
string videoPathHC = "";// 猴车录像保存路径
|
string videoPathSleep = "";// 睡岗录像保存路径
|
string videoPathWear = "";// 穿戴录像保存路径
|
string videoPathFire = "";// 烟火录像保存路径
|
|
//最后一次录像时间 ------第4步
|
auto videoTimeBelt = std::chrono::system_clock::now();// 上一次皮带运行状态录制时间
|
auto videoTimeTSJ = std::chrono::system_clock::now();// 上一次提升机录制时间
|
auto videoTimePerson = std::chrono::system_clock::now();// 上一次人员闯入录制时间
|
auto videoTimeBeltJC = std::chrono::system_clock::now();// 上一次皮带检测录制时间
|
//auto videoTimeCameraCover = std::chrono::system_clock::now();// 上一次摄像头遮挡录制时间
|
//auto videoTimeCameraMove = std::chrono::system_clock::now();// 上一次摄像头移动录制时间
|
auto videoTimeDM = std::chrono::system_clock::now();// 上一次堆煤录制时间
|
auto videoTimeHC = std::chrono::system_clock::now();// 上一次猴车录制时间
|
auto videoTimeSleep = std::chrono::system_clock::now();// 上一次睡岗录制时间
|
auto videoTimeWear = std::chrono::system_clock::now();// 上一次穿戴录制时间
|
auto videoTimeFire = std::chrono::system_clock::now();// 上一次烟火录制时间
|
|
//当前录像开始时间 ------第5步
|
auto start_timeBelt = std::chrono::system_clock::now();// 皮带运行状态开始录制时间
|
auto start_timeTSJ = std::chrono::system_clock::now();// 提升机开始录制时间
|
auto start_timePerson = std::chrono::system_clock::now();// 人员闯入开始录制时间
|
auto start_timeBeltJC= std::chrono::system_clock::now();// 皮带检测开始录制时间
|
auto start_timeCameraCover = std::chrono::system_clock::now();// 摄像头遮挡开始录制时间
|
auto start_timeCameraMove = std::chrono::system_clock::now();// 摄像头移动开始录制时间
|
auto start_timeDM = std::chrono::system_clock::now();// 堆煤开始录制时间
|
auto start_timeHC = std::chrono::system_clock::now();// 猴车开始录制时间
|
auto start_timeSleep = std::chrono::system_clock::now();// 睡岗开始录制时间
|
auto start_timeWear = std::chrono::system_clock::now();// 穿戴开始录制时间
|
auto start_timeFire = std::chrono::system_clock::now();// 烟火开始录制时间
|
|
//调用模型和算法的返回结果 ------第6步
|
int beltStatus = 0;// 皮带最新状态
|
int beltStatusold = 0;// 皮带旧状态
|
int tsjStatus = -1;// 提升机最新状态 0运动 1停止 -1未知
|
int tsjStatusold = -1;// 提升机旧状态 0运动 1停止 -1未知
|
vector<double> personResult;//breakin:>0 人员闯入 <=0 无人员闯入;wearHat 0:全部佩戴安全帽 1:有人未佩戴安全帽
|
vector<double> beltJCResult;
|
double cameracover = 0;// 摄像头遮挡标志
|
double cameramove = 0;// 摄像头移动标志
|
float proportion = 0;// 煤炭占比
|
vector<double> hcResult; //猴车返回结果
|
vector<double> sleepResult; //睡岗返回结果
|
vector<double> resultWearold;//穿戴返回结果,上一次的结果
|
vector<double> resultWear;//穿戴返回结果
|
vector<double> resultFire;//烟火返回结果
|
|
//异步任务结果 ------第7步
|
std::future<double> futureBelt;// 皮带运行状态检测异步任务结果
|
std::future<double> futureTSJ;// 提升机状态检测异步任务结果
|
std::future<vector<double>> futurePerson;// 目标检测异步任务结果
|
std::future<vector<double>> futureBeltJC;// 皮带检测异步任务结果
|
std::future<double> futureCameraCover;// 摄像头遮挡检测异步任务结果
|
std::future<double> futureCameraMove;// 摄像头移动检测异步任务结果
|
std::future<double> futureDM;// 堆煤检测异步任务结果
|
std::future<vector<double>> futureHC;// 乘猴车携带大件异步任务结果
|
std::future<vector<double>> futureSleep;// 睡岗异步任务结果
|
std::future<vector<double>> futureWear;// 穿戴检测异步任务结果
|
std::future<vector<double>> futureFire;// 烟火检测异步任务结果
|
|
//VideoWriter对象 ------第8步
|
VideoWriter video_writerBelt;// 皮带运行状态录像用
|
VideoWriter video_writerTSJ;// 提升机录像用
|
VideoWriter video_writerPerson;// 人员闯入录像用
|
VideoWriter video_writerBeltJC;// 皮带检测录像用
|
VideoWriter video_writerCameraCover;// 摄像头遮挡录像用
|
VideoWriter video_writerCameraMove;// 摄像头移动录像用
|
VideoWriter video_writerDM;// 堆煤录像用
|
VideoWriter video_writerHC;// 猴车录像用
|
VideoWriter video_writerSleep;// 睡岗录像用
|
VideoWriter video_writerWear;// 穿戴录像用
|
VideoWriter video_writerFire;// 烟火录像用
|
|
//创建写入redis的实例 ------第9步
|
warningfile wfBelt = warningfile();
|
warningfile wfTSJ = warningfile();
|
warningfile wfPerson = warningfile();
|
warningfile wfBeltJC = warningfile();
|
warningfile wfCameraCover = warningfile();
|
warningfile wfCameraMove = warningfile();
|
warningfile wfDM = warningfile();
|
warningfile wfHC = warningfile();
|
warningfile wfSleep = warningfile();
|
warningfile wfWear = warningfile();
|
warningfile wfFire = warningfile();
|
|
//第一次报警时间 ------第10步
|
auto firstSleep = std::chrono::system_clock::now();// 睡岗第一次报警时间
|
auto firstFire = std::chrono::system_clock::now();// 烟火第一次报警时间
|
|
|
//记录判断结果
|
|
vector<Mat> vecVideoSleep;//保存睡岗视频帧
|
vector<int> vecFire;//烟火判断结果
|
vector<Mat> vecVideoFire;//保存烟火视频帧
|
|
//提升机和皮带判断时,需要累计三张图片才能进行判断
|
std::vector<cv::Mat> imagesTsj;
|
std::vector<cv::Mat> imagesBelt;
|
std::string color_result;
|
std::string lable_title;
|
|
cout <<modelArray.size()<<endl;
|
//循环每个摄像头的模型,加载模型
|
for (int j = 0; j < modelArray.size(); ++j) {
|
Json::Value modelNode = modelArray[j];
|
std::string modelCode = modelNode["code"].asString();//模型编码 区分加载不同的模型
|
std::string modelPath = modelNode["path"].asString();
|
std::string modelPath2 = modelNode["path2"].asString();//模型2路径
|
std::string imagePath = modelNode["img_path"].asString();
|
|
std::string modelName = modelNode["name"].asString();
|
Json::Value modelTypeArr = modelNode["type"];////模型分析类型编码
|
std::string modelType = jsontostr(modelTypeArr);
|
|
double threshold = stod(modelNode["threshold"].asString());//阈值
|
float modelLimit = stof(modelNode["limit"].asString());//限定值
|
std::string modelAnalysis ="";
|
color_result = modelNode["color_result"].asString();//颜色反正值
|
|
// std::string area = modelNode["threshold"].asString();//区域一
|
// std::string area2 = modelNode.get("area2", "").asString();//区域二
|
Json::Value rects = modelNode["point_rects"];////模型分析类型编码
|
for (auto k = 0; k < rects.size(); ++k)
|
{
|
Json::Value pointNode = rects[k];
|
lable_title=pointNode["title"].asString();
|
std::string point_type=pointNode["type"].asString();
|
Json::Value point_Arr= pointNode["points"];
|
for (auto x = 0; x < point_Arr.size(); ++x)
|
{
|
int croodx = stoi(point_Arr[x]["x"].asString());
|
int croody = stoi(point_Arr[x]["y"].asString());
|
if(point_type=="detectarea")
|
{
|
detectarea.push_back(cv::Point(croodx, croody));
|
}
|
if (point_type=="flowarea")
|
{
|
flowarea.push_back(cv::Point(croodx, croody));
|
}
|
if (point_type=="flowrelate")
|
{
|
flowrelate.push_back(cv::Point(croodx, croody));
|
}
|
if (point_type=="leftroller")
|
{
|
leftarea.push_back(cv::Point(croodx, croody));
|
}
|
if (point_type=="rightroller")
|
{
|
rightarea.push_back(cv::Point(croodx, croody));
|
}
|
if (point_type=="beltarea")
|
{
|
beltarea.push_back(cv::Point(croodx, croody));
|
}
|
if (point_type=="workarea")
|
{
|
workarea.push_back(cv::Point(croodx, croody));
|
}
|
|
}
|
}
|
|
int* arr = new int[detectarea.size() * 2];
|
//加载模型处理------
|
if(modelCode=="1") //皮带状态
|
{
|
if (!rBelt.initConfig(modelPath.c_str(),arr))
|
{
|
printf("皮带运行模型初始化失败。\n");
|
}
|
else
|
{
|
printf("皮带运行模型初始化成功。\n");
|
rBelt.isLoad = true;
|
}
|
areaBelt =detectarea;
|
videoPathBelt = coalCode + ipccode + modelType + modelAnalysis;
|
wfBelt.setCoalCode(coalCode);
|
wfBelt.setCameraCode(ipccode);
|
wfBelt.setCameraName(ipcname);
|
wfBelt.setRtspUrl(ipcrtsppath);
|
wfBelt.setAnalyse(modelType);
|
//wfBelt.setAnalyseResult(modelAnalysis);
|
}
|
if(modelCode=="2") //提升机运行检测模型
|
{
|
if (!rTSJ.initConfig(modelPath.c_str(), arr))
|
{
|
printf("提升机模型初始化失败。\n");
|
}
|
else
|
{
|
printf("提升机模型初始化成功。\n");
|
rTSJ.isLoad = true;
|
}
|
areaTSJ = detectarea;
|
videoPathTSJ = coalCode + ipccode + modelType;
|
wfTSJ.setCoalCode(coalCode);
|
wfTSJ.setCameraCode(ipccode);
|
wfTSJ.setCameraName(ipcname);
|
wfTSJ.setRtspUrl(ipcrtsppath);
|
wfTSJ.setAnalyse(modelType);
|
wfTSJ.setAnalyseResult(modelAnalysis);
|
break;
|
}
|
if(modelCode=="3") //人员区域闯入模型
|
{
|
if (!hatJC.initConfig(modelPath.c_str(), 0.5, 0.5))
|
{
|
printf("目标检测模型初始化失败\n");
|
}
|
else
|
{
|
printf("目标检测模型初始化成功。\n");
|
hatJC.isLoad = true;
|
}
|
areaPerson = detectarea;//危险区域
|
workareaPerson = workarea;//工作区域
|
videoPathPerson = coalCode + ipccode + modelType + modelAnalysis;
|
wfPerson.setCoalCode(coalCode);
|
wfPerson.setCameraCode(ipccode);
|
wfPerson.setCameraName(ipcname);
|
wfPerson.setRtspUrl(ipcrtsppath);
|
wfPerson.setAnalyse(modelType);
|
wfPerson.setAnalyseResult(modelAnalysis);
|
}
|
if(modelCode=="4") //摄像头遮挡算法
|
{
|
if (!cover.initConfig()) {
|
printf("摄像头遮挡算法初始化失败\n");
|
}
|
else
|
{
|
std::cout << "摄像头遮挡算法初始化成功" << std::endl;
|
cover.isLoad = true;
|
}
|
videoPathCameraCover = coalCode + ipccode + modelType + modelAnalysis;
|
wfCameraCover.setCoalCode(coalCode);
|
wfCameraCover.setCameraCode(ipccode);
|
wfCameraCover.setCameraName(ipcname);
|
wfCameraCover.setRtspUrl(ipcrtsppath);
|
wfCameraCover.setAnalyse(modelType);
|
wfCameraCover.setAnalyseResult(modelAnalysis);
|
}
|
if(modelCode=="5") //摄像头移动算法
|
{
|
if (!camera.initConfig()) {
|
printf("摄像头移动算法初始化失败\n");
|
}
|
else
|
{
|
std::cout << "摄像头移动算法初始化成功" << std::endl;
|
camera.isLoad = true;
|
camera.stdMat = cv::imread(imagePath);
|
}
|
videoPathCameraMove = coalCode + ipccode + modelType + modelAnalysis;
|
wfCameraMove.setCoalCode(coalCode);
|
wfCameraMove.setCameraCode(ipccode);
|
wfCameraMove.setCameraName(ipcname);
|
wfCameraMove.setRtspUrl(ipcrtsppath);
|
wfCameraMove.setAnalyse(modelType);
|
wfCameraMove.setAnalyseResult(modelAnalysis);
|
}
|
if(modelCode=="6") //堆煤检测模型
|
{
|
if (!dm.initConfig(modelPath.c_str(), arr)) {
|
printf("堆煤模型初始化失败\n");
|
}
|
else
|
{
|
std::cout << "堆煤模型初始化成功" << std::endl;
|
dm.isLoad = true;
|
}
|
videoPathDM = coalCode + ipccode + modelType + modelAnalysis;
|
areaDM = detectarea;
|
limitDM = modelLimit;//堆煤限定煤量占比
|
|
wfDM.setCoalCode(coalCode);
|
wfDM.setCameraCode(ipccode);
|
wfDM.setCameraName(ipcname);
|
wfDM.setRtspUrl(ipcrtsppath);
|
wfDM.setAnalyse(modelType);
|
wfDM.setAnalyseResult(modelAnalysis);
|
}
|
if(modelCode=="7") //皮带跑偏和异物检测
|
{
|
int* leftarr = new int[leftarea.size() * 2];
|
int* rightarr = new int[rightarea.size() * 2];
|
int* midd_arr = new int[beltarea.size() * 2];
|
|
if (!beltJC.initConfig(modelPath.c_str(), leftarr, rightarr, midd_arr, modelLimit))
|
{
|
printf("皮带跑偏和异物检测模型初始化失败\n");
|
}
|
else
|
{
|
printf("皮带跑偏和异物检测模型初始化成功。\n");
|
beltJC.isLoad = true;
|
}
|
leftareaBeltJC = leftarea;
|
rightareaBeltJC = rightarea;
|
areaBeltJC = beltarea;
|
videoPathBeltJC = coalCode + ipccode + modelType + modelAnalysis;
|
wfBeltJC.setCoalCode(coalCode);
|
wfBeltJC.setCameraCode(ipccode);
|
wfBeltJC.setCameraName(ipcname);
|
wfBeltJC.setRtspUrl(ipcrtsppath);
|
wfBeltJC.setAnalyse(modelType);
|
wfBeltJC.setAnalyseResult(modelAnalysis);
|
}
|
if(modelCode=="8") //猴车大物件
|
{
|
if (!hatHC.initConfig(modelPath.c_str(), 0.5, 0.5))
|
{
|
printf("乘猴车携带大件模型初始化失败\n");
|
}
|
else
|
{
|
printf("乘猴车携带大件模型初始化成功。\n");
|
hatHC.isLoad = true;
|
}
|
areaHC = detectarea;
|
videoPathHC = coalCode + ipccode + modelType + modelAnalysis;
|
wfHC.setCoalCode(coalCode);
|
wfHC.setCameraCode(ipccode);
|
wfHC.setCameraName(ipcname);
|
wfHC.setRtspUrl(ipcrtsppath);
|
wfHC.setAnalyse(modelType);
|
wfHC.setAnalyseResult(modelAnalysis);
|
}
|
|
if (modelCode == "9")//睡岗判断
|
{
|
if (!hatSleep.initConfig(modelPath.c_str(), 0.5, 0.5))
|
{
|
printf("睡岗模型初始化失败\n");
|
}
|
else
|
{
|
printf("睡岗模型初始化成功。\n");
|
hatSleep.isLoad = true;
|
}
|
areaSleep = detectarea;
|
videoPathSleep = coalCode + ipccode + modelType + modelAnalysis;
|
wfSleep.setCoalCode(coalCode);
|
wfSleep.setCameraCode(ipccode);
|
wfSleep.setCameraName(ipcname);
|
wfSleep.setRtspUrl(ipcrtsppath);
|
wfSleep.setAnalyse(modelType);
|
wfSleep.setAnalyseResult(modelAnalysis);
|
}
|
if (modelCode == "10")//穿戴检测,初始化两个模型
|
{
|
if (!hatWear.initConfig(modelPath.c_str(), 0.5, 0.5))
|
{
|
printf("穿戴模型1初始化失败\n");
|
}
|
else
|
{
|
printf("穿戴模型1初始化成功。\n");
|
if (!cfWear.initConfig(modelPath2.c_str()))
|
{
|
printf("穿戴模型2初始化失败\n");
|
}
|
else
|
{
|
printf("穿戴模型2初始化成功\n");
|
}
|
hatWear.isLoad = true;
|
}
|
areaWear = detectarea;
|
videoPathWear = coalCode + ipccode + modelType + modelAnalysis;
|
wfWear.setCoalCode(coalCode);
|
wfWear.setCameraCode(ipccode);
|
wfWear.setCameraName(ipcname);
|
wfWear.setRtspUrl(ipcrtsppath);
|
wfWear.setAnalyse(modelType);
|
wfWear.setAnalyseResult(modelAnalysis);
|
}
|
if (modelCode == "11")//烟火模型
|
{
|
if (!hatFire.initConfig(modelPath.c_str())) {
|
printf("烟火模型初始化失败\n");
|
}
|
else
|
{
|
printf("烟火模型初始化成功。\n");
|
hatFire.isLoad = true;
|
}
|
areaFire = detectarea;
|
videoPathFire = coalCode + ipccode + modelType + modelAnalysis;
|
wfFire.setCoalCode(coalCode);
|
wfFire.setCameraCode(ipccode);
|
wfFire.setCameraName(ipcname);
|
wfFire.setRtspUrl(ipcrtsppath);
|
wfFire.setAnalyse(modelType);
|
wfFire.setAnalyseResult(modelAnalysis);
|
}
|
if (modelCode == "12")//人员跌倒
|
{
|
|
}
|
}
|
|
std::queue<int> quTSJ;//记录提升机运动的判断结果
|
std::queue<int> quBelt;//记录皮带运动判断结果
|
|
int tsjCount;//提升机计数,间隔一段时间,调用一次模型
|
int beltCount;//提升机计数,间隔一段时间,调用一次模型
|
Mat iMatWear;//人员穿戴的第一帧
|
|
long currentFrame = 1;//记录当前帧数
|
long skip_frame_num = skipN;//跳帧间隔设置
|
Mat frame;
|
while (!asyncStop)
|
{
|
//std::cout << ipccode + "当前线程待处理队列数量1111:" << queJC.size() << std::endl;
|
|
if (queJC.size() < 1)//队列里有一定数量帧的时候,再开始处理
|
continue;
|
|
try
|
{
|
// 在操作队列之前先锁定互斥锁
|
std::unique_lock<std::mutex> lck(mtx);
|
frame = queJC.front().clone();
|
queJC.pop();
|
lck.unlock();
|
|
if (frame.empty())
|
continue;
|
|
if (currentFrame % skip_frame_num == 0) //跳帧处理
|
{
|
///////////////////////////////////执行异步任务///////////////////////////////////////////////
|
|
//皮带运行算法处理及判断 modelId = 1
|
if (rBelt.isLoad)
|
{
|
futureBelt = std::async(std::launch::async, &PreProcessModel::fnBeltMoveRec, &ppm, std::ref(frame), std::ref(imagesBelt), ref(beltCount), std::ref(rBelt), areaBelt);
|
}
|
|
//提升机模型处理及判断 modelId = 2
|
if (rTSJ.isLoad)
|
{
|
futureTSJ = std::async(std::launch::async, &PreProcessModel::fnImRecProByModelTSJ, &ppm, std::ref(frame), std::ref(imagesTsj), ref(tsjCount), std::ref(rTSJ), std::ref(quTSJ), areaTSJ);
|
}
|
|
//人员闯入模型处理及判断 modelId = 3
|
if (hatJC.isLoad)
|
{
|
futurePerson = std::async(std::launch::async, &PreProcessModel::fnImRecProByModelHAT1, &ppm, std::ref(frame), std::ref(hatJC), areaPerson,workareaPerson,c_list,lable_title,color_result);
|
}
|
|
//摄像头移动和遮挡专用
|
auto cameraRecordTime = std::chrono::system_clock::now() + std::chrono::hours(-1);//记录最后一次调用摄像头移动算法时间,间隔1小时调用一次摄像头移动和遮挡算法
|
std::chrono::duration<double> timeDifference = std::chrono::system_clock::now() - cameraRecordTime;
|
if (timeDifference.count() >= 3600)//间隔1个小时检测一次摄像头移动和遮挡
|
{
|
//摄像头遮挡算法处理及判断 modelId = 4
|
if (cover.isLoad)
|
{
|
futureCameraCover = std::async(std::launch::async, &PreProcessModel::fnCameraCoverRec, &ppm, std::ref(frame), std::ref(cover));
|
}
|
|
//摄像头移动算法处理及判断 modelId = 5
|
if (camera.isLoad)
|
{
|
futureCameraMove = std::async(std::launch::async, &PreProcessModel::fnCameraMoveRec, &ppm, std::ref(frame), std::ref(camera));
|
}
|
|
cameraRecordTime = std::chrono::system_clock::now();//重新计时
|
}
|
|
//堆煤模型处理及判断 modelId = 6
|
if (dm.isLoad)
|
{
|
futureDM = std::async(std::launch::async, &PreProcessModel::fnImRecProByModelDM, &ppm, std::ref(frame), std::ref(dm), areaDM);
|
}
|
|
//皮带跑偏和异物检测模型处理及判断 modelId = 7
|
if (beltJC.isLoad)
|
{
|
futureBeltJC = std::async(std::launch::async, &PreProcessModel::fnImRecProByModelBeltJC2, &ppm, std::ref(frame), std::ref(beltJC), leftareaBeltJC,rightareaBeltJC,areaBeltJC);
|
}
|
|
//乘猴车携带大件 modelId = 8
|
if (hatHC.isLoad)
|
{
|
futureHC = std::async(std::launch::async, &PreProcessModel::fnImRecProByModelHATHC, &ppm, std::ref(frame), std::ref(hatHC), areaHC);
|
}
|
|
//睡岗 modelId = 9
|
if (hatSleep.isLoad)
|
{
|
futureSleep = std::async(std::launch::async, &PreProcessModel::fnImRecProByModelHATSleep, &ppm, std::ref(frame), std::ref(hatSleep));
|
}
|
|
//人员穿戴模型处理及判断 11
|
if (hatWear.isLoad)
|
{
|
futureWear = std::async(std::launch::async, &PreProcessModel::fnImRecProByModelWear, &ppm, std::ref(frame), std::ref(hatWear), std::ref(cfWear), areaWear);
|
}
|
|
//烟火模型处理及判断 12
|
if (hatFire.isLoad)
|
{
|
futureFire = std::async(std::launch::async, &PreProcessModel::fnImRecProByModelFire, &ppm, std::ref(frame), std::ref(hatFire));
|
}
|
|
///////////////////////////////////检查异步任务,并得到返回结果///////////////////////////////////////////////
|
//检查异步任务是否开启 modelId = 1
|
if (futureBelt.valid())
|
{
|
beltStatus = futureBelt.get();// 皮带最新运行状态
|
}
|
|
//检查异步任务是否开启 modelId = 2
|
if (futureTSJ.valid())
|
{
|
tsjStatus = futureTSJ.get();// 等待返回提升机运行状态
|
}
|
|
//检查异步任务是否开启 modelId = 3
|
if (futurePerson.valid()) {
|
personResult = futurePerson.get();// 等待返回是否人员闯入
|
}
|
|
//检查异步任务是否开启 modelId = 4
|
if (futureCameraCover.valid())
|
{
|
cameracover = futureCameraCover.get();// 获取摄像头遮挡状态
|
}
|
|
//检查异步任务是否开启 modelId = 5
|
if (futureCameraMove.valid())
|
{
|
cameramove = futureCameraMove.get();// 获取摄像头移动状态
|
}
|
|
//检查异步任务是否开启 modelId = 6
|
if (futureDM.valid())
|
{
|
proportion = futureDM.get();// 等待返回堆煤占比
|
|
//跳帧保存数据
|
if (currentFrame % (skip_frame_num*5) == 0) //跳帧处理,每间隔一定帧数保存一次记录
|
{
|
// 实时写入煤流量
|
std::string query = "CALL insert_or_update_CoalFlow(" + ipccode + ", " + std::to_string(proportion) + ")";
|
|
// 检查连接是否仍然有效
|
if (mysql_ping(mysql) == 0) {
|
//std::cout << "连接 MySQL 数据库成功" << std::endl;
|
if (mysql_query(mysql, query.c_str())) {
|
string err_string = mysql_error(mysql);
|
cout << err_string << endl;
|
}
|
}
|
else {
|
//重新连接数据库
|
if (!mysql_real_connect(mysql, mysqlpath.c_str(), mysqluser.c_str(), mysqlpass.c_str(), mysqldatabase.c_str(), stoi(mysqlport), NULL, 0))
|
{
|
std::cout << "连接 MySQL 数据库失败: " << mysql_error(mysql) << std::endl;
|
mysql_close(mysql); // 关闭连接
|
}
|
|
//mysql_set_character_set(mysql, "utf8mb4");
|
mysql_query(mysql, "SET NAMES GB2312");//解决中文乱码问题
|
}
|
}
|
}
|
|
//皮带检测异步任务是否开启 modelId = 7
|
if (futureBeltJC.valid())
|
{
|
beltJCResult = futureBeltJC.get();// 等待返回是否皮带检测结果
|
}
|
|
//乘猴车携带大件 modelId = 8
|
if (futureHC.valid()) {
|
hcResult = futureHC.get();// 等待返回结果
|
}
|
|
//睡岗 modelId = 9
|
if (futureSleep.valid()) {
|
sleepResult = futureSleep.get();// 等待返回睡岗人员数量
|
}
|
|
//人员穿戴 11
|
if (futureWear.valid()) {
|
resultWear = futureWear.get();// 等待返回人员穿戴结果
|
}
|
|
//烟火检测 12
|
if (futureFire.valid()) {
|
resultFire = futureFire.get();// 等待返回烟火结果
|
}
|
|
queJC2.push(frame);// 推到视频推流队列
|
|
string filefolder = fnCreateFileFolder(warningFilePath);//生成文件夹路径
|
string videoPath;//录像保存路径
|
string firstImagPath;//录像的第一张图片
|
double seconds;
|
|
#pragma region 进行判断报警录像处理
|
// 皮带运行状态变化报警 1
|
if (beltStatus != -1 && beltStatus != beltStatusold && !video_writerBelt.isOpened())
|
{
|
beltStatus = beltStatusold;//皮带状态保持一致
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimeBelt).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << "皮带运行触发报警录像后,开始保存10秒视频" << endl;
|
start_timeBelt = std::chrono::system_clock::now();
|
videoTimeBelt = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
if (beltStatus == 0)//运输
|
{
|
videoPath = filefolder + videoPathBelt + rBelt.analysis1 + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称;
|
firstImagPath = filefolder + videoPathBelt + rBelt.analysis1 + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
}
|
else//停止
|
{
|
videoPath = filefolder + videoPathBelt + rBelt.analysis2 + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称;
|
firstImagPath = filefolder + videoPathBelt + rBelt.analysis2 + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
}
|
//cv::resize(frame, frame, Size(640, 480));
|
// 创建VideoWriter对象
|
video_writerBelt = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfBelt.setRecordFileName(videoPath);
|
wfBelt.setrecordImgFileName(firstImagPath);
|
|
fnVideoRecordToMysql(frame, 1, video_writerBelt, start_timeBelt, wfBelt, mysql, recordtime);
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
}
|
|
}
|
else
|
{
|
if (beltStatus != -1)
|
beltStatus = beltStatusold;//皮带状态保持一致
|
|
if (video_writerBelt.isOpened())
|
{
|
//cv::resize(frame, frame, Size(640, 480));
|
fnVideoRecordToMysql(frame, 0, video_writerBelt, start_timeBelt, wfBelt, mysql, recordtime);
|
|
}
|
}
|
|
// 提升机状态变化报警 2
|
if (tsjStatus != -1 && tsjStatus != tsjStatusold && !video_writerTSJ.isOpened())
|
{
|
tsjStatusold = tsjStatus;//提升机保持状态一致
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimeTSJ).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << "提升机触发报警录像后,开始保存10秒视频" << endl;
|
start_timeTSJ = std::chrono::system_clock::now();
|
videoTimeTSJ = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
if (tsjStatus == 0)//运输
|
{
|
videoPath = filefolder + videoPathTSJ + rTSJ.analysis1 + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称;
|
firstImagPath = filefolder + videoPathTSJ + rTSJ.analysis1 + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
}
|
else//停止
|
{
|
videoPath = filefolder + videoPathTSJ + rTSJ.analysis2 + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称;
|
firstImagPath = filefolder + videoPathTSJ + rTSJ.analysis2 + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
}
|
//cv::resize(frame, frame, Size(640, 480));
|
// 创建VideoWriter对象
|
video_writerTSJ = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfTSJ.setRecordFileName(videoPath);
|
wfTSJ.setrecordImgFileName(firstImagPath);
|
|
fnVideoRecordToMysql(frame, 1, video_writerTSJ, start_timeTSJ, wfTSJ, mysql, recordtime);
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
}
|
}
|
else
|
{
|
if (tsjStatus != -1)
|
tsjStatusold = tsjStatus;//提升机保持状态一致
|
|
if (video_writerTSJ.isOpened())
|
{
|
cv::resize(frame, frame, Size(640, 480));
|
fnVideoRecordToMysql(frame, 0, video_writerTSJ, start_timeTSJ, wfTSJ, mysql, recordtime);
|
}
|
}
|
|
//人员闯入或者未戴安全帽报警 3
|
if (!video_writerPerson.isOpened() && personResult.size() > 0
|
&& ((areaPerson.size()>0 && personResult[0] > 0) //人员闯入判断
|
|| personResult[1] > 0 //未带安全帽判断
|
|| (workareaPerson.size()>0 && personResult[2] <= 0))//离岗判断
|
)
|
{
|
string videotitle = "";
|
|
if (personResult[0] > 0)
|
{
|
videotitle = "人员闯入";
|
}
|
|
if (personResult[1] > 0)
|
{
|
videotitle = videotitle + " 未佩戴安全帽";
|
}
|
|
if (personResult[2] <= 0)
|
{
|
videotitle = videotitle + " 人员脱岗离岗";
|
}
|
|
wfPerson.setAnalyseResult(videotitle);
|
|
personResult[0] = 0;//人员闯入标志复位
|
personResult[1] = 0;//未带安全帽标志复位
|
personResult[2] = 0;//工作区域离岗标志复位
|
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimePerson).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << videotitle << "触发报警录像后,开始保存10秒视频" << endl;
|
start_timePerson = std::chrono::system_clock::now();
|
videoTimePerson = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathPerson + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathPerson + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerPerson = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfPerson.setRecordFileName(videoPath);
|
wfPerson.setrecordImgFileName(firstImagPath);
|
|
fnVideoRecordToMysql(frame, 1, video_writerPerson, start_timePerson, wfPerson, mysql, recordtime);
|
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
}
|
}
|
else
|
{
|
if (video_writerPerson.isOpened())
|
{
|
fnVideoRecordToMysql(frame, 0, video_writerPerson, start_timePerson, wfPerson, mysql , recordtime);
|
}
|
}
|
|
//摄像头遮挡报警 4
|
if (cameracover == 1 && !video_writerCameraCover.isOpened())
|
{
|
cameracover = 0;//标志复位
|
|
cout << "摄像头遮挡触发报警录像后,开始保存10秒视频" << endl;
|
start_timeCameraCover = std::chrono::system_clock::now();
|
//videoTimeCameraCover = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathCameraCover + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathCameraCover + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerCameraCover = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfCameraCover.setRecordFileName(videoPath);
|
wfCameraCover.setrecordImgFileName(firstImagPath);
|
|
fnVideoRecordToMysql(frame, 1, video_writerCameraCover, start_timeCameraCover, wfCameraCover, mysql , recordtime);
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
}
|
else
|
{
|
if (video_writerCameraCover.isOpened())
|
{
|
fnVideoRecordToMysql(frame, 0, video_writerCameraCover, start_timeCameraCover, wfCameraCover, mysql , recordtime);
|
}
|
}
|
|
//摄像头移动报警 5
|
if (cameramove == 1 && !video_writerCameraMove.isOpened())
|
{
|
cameramove = 0;//标志复位
|
|
cout << "摄像头移动触发报警录像后,开始保存10秒视频" << endl;
|
start_timeCameraMove = std::chrono::system_clock::now();
|
//videoTimeCameraMove = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathCameraMove + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathCameraMove + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerCameraMove = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfCameraMove.setRecordFileName(videoPath);
|
wfCameraMove.setrecordImgFileName(firstImagPath);
|
|
fnVideoRecordToMysql(frame, 1, video_writerCameraMove, start_timeCameraMove, wfCameraMove, mysql , recordtime);
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
}
|
else
|
{
|
if (video_writerCameraMove.isOpened())
|
{
|
fnVideoRecordToMysql(frame, 1, video_writerCameraMove, start_timeCameraMove, wfCameraMove, mysql , recordtime);
|
}
|
}
|
|
// 堆煤报警 6
|
if (proportion > std::stof(limitDM) && !video_writerDM.isOpened())
|
{
|
wfDM.setAnalyseResult("堆煤");
|
|
proportion = 0;//标志复位
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimeDM).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << "堆煤触发报警录像后,开始保存10秒视频" << endl;
|
start_timeDM = std::chrono::system_clock::now();
|
videoTimeDM = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathDM + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathDM + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerDM = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfDM.setRecordFileName(videoPath);
|
wfDM.setrecordImgFileName(firstImagPath);
|
fnVideoRecordToMysql(frame, 1, video_writerDM, start_timeDM, wfDM, mysql, recordtime);
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
}
|
}
|
else
|
{
|
if (video_writerDM.isOpened())
|
{
|
fnVideoRecordToMysql(frame, 0, video_writerDM, start_timeDM, wfDM, mysql, recordtime);
|
}
|
}
|
|
//皮带跑偏,异物报警 7
|
if (!video_writerBeltJC.isOpened() && beltJCResult.size() > 0 && (beltJCResult[0] > 0 || beltJCResult[1] == 0 || beltJCResult[2] > 0))
|
{
|
if (beltJCResult[0] > 0 )
|
{
|
wfBeltJC.setAnalyseResult("大煤块");
|
}
|
else if (beltJCResult[1] == 0)
|
{
|
wfBeltJC.setAnalyseResult("皮带跑偏");
|
}
|
else if (beltJCResult[2] > 0)
|
{
|
wfBeltJC.setAnalyseResult("大块异物");
|
}
|
else
|
{
|
wfBeltJC.setAnalyseResult("");
|
}
|
|
beltJCResult[0] = 0;//大煤块标志复位
|
beltJCResult[1] = 1;//标志复位 0为跑偏 1为不跑偏
|
beltJCResult[2] = 0;//异物标志复位
|
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimeBeltJC).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << "皮带跑偏,大煤块,异物触发报警录像后,开始保存10秒视频" << endl;
|
start_timeBeltJC = std::chrono::system_clock::now();
|
videoTimeBeltJC = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathBeltJC + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathBeltJC + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerBeltJC = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfBeltJC.setRecordFileName(videoPath);
|
wfBeltJC.setrecordImgFileName(firstImagPath);
|
|
fnVideoRecordToMysql(frame, 1, video_writerBeltJC, start_timeBeltJC, wfBeltJC, mysql, recordtime);
|
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
}
|
}
|
else
|
{
|
if (video_writerBeltJC.isOpened())
|
{
|
fnVideoRecordToMysql(frame, 0, video_writerBeltJC, start_timeBeltJC, wfBeltJC, mysql, recordtime);
|
}
|
}
|
|
// 猴车携带大件 8
|
if (hcResult.size() >0 && hcResult[0] > 0 && !video_writerHC.isOpened())
|
{
|
wfHC.setAnalyseResult("猴车携带大件");
|
|
hcResult[0] = 0;//标志复位
|
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimeHC).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << "猴车携带大件触发报警录像后,开始保存10秒视频" << endl;
|
start_timeHC = std::chrono::system_clock::now();
|
videoTimeHC = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathHC + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathHC + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerHC = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfHC.setRecordFileName(videoPath);
|
wfHC.setrecordImgFileName(firstImagPath);
|
|
fnVideoRecordToMysql(frame, 1, video_writerHC, start_timeHC, wfHC, mysql, recordtime);
|
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
}
|
}
|
else
|
{
|
if (video_writerHC.isOpened())
|
{
|
fnVideoRecordToMysql(frame, 0, video_writerHC, start_timeHC, wfHC, mysql , recordtime);
|
}
|
}
|
|
// 睡岗报警 9
|
if (sleepResult.size() > 0 && sleepResult[0] > 0 && !video_writerSleep.isOpened())
|
{
|
wfSleep.setAnalyseResult("睡岗");
|
|
sleepResult[0] = 0;//标志复位
|
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimeSleep).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << "睡岗触发报警录像后,开始保存10秒视频" << endl;
|
start_timeSleep = std::chrono::system_clock::now();
|
videoTimeSleep = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathSleep + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathSleep + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerSleep = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfSleep.setRecordFileName(videoPath);
|
wfSleep.setrecordImgFileName(firstImagPath);
|
|
fnVideoRecordToMysql(frame, 1, video_writerSleep, start_timeSleep, wfSleep, mysql, recordtime);
|
|
//保存第一张图片
|
cv::imwrite(firstImagPath, frame);
|
|
}
|
}
|
else
|
{
|
if (video_writerSleep.isOpened())
|
{
|
fnVideoRecordToMysql(frame, 0, video_writerSleep, start_timeSleep, wfSleep, mysql, recordtime);
|
|
}
|
}
|
|
// 人员穿戴报警 11
|
if (resultWear.size() > 0 && !video_writerWear.isOpened())
|
{
|
string AnalyseResult = "";
|
//初始化上一次的结果记录
|
if (resultWearold.size() == 0)
|
{
|
resultWearold = resultWear;
|
iMatWear = frame;//记录进入的第一个人图像
|
}
|
|
if (resultWear[0] == 0)//检测框内没人
|
{
|
if (resultWearold[0] == 1)//原来检测区域有人,则表示检测完毕,进行判断处理
|
{
|
if (resultWearold[1] < 1)
|
{
|
AnalyseResult+="未佩戴安全帽";
|
}
|
|
if (resultWearold[2] < 1)
|
{
|
|
AnalyseResult += " 未携带自救器";
|
}
|
|
if (resultWearold[3] < 1)
|
{
|
AnalyseResult += " 未穿胶鞋";
|
}
|
|
if (resultWearold[4] < 1)
|
{
|
AnalyseResult += " 未穿工作服";
|
}
|
|
//wfWear.setAnalyse("AI-11-03");
|
wfWear.setAnalyseResult(AnalyseResult);
|
|
resultWear.clear();
|
resultWearold.clear();//判断完成后清空保留的状态
|
}
|
else
|
{
|
resultWearold = resultWear;
|
}
|
}
|
else if (resultWear[0] == 1)//检测框内有1人
|
{
|
resultWearold[0] = resultWear[0];
|
|
if (resultWear[1] == 1)//记录安全帽检测结果
|
{
|
resultWearold[1] = 1;
|
}
|
|
if (resultWear[2] == 1)//记录自救器检测结果
|
{
|
resultWearold[2] = 1;
|
}
|
|
if (resultWear[3] == 1)//记录鞋子检测结果
|
{
|
resultWearold[3] = 1;
|
}
|
|
if (resultWear[4] == 1)//记录工作服检测结果
|
{
|
resultWearold[4] = 1;
|
}
|
}
|
else if (resultWear[0]>1)//检测框内有多人
|
{
|
//wfWear.setAnalyseResult("检测框内有多人");
|
cout << "检测框内有多人,检测作废" << endl;
|
resultWear.clear();
|
}
|
|
if (!AnalyseResult.empty())//判断有违规行为
|
{
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimeWear).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << "人员穿戴触发报警录像后,开始保存10秒视频" << endl;
|
start_timeWear = std::chrono::system_clock::now();
|
videoTimeWear = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathWear + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathWear + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerWear = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfWear.setRecordFileName(videoPath);
|
wfWear.setrecordImgFileName(firstImagPath);
|
|
//fnVideoRecord(frame, 1, video_writerWear, start_timeWear, wfWear, context, recordtime);
|
fnVideoRecordToMysql(frame, 1, video_writerWear, start_timeWear, wfWear, mysql, recordtime);
|
|
//保存第一张图片
|
cv::imwrite(firstImagPath, iMatWear);
|
}
|
}
|
}
|
else
|
{
|
if (video_writerWear.isOpened())
|
{
|
//fnVideoRecord(frame, 0, video_writerWear, start_timeWear, wfWear, context, recordtime);
|
fnVideoRecordToMysql(frame, 0, video_writerWear, start_timeWear, wfWear, mysql, recordtime);
|
}
|
}
|
|
// 烟火报警 12
|
if (resultFire.size() > 0 && !video_writerFire.isOpened())
|
{
|
int res = 0;
|
|
//有烟火报警
|
if (resultFire[0] || resultFire[1])
|
{
|
if (vecFire.size() == 0)
|
{
|
firstFire = std::chrono::system_clock::now();//记录第一次报警时间
|
vecFire.push_back(resultFire[0] || resultFire[1]);
|
vecVideoFire.push_back(frame);
|
resultFire[0] = 0;//火标志复位
|
resultFire[1] = 0;//烟标志复位
|
continue;
|
}
|
}
|
|
if (vecFire.size() > 0)//开始计数了
|
{
|
std::chrono::duration<double> timeDifference = std::chrono::system_clock::now() - firstFire;
|
|
if (timeDifference.count() > 5)//大于5秒,进行判断
|
{
|
res = fnJudeRatio(vecFire, 1, 0.6);
|
|
//判断有烟火
|
if (res != 0)
|
{
|
wfFire.setAnalyseResult("烟火报警");
|
seconds = std::chrono::duration<double>(std::chrono::system_clock::now() - videoTimeHC).count();
|
if (seconds > RecIntervalime)
|
{
|
cout << "烟火触发报警录像后,开始保存10秒视频" << endl;
|
start_timeFire = std::chrono::system_clock::now();
|
videoTimeFire = std::chrono::system_clock::now();//重新开始记录最后一次录像时间
|
videoPath = filefolder + videoPathFire + getCurrentDateTime("%Y%m%d%H%M%S") + ".mp4";//录像文件名称
|
firstImagPath = filefolder + videoPathFire + getCurrentDateTime("%Y%m%d%H%M%S") + ".png";
|
// 创建VideoWriter对象
|
video_writerFire = VideoWriter(videoPath, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 20, Size(frame.cols, frame.rows));
|
wfFire.setRecordFileName(videoPath);
|
wfFire.setrecordImgFileName(firstImagPath);
|
|
//fnVideoRecord(frame, 1, video_writerFire, start_timeFire, wfFire, context, recordtime);
|
fnVideoRecordToMysql2(vecVideoFire, 1, video_writerFire, wfFire, mysql);
|
|
//保存第一张图片
|
cv::imwrite(firstImagPath, vecVideoFire[0]);
|
}
|
}
|
|
vecVideoFire.clear();
|
vecFire.clear();
|
}
|
else
|
{
|
vecFire.push_back(resultFire[0] || resultFire[1]);
|
vecVideoFire.push_back(frame);
|
}
|
}
|
|
resultFire[0] = 0;//火标志复位
|
resultFire[1] = 0;//烟标志复位
|
}
|
|
#pragma endregion
|
|
}
|
|
//cv::imwrite("./img/" + std::to_string(currentFrame)+".jpg", frame);
|
//cv::resize(frame, frame, Size(1920, 1080));
|
//cv::imshow(ipccode, frame);//展示帧图片
|
//cv::imshow("ipccode", queJC2.front());//展示帧图片
|
//cv::waitKey(20);
|
|
//std::this_thread::sleep_for(std::chrono::milliseconds(10));// 延迟等待一段时间
|
|
if (currentFrame > 10000) {
|
currentFrame = 0;
|
}
|
|
currentFrame++;
|
}
|
catch (const std::exception& ex)
|
{
|
std::string errorMessage = "处理视频帧失败-";
|
errorMessage += ex.what();
|
cout << errorMessage << endl;
|
|
continue;
|
}
|
}
|
|
frame.release();
|
}
|
|
/// @brief 推流到rabbitmq
|
/// @param queJC2 处理完的视频流帧队列
|
/// @param ipccode 摄像机编号
|
void PreProcessFn::fnPushVideoInRabbitMQ(queue<Mat>& queJC2, string ipccode)
|
{
|
CRabbitmqClient objRabbitmq;
|
int iRet = objRabbitmq.Connect(rabbitpath, stoi(rabbitport), rabbituser, rabbitpass);
|
iRet = objRabbitmq.ExchangeDeclare(ipccode, "fanout");
|
objRabbitmq.Publish("", ipccode, "");
|
printf("Rabbitmq连接状态:%d\n", iRet);
|
std::string imgStr;
|
//定义接受帧
|
Mat frame;
|
|
long currentFrame = 1;
|
long skip_frame_num = skipN;//跳帧间隔设置(每1帧)
|
|
//创建url连接,定时判断有没有页面进行拉流
|
CURL* curl;
|
CURLcode res;
|
std::string readBuffer;
|
curl = curl_easy_init();
|
bool pushflg = true;//是否推流标志
|
|
if(curl)
|
{
|
string url = "http://" + rabbitpath + ":1" + rabbitport + "/api/exchanges/%2F/"+ ipccode + "/bindings/source";
|
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
// 如果需要验证身份,请设置用户名和密码,例如 "admin:admin"
|
curl_easy_setopt(curl, CURLOPT_USERNAME, rabbituser.c_str());
|
curl_easy_setopt(curl, CURLOPT_PASSWORD, rabbitpass.c_str());
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
}
|
|
while (!asyncStop) {
|
//std::cout << ipccode + "当前线程Rabbitmq数据数量2222:" << queJC2.size() << std::endl;
|
try
|
{
|
if (queJC2.size() > 500)
|
{
|
cout << "推送视频时,存在内存溢出风险!" << endl;
|
}
|
|
if (queJC2.empty() || queJC2.size() == 0)
|
{
|
continue;
|
}
|
|
//加锁,防止别的系统操作这段内存
|
std::unique_lock<std::mutex> lck(mtx);
|
frame = queJC2.front();
|
queJC2.pop();
|
lck.unlock();
|
|
if (frame.empty())//帧为空,则舍弃
|
continue;
|
|
if (currentFrame % 20 == 0) //每20帧,判断一次是否有页面拉流
|
{
|
//通过API获取指定exchange对应的queue
|
res = curl_easy_perform(curl);
|
if(res != CURLE_OK)
|
{
|
pushflg = false;//不可推流
|
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
|
continue;
|
}
|
else
|
{
|
//std::cout << readBuffer << std::endl;
|
//对应的exchange中,有queue,则进行推流
|
if(readBuffer.length()>5)
|
{
|
pushflg = true; //可推流
|
}
|
else
|
{
|
pushflg = false;//不可推流
|
}
|
}
|
}
|
|
//pushflg=true;//test
|
|
//如果为true则推流
|
if(pushflg)
|
{
|
|
if (iRet != 0)
|
{
|
//重新连接并发送
|
objRabbitmq.Connect(rabbitpath, stoi(rabbitport), rabbituser, rabbitpass);
|
objRabbitmq.ExchangeDeclare(ipccode, "fanout");
|
}
|
|
//cv::imwrite("./img/" + ipccode +".jpg", frame);
|
////压缩图片
|
//cv::resize(frame, frame, Size(1280, 720));
|
|
imgStr = Mat2Base64(frame, ".jpg");//输出Base64编码的字符串
|
//std::cout << "Base64 size: " << imgStr.size() << std::endl;
|
objRabbitmq.Publish(imgStr, ipccode, "");
|
|
//cv::resize(frame, frame, Size(1280, 720));
|
//cv::imshow(ipccode, frame);//展示帧图片
|
//waitKey(5);
|
}
|
|
|
readBuffer.clear();
|
|
//std::this_thread::sleep_for(std::chrono::milliseconds(10));// 延迟等待一段时间
|
|
if (currentFrame > 10000) {
|
currentFrame = 0;
|
}
|
|
currentFrame++;
|
|
}
|
catch (const std::exception& ex)
|
{
|
std::string errorMessage = "保存到RabbitMQ失败:-";
|
errorMessage += ex.what();
|
cout << errorMessage << endl;
|
continue;
|
}
|
}
|
|
curl_easy_cleanup(curl);
|
frame.release();
|
}
|
|
/// @brief 推流到流媒体服务器
|
/// @param queJC2 处理完的视频流帧队列
|
/// @param ipccode 摄像机编号
|
void PreProcessFn::fnPushVideo(queue<Mat>& queJC2, string ipccode)
|
{
|
//定义接受帧
|
Mat frame;
|
|
vector<string> arguments = {
|
"ffmpeg "
|
"-hwaccel","cuvid",
|
"-hwaccel_output_format","cuda",
|
"-y", "-an",
|
"-f", "rawvideo",
|
"-vcodec", "rawvideo",
|
"-pix_fmt", "bgr24",
|
"-s", "640x480",
|
"-r", "15",
|
"-i", "-",
|
"-pix_fmt", "yuv420p",
|
"-f", "flv",
|
"-max_delay", "1000",
|
"-flvflags", "no_duration_filesize",
|
"-c:v","h264_nvenc",
|
"-b:v", "3M",
|
"-g:v", "15",
|
"-bf", "0",
|
"-bufsize", "50000000",
|
"-rtbufsize", "50000000",
|
"rtmp://192.168.1.8:1935/live/camera1" };
|
|
string ffmpeg_command = join(arguments, " ");
|
|
// 打开FFmpeg进程
|
FILE* pipe = popen(ffmpeg_command.c_str(), "w");
|
if (!pipe) {
|
std::cerr << "无法启动FFmpeg" << std::endl;
|
}
|
|
while (!asyncStop) {
|
//std::cout << ipccode + "当前线程Rabbitmq数据数量2222:" << queJC2.size() << std::endl;
|
try
|
{
|
if (queJC2.size() > 500)
|
{
|
cout << "推送视频时,存在内存溢出风险!" << endl;
|
}
|
|
if (queJC2.empty() || queJC2.size() == 0)
|
{
|
continue;
|
}
|
|
frame = queJC2.front();
|
queJC2.pop();
|
|
if (frame.empty())//帧为空,则舍弃
|
continue;
|
|
|
// 将帧写入到FFmpeg管道中
|
fwrite(frame.data, 1, frame.total() * frame.elemSize(), pipe);
|
|
//cv::resize(frame, frame, Size(1280, 720));
|
//cv::imshow(ipccode, frame);//展示帧图片
|
//waitKey(10);
|
|
//std::this_thread::sleep_for(std::chrono::milliseconds(10));// 延迟等待一段时间
|
|
}
|
catch (const std::exception& ex)
|
{
|
std::string errorMessage = "保存到RabbitMQ失败:-";
|
errorMessage += ex.what();
|
cout << errorMessage << endl;
|
continue;
|
}
|
}
|
|
frame.release();
|
}
|
|
|
|
/// @brief 推流到流媒体服务器
|
/// @param queJC2 处理完的视频流帧队列
|
/// @param ipccode 摄像机编号
|
void PreProcessFn::fnPushVideoToUrl(queue<Mat>& queJC2,string toRtsp, string fps, string ipccode)
|
{
|
//定义接受帧
|
Mat frame;
|
|
vector<string> arguments = {
|
"ffmpeg "
|
"-hwaccel","cuvid",
|
"-hwaccel_output_format","cuda",
|
"-y", "-an",
|
"-f", "rawvideo",
|
"-vcodec", "rawvideo",
|
"-pix_fmt", "bgr24",
|
"-s", "1280x720",
|
"-r", fps,
|
"-i", "-",
|
"-pix_fmt", "yuv420p",
|
"-f", "flv",
|
"-max_delay", "1000",
|
"-flvflags", "no_duration_filesize",
|
"-c:v","h264_nvenc",
|
"-b:v", "3M",
|
"-g:v", "15",
|
"-bf", "0",
|
"-bufsize", "50000000",
|
"-rtbufsize", "50000000",
|
toRtsp };
|
|
string ffmpeg_command = join(arguments, " ");
|
|
// 打开FFmpeg进程
|
FILE* pipe = popen(ffmpeg_command.c_str(), "w");
|
if (!pipe) {
|
std::cerr << "无法启动FFmpeg" << std::endl;
|
}
|
|
while (!asyncStop) {
|
//std::cout << ipccode + "当前线程Rabbitmq数据数量2222:" << queJC2.size() << std::endl;
|
try
|
{
|
if (queJC2.size() > 500)
|
{
|
cout << "推送视频时,存在内存溢出风险!" << endl;
|
}
|
|
if (queJC2.empty() || queJC2.size() == 0)
|
{
|
continue;
|
}
|
|
frame = queJC2.front();
|
queJC2.pop();
|
|
if (frame.empty())//帧为空,则舍弃
|
continue;
|
|
// 将帧写入到FFmpeg管道中
|
fwrite(frame.data, 1, frame.total() * frame.elemSize(), pipe);
|
|
//cv::resize(frame, frame, Size(1280, 720));
|
//cv::imshow(ipccode, frame);//展示帧图片
|
//waitKey(10);
|
|
//std::this_thread::sleep_for(std::chrono::milliseconds(10));// 延迟等待一段时间
|
|
}
|
catch (const std::exception& ex)
|
{
|
std::string errorMessage = "保存到RabbitMQ失败:-";
|
errorMessage += ex.what();
|
cout << errorMessage << endl;
|
continue;
|
}
|
}
|
|
frame.release();
|
}
|