已完成软件功能,画面色彩调整未做,自动挂载Tf未做,模型尚未调优

This commit is contained in:
2026-03-05 11:02:56 +08:00
parent 336a19762a
commit 0448084da5
2 changed files with 9099 additions and 4 deletions

View File

@@ -94,6 +94,42 @@ static std::condition_variable latestAlertCv;
static std::optional<std::vector<Dection>> latestAlertDets; // 仅存最新
static std::atomic<uint64_t> latestAlertSeq{0};
// 推流线程:避免 fwrite/ffmpeg 阻塞影响本机显示
static std::mutex g_pipeMutex;
static std::condition_variable g_pipeCv;
static cv::Mat g_pipeFrame; // 最新一帧(固定 640x480 bgr24
static std::atomic<bool> g_pipeRunning{false};
static std::atomic<uint64_t> g_pipeSeq{0};
static void pipeWriterThread(FILE *pipe)
{
uint64_t seen = g_pipeSeq.load(std::memory_order_relaxed);
while (g_pipeRunning.load())
{
cv::Mat local;
{
std::unique_lock<std::mutex> lk(g_pipeMutex);
g_pipeCv.wait(lk, [&]
{ return !g_pipeRunning.load() ||
g_pipeSeq.load(std::memory_order_relaxed) != seen; });
if (!g_pipeRunning.load())
break;
seen = g_pipeSeq.load(std::memory_order_relaxed);
local = g_pipeFrame; // Mat 头拷贝(数据共享)
}
if (!pipe || local.empty())
continue;
const size_t bytes = local.total() * local.elemSize();
(void)fwrite(local.data, 1, bytes, pipe);
// 不要 fflushpipe 已经 _IONBF无缓冲
}
}
// 把阈值/输出模式缓存到内存,避免频繁读文件
struct RuntimeConfig
{
@@ -172,6 +208,10 @@ int main()
return -1;
}
// 推流线程启动(推流阻塞不再影响本机显示)
g_pipeRunning = true;
std::thread(pipeWriterThread, pipe).detach();
// 先加载一次区域,避免首帧没有框
LoadZonesFromEnv();
@@ -838,6 +878,8 @@ FILE *pipeInit()
// 处理单帧
bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chrono::steady_clock::time_point &t0)
{
cap.grab();
cap.grab();
// 读取帧(失败不退出,短休眠重试)
if (!cap.read(frame) || frame.empty())
{
@@ -845,7 +887,7 @@ bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chron
this_thread::sleep_for(50ms);
return true;
}
handleFrame = frame.clone();
handleFrame = frame;
vector<Dection> destCopy;
// 读取最新检测:短锁获取并将结果拷贝到本地变量
@@ -881,9 +923,24 @@ bool processFrame(VideoCapture &cap, FILE *pipe, Mat &frame, int64 &count, chron
else
outFrame = handleFrame;
// 写入管道(推流处理后画面
fwrite(outFrame.data, 1, outFrame.total() * outFrame.elemSize(), pipe);
fflush(pipe);
// 提交给推流线程(丢旧保新
if (pipe && g_pipeRunning.load())
{
// 固定确保 640x480 bgr24
Mat outFrame;
if (handleFrame.cols != 640 || handleFrame.rows != 480)
resize(handleFrame, outFrame, Size(640, 480));
else
outFrame = handleFrame;
{
std::lock_guard<std::mutex> lk(g_pipeMutex);
// clone避免 handleFrame 下一轮被覆盖导致推流线程写到脏数据
g_pipeFrame = outFrame.clone();
g_pipeSeq.fetch_add(1, std::memory_order_relaxed);
}
g_pipeCv.notify_one();
}
// 短锁进行保存
{
@@ -942,6 +999,10 @@ void mainLoop(VideoCapture &cap, FILE *pipe)
// 资源清理
void cleanup(FILE *pipe, VideoCapture &cap)
{
// 停止推流线程
g_pipeRunning = false;
g_pipeCv.notify_all();
// 防御式确保报警线程条件被唤醒
alertWorkerRunning = false;
latestAlertCv.notify_all();