frame
This commit is contained in:
Binary file not shown.
@@ -10,6 +10,11 @@
|
|||||||
#include <opencv4/opencv2/opencv.hpp>
|
#include <opencv4/opencv2/opencv.hpp>
|
||||||
#include <mqtt/async_client.h>
|
#include <mqtt/async_client.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
#include <queue>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace cv;
|
using namespace cv;
|
||||||
@@ -24,7 +29,21 @@ const string Topic = "/video/PersonData";
|
|||||||
const int Qos = 0;
|
const int Qos = 0;
|
||||||
mqtt::async_client client(mqtt_url, clientId);
|
mqtt::async_client client(mqtt_url, clientId);
|
||||||
|
|
||||||
// 函数声明
|
// 保存检测结果
|
||||||
|
struct Dection
|
||||||
|
{
|
||||||
|
int x, y, w, h;
|
||||||
|
double distance;
|
||||||
|
};
|
||||||
|
|
||||||
|
mutex detMutex; // 保护latestDection的互斥锁
|
||||||
|
vector<Dection> latestDection; // 保存最新接收到的检测结果
|
||||||
|
|
||||||
|
mutex alertMutex; // 保护alertQueue的互斥锁
|
||||||
|
condition_variable alertcv; // 通知报警线程有新任务
|
||||||
|
queue<nlohmann::json> alertQueue; // 存放解析后的数据
|
||||||
|
std::atomic<bool> alertWorkerRunning{false}; // 工作线程运行标志
|
||||||
|
|
||||||
// mqtt初始化
|
// mqtt初始化
|
||||||
void MqttInit();
|
void MqttInit();
|
||||||
// 摄像头管道初始化
|
// 摄像头管道初始化
|
||||||
@@ -87,6 +106,44 @@ void MqttInit()
|
|||||||
|
|
||||||
client.connect()->wait();
|
client.connect()->wait();
|
||||||
client.subscribe(Topic, Qos)->wait();
|
client.subscribe(Topic, Qos)->wait();
|
||||||
|
|
||||||
|
// 开启报警线程
|
||||||
|
thread([]()
|
||||||
|
{
|
||||||
|
while (alertWorkerRunning.load())
|
||||||
|
{
|
||||||
|
unique_lock<mutex> lk(alertMutex);
|
||||||
|
// 等待条件,队列非空或者收到停止信号
|
||||||
|
alertcv.wait(lk,[](){
|
||||||
|
return !alertQueue.empty() || !alertWorkerRunning.load();});
|
||||||
|
|
||||||
|
//如果线程应退出切队列为空,退出循环
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
// mqtt接收订阅消息的回调
|
// mqtt接收订阅消息的回调
|
||||||
@@ -98,19 +155,35 @@ void getMsgCallback(mqtt::const_message_ptr msg)
|
|||||||
try {
|
try {
|
||||||
// TODO 处理接收到到的位置数据
|
// TODO 处理接收到到的位置数据
|
||||||
auto json = nlohmann::json::parse(payload);
|
auto json = nlohmann::json::parse(payload);
|
||||||
//绘制 接收到的坐标 的方框
|
|
||||||
thread([json](){
|
|
||||||
for(auto & ii :json)
|
|
||||||
{
|
|
||||||
int x = static_cast<int>(ii["x"]);
|
|
||||||
int y = static_cast<int>(ii["y"]);
|
|
||||||
int w = static_cast<int>(ii["w"]);
|
|
||||||
int h = static_cast<int>(ii["h"]);
|
|
||||||
double distance = static_cast<double>(ii["distance"]);
|
|
||||||
drawRect(x,y,w,h,distance);
|
|
||||||
}
|
|
||||||
}).detach();
|
|
||||||
|
|
||||||
|
vector<Dection> dets;
|
||||||
|
dets.reserve(json.size()); //预分配,减少多次分配
|
||||||
|
for(const auto&ii:json)
|
||||||
|
{
|
||||||
|
Dection d;
|
||||||
|
// 使用静态转换确保类型为整数/浮点
|
||||||
|
d.x = static_cast<int>(ii.value("x", 0));
|
||||||
|
d.y = static_cast<int>(ii.value("y", 0));
|
||||||
|
d.w = static_cast<int>(ii.value("w", 0));
|
||||||
|
d.h = static_cast<int>(ii.value("h", 0));
|
||||||
|
d.distance = static_cast<double>(ii.value("distance", 0.0));
|
||||||
|
|
||||||
|
dets.push_back(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
//原子替换最新检测合集
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lk(detMutex);
|
||||||
|
latestDection = move(dets);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lk(alertMutex);
|
||||||
|
alertQueue.push(move(json)); //push后通知工作线程
|
||||||
|
}
|
||||||
|
|
||||||
|
//唤醒任务线程
|
||||||
|
alertcv.notify_one();
|
||||||
}
|
}
|
||||||
catch (const nlohmann::json::parse_error &e) {
|
catch (const nlohmann::json::parse_error &e) {
|
||||||
cerr << "JSON 解析错误: " << e.what() << "\n原始 payload: " << payload << "\n";
|
cerr << "JSON 解析错误: " << e.what() << "\n原始 payload: " << payload << "\n";
|
||||||
@@ -180,22 +253,29 @@ bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chron
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拷贝视频帧
|
|
||||||
handleFrame = frame;
|
|
||||||
|
|
||||||
// FPS计算与显示
|
|
||||||
++count;
|
|
||||||
auto now = chrono::steady_clock::now();
|
|
||||||
if (chrono::duration_cast<chrono::milliseconds>(now - t0).count() / 1000.0 > 1.0)
|
|
||||||
{
|
|
||||||
string fps = "FPS:" + to_string(count);
|
|
||||||
count = 0;
|
|
||||||
t0 = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 写入管道
|
// 写入管道
|
||||||
fwrite(frame.data, 1, frame.total() * frame.elemSize(), pipe);
|
fwrite(frame.data, 1, frame.total() * frame.elemSize(), pipe);
|
||||||
fflush(pipe);
|
fflush(pipe);
|
||||||
|
|
||||||
|
// 拷贝视频帧
|
||||||
|
handleFrame = frame;
|
||||||
|
|
||||||
|
// 读取最新检测:短锁获取并将结果拷贝到本地变量
|
||||||
|
vector<Dection> destCopy;
|
||||||
|
|
||||||
|
{
|
||||||
|
lock_guard<mutex> lk(detMutex);
|
||||||
|
destCopy = latestDection; // 复制到本地后释放锁
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在主线程上进行绘制
|
||||||
|
for (const auto &ii : destCopy)
|
||||||
|
{
|
||||||
|
drawRect(ii.x, ii.y, ii.w, ii.h, ii.distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
latestDection.clear();
|
||||||
|
|
||||||
// 可选:显示窗口
|
// 可选:显示窗口
|
||||||
// imshow("测试画面", frame);
|
// imshow("测试画面", frame);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user