报警输出完成
This commit is contained in:
Binary file not shown.
@@ -3,7 +3,8 @@
|
||||
1.推流摄像头画面,使用UDP原生协议进行推流,交由YOLO模型进行处理
|
||||
2.接收YOLO传来的坐标和度数据
|
||||
3.根据获取到的数据绘制边框和相应数据
|
||||
4.将绘制完毕的视频流继续推流至RTSP服务器用于输出
|
||||
4.根据距离信息进行报警和图片视频保存
|
||||
5.将绘制完毕的视频流继续推流至RTSP服务器用于输出
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
@@ -55,6 +56,8 @@ mutex alertMutex; // 保护alertQueue的互斥锁
|
||||
condition_variable alertcv; // 通知报警线程有新任务
|
||||
queue<nlohmann::json> alertQueue; // 存放解析后的数据
|
||||
std::atomic<bool> alertWorkerRunning{false}; // 工作线程运行标志
|
||||
atomic<bool> outPutMode = false; // 保存报警输出false--电平
|
||||
// atomic<bool> currentFrameHasDanger{false}; // 是否进行了报警
|
||||
|
||||
// mqtt初始化
|
||||
void MqttInit();
|
||||
@@ -72,8 +75,14 @@ void mainLoop(VideoCapture &cap, FILE *pipe);
|
||||
void getMsgCallback(mqtt::const_message_ptr msg);
|
||||
// 绘制矩形方框和深度信息
|
||||
void drawRect(int x, int y, int w, int h, double distance);
|
||||
// 获取报警距离
|
||||
// 报警线程
|
||||
void warnThread();
|
||||
// 获取报警距离和输出模式
|
||||
bool GetDistance();
|
||||
// 调用报警输出程序
|
||||
void setGPIOLevel(int level);
|
||||
// // 状态机
|
||||
// void warnStatus();
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -102,6 +111,135 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 调用报警输出程序
|
||||
void setGPIOLevel(int level)
|
||||
{
|
||||
string cmd = "echo 'orangepi' | sudo -S /home/orangepi/RKApp/GPIOSignal/bin/sendGpioSignal " + to_string(level);
|
||||
system(cmd.c_str());
|
||||
}
|
||||
|
||||
// // 状态机
|
||||
// void warnStatus()
|
||||
// {
|
||||
// thread([]()
|
||||
// {
|
||||
// bool isAlarm = false;
|
||||
// auto lastDangerTime = chrono::steady_clock::now();
|
||||
// while(alertWorkerRunning.load())
|
||||
// {
|
||||
|
||||
// } });
|
||||
// }
|
||||
|
||||
// 报警线程
|
||||
void warnThread()
|
||||
{
|
||||
// 开启报警线程
|
||||
thread([]()
|
||||
{
|
||||
//状态变量
|
||||
bool isAlarming = false; //报警状态
|
||||
auto lastDangerTime = chrono::steady_clock::now(); //上次报警时间
|
||||
|
||||
//读取配置设置初始状态
|
||||
GetDistance();
|
||||
int normalLevel = outPutMode?0:1; //false:正常高,输出低,true:正常低,输出高
|
||||
int alarmLevel = outPutMode?1:0; //报警输出,true:报警高,false:报警低
|
||||
|
||||
cout << "normalLevel = " << normalLevel <<",alarmLevel = " << alarmLevel << endl;
|
||||
|
||||
//设置初始状态为正常状态
|
||||
setGPIOLevel(normalLevel);
|
||||
|
||||
while (alertWorkerRunning.load())
|
||||
{
|
||||
unique_lock<mutex> lk(alertMutex);
|
||||
// 等待条件,队列非空或者收到停止信号
|
||||
if(isAlarming)
|
||||
{ //如果触发报警,就每每100ms检查一次
|
||||
alertcv.wait_for(lk,100ms,[](){
|
||||
return !alertQueue.empty() || !alertWorkerRunning.load();});
|
||||
}
|
||||
else{
|
||||
//没有触发报警,就死等
|
||||
alertcv.wait(lk,[](){
|
||||
return !alertQueue.empty() || !alertWorkerRunning.load();});
|
||||
}
|
||||
|
||||
|
||||
//如果线程应退出切队列为空,退出循环
|
||||
if(alertQueue.empty() && !alertWorkerRunning.load())
|
||||
break;
|
||||
|
||||
//当前帧是否触发报警
|
||||
bool currentFrameHasDanger = false;
|
||||
|
||||
//处理队列中的所有信号
|
||||
while(!alertQueue.empty())
|
||||
{
|
||||
auto job = move(alertQueue.front());
|
||||
alertQueue.pop(); //释放空指针
|
||||
//解锁,以便于增加队列任务
|
||||
lk.unlock();
|
||||
|
||||
//报警处理函数
|
||||
try
|
||||
{
|
||||
//获取报警距离
|
||||
GetDistance();
|
||||
|
||||
// 更新电平定义(防止运行时修改了配置文件)
|
||||
normalLevel = outPutMode ? 0 : 1;
|
||||
alarmLevel = outPutMode ? 1 : 0;
|
||||
|
||||
for(auto&ii:job)
|
||||
{
|
||||
if(ii["distance"] <= dis.danger)
|
||||
{ //触发警报
|
||||
currentFrameHasDanger = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
|
||||
lk.lock(); //重新上锁,以继续处理下个任务
|
||||
|
||||
}
|
||||
|
||||
//逻辑处理,状态机
|
||||
if(currentFrameHasDanger)
|
||||
{
|
||||
lastDangerTime = chrono::steady_clock::now();
|
||||
if(!isAlarming)
|
||||
{
|
||||
//刚进入报警状态
|
||||
isAlarming = true;
|
||||
setGPIOLevel(alarmLevel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//当前帧没有危险,检测是否需要恢复
|
||||
if(isAlarming)
|
||||
{
|
||||
auto now = chrono::steady_clock::now();
|
||||
auto dur = chrono::duration_cast<chrono::seconds>(now - lastDangerTime).count();
|
||||
if(dur >= 2)
|
||||
{//超过两秒恢复正常
|
||||
isAlarming=false;
|
||||
setGPIOLevel(normalLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} })
|
||||
.detach();
|
||||
}
|
||||
|
||||
// 获取报警距离
|
||||
bool GetDistance()
|
||||
{
|
||||
@@ -123,6 +261,12 @@ bool GetDistance()
|
||||
dis.warn = stoi(line.substr(sizeof("MID_THRESHOLD=") - 1));
|
||||
else if (line.find("MAX_DISTANCE=") != string::npos)
|
||||
dis.safe = stoi(line.substr(sizeof("MAX_DISTANCE=") - 1));
|
||||
else if (line.find("outPutMode:") != string::npos)
|
||||
{
|
||||
// 确认输电平模式
|
||||
string val = line.substr(sizeof("outPutMode:"));
|
||||
outPutMode = (val == "true");
|
||||
}
|
||||
}
|
||||
|
||||
rf.Close();
|
||||
@@ -148,7 +292,7 @@ void drawRect(int x, int y, int w, int h, double distance)
|
||||
sca = Scalar(0, 255, 0);
|
||||
|
||||
rectangle(handleFrame, r, sca, 2);
|
||||
putText(handleFrame,to_string(distance),Point(x,y),FONT_HERSHEY_SIMPLEX,0.35,Scalar(0,0,0));
|
||||
putText(handleFrame, to_string(distance), Point(x, y), FONT_HERSHEY_SIMPLEX, 0.35, Scalar(0, 0, 0));
|
||||
}
|
||||
|
||||
// mqtt初始化
|
||||
@@ -163,43 +307,10 @@ void MqttInit()
|
||||
client.connect()->wait();
|
||||
client.subscribe(Topic, Qos)->wait();
|
||||
|
||||
// 开启报警线程
|
||||
thread([]()
|
||||
{
|
||||
while (alertWorkerRunning.load())
|
||||
{
|
||||
unique_lock<mutex> lk(alertMutex);
|
||||
// 等待条件,队列非空或者收到停止信号
|
||||
alertcv.wait(lk,[](){
|
||||
return !alertQueue.empty() || !alertWorkerRunning.load();});
|
||||
alertWorkerRunning = true;
|
||||
|
||||
//如果线程应退出切队列为空,退出循环
|
||||
if(alertQueue.empty() && !alertWorkerRunning.load())
|
||||
break;
|
||||
|
||||
//处理队列中的所有信号
|
||||
while(!alertQueue.empty())
|
||||
{
|
||||
auto job = move(alertQueue.front());
|
||||
alertQueue.pop(); //释放空指针
|
||||
//解锁,以便于增加队列任务
|
||||
lk.unlock();
|
||||
|
||||
//报警处理函数
|
||||
try
|
||||
{
|
||||
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << '\n';
|
||||
}
|
||||
|
||||
lk.lock(); //重新上锁,以继续处理下个任务
|
||||
|
||||
}
|
||||
} })
|
||||
.detach();
|
||||
// 开启线程
|
||||
warnThread();
|
||||
}
|
||||
|
||||
// mqtt接收订阅消息的回调
|
||||
@@ -316,9 +427,8 @@ bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chron
|
||||
// 拷贝视频帧
|
||||
handleFrame = frame;
|
||||
|
||||
// 读取最新检测:短锁获取并将结果拷贝到本地变量
|
||||
vector<Dection> destCopy;
|
||||
|
||||
// 读取最新检测:短锁获取并将结果拷贝到本地变量
|
||||
{
|
||||
lock_guard<mutex> lk(detMutex);
|
||||
destCopy = latestDection; // 复制到本地后释放锁
|
||||
@@ -330,7 +440,11 @@ bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chron
|
||||
drawRect(ii.x, ii.y, ii.w, ii.h, ii.distance);
|
||||
}
|
||||
|
||||
latestDection.clear();
|
||||
// 短锁进行清除
|
||||
{
|
||||
lock_guard<mutex> lk(detMutex);
|
||||
latestDection.clear();
|
||||
}
|
||||
|
||||
// 可选:显示窗口
|
||||
// imshow("测试画面", frame);
|
||||
|
||||
Reference in New Issue
Block a user