ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Qt+FFmpeg+OpenCV‑DNN 实现本地或 RTMP/RTSP 实时 YOLOv5 目标检测播放器

Qt+FFmpeg+OpenCV‑DNN 实现本地或 RTMP/RTSP 实时 YOLOv5 目标检测播放器 一、前言本项目完整实现工业可用的视频 AI 播放器FFmpeg 原生解码视频流独立解码线程、独立 AI 检测线程队列满丢弃旧帧断流指数退避重连本地视频 / 图片也支持检测QPainter 绘制检测框可直接编译运行适合二次开发。二、展示本地视频在线视频三、项目简介RTMPFaceYOLOQt FFmpeg OpenCV DNN拉取 RTMP/RTSP/HTTP 直播流、本地视频、图片运行 YOLOv5 ONNX 目标检测画面叠加检测框、类别、置信度左上角悬浮展示解码 FPS、检测 FPS、单帧推理耗时。3.1 核心功能输入源RTMP / RTSP / HTTP 网络流、本地视频文件、单张图片AI 推理OpenCV DNN 加载 YOLOv5s‑ONNX 模型COCO80 类目标检测多线程隔离UI 渲染线程、FFmpeg 解码线程、YOLO 检测线程完全分离流稳定性RTSP over‑tcp、低延迟参数配置网络断开指数退避自动重连背压处理检测队列有界队列满丢弃最旧帧永远处理最新画面延迟不会累积可观测性实时统计解码 FPS、检测 FPS、推理耗时区分 “无检出” 和 “未执行推理”本地文件播放按原视频帧率做时间对齐播放不会倍速飞速播放资源安全FFmpeg 资源统一释放跨线程自定义结构体元类型注册信号槽安全传递检测结果3.2 技术栈C / Qt WidgetsFFmpeg视频流解码、格式转换 sws_scaleOpenCV DNNYOLOv5 ONNX 推理letterbox 预处理、NMS 非极大抑制构建CMake/qmakeWindows/Linux 均可编译四、目录结构RTMPFaceYOLO/ ├── src/ # 源码 │ ├── main.cpp # 程序入口命令行解析、元类型注册、默认拉流地址 │ ├── videoplayer.h/.cpp # VideoPlayerUI渲染 DecodeThreadFFmpeg 解码线程 │ ├── detectthread.h/.cpp # DetectThread有界队列 抽帧检测线程 │ └── detector.h/.cpp # DetectorOpenCV DNN 封装加载/预处理/推理/后处理 ├── models/ │ ├── yolov5s.onnx # fp16转fp32实际加载的模型fp32, COCO 80 类, 输入 640×640 │ └── yolov5s_orig_fp16_opset17.onnx # 原始备用 ├── bin/ # 运行时输出exe Qt/FFmpeg/OpenCV dll ├── build/ # 构建中间产物五、类职责说明类文件职责VideoPlayervideoplayer.cppUI 主窗口管理解码、检测线程生命周期模型路径查找接收帧与检测结果QPainter 绘制框标签FPS 悬浮统计DecodeThreadvideoplayer.cppQThread 子类FFmpeg 拉流解码sws 转 RGB24发送sigImage(QImage)断流指数退避重连本地视频帧率同步DetectThreaddetectthread.cppQThread 子类内置 Detector有界队列满丢旧帧按时间间隔抽帧推理信号回传检测结果Detectordetector.cpp非线程安全ONNX 模型加载、letterbox 预处理、推理、置信度过滤、NMS、坐标反映射仅在检测线程串行调用Detection结构体detector.h单目标检测结果原图 QRect 框、类别 ID、置信度需要Q_DECLARE_METATYPE支持跨线程信号槽六、整体数据流┌─────────────┐ sigImage(QImage RGB888) ┌──────────────┐ │ DecodeThread│ ─────────────────────────► │ VideoPlayer │ │ (FFmpeg解码) │ │ slotShowImage └─────────────┘ └──────┬───────┘ │ submit(img) ▼ ┌──────────────┐ │ DetectThread │ │ 有界队列抽帧 │ └──────┬───────┘ │ Detector::detect() │ ├─ preprocess: letterbox→640×640→blob │ ├─ forward(): ONNX 推理(计时) │ └─ postprocess: 阈值过滤→NMS→坐标反映射 ▼ sigResult(QVectorDetection) ┌──────────────┐ │ VideoPlayer │ │ slotDetection│ │ → render() │ QPainter 画框标签 └──────────────┘main.cpp解析命令行流地址调用VideoPlayer::open(url)如果是图片执行单次检测视频 / 网络流启动DecodeThread开启检测则同时启动DetectThread解码线程输出 RGB888 格式QImage信号发送给 UI 线程UI 保存最新帧把图像提交给检测线程队列检测线程做时间限流距离上次推理不足 100ms 直接跳过调用 Detector 推理推理完成通过信号把检测结果回传给 UIUI 保存上一次检测结果使用QPainter绘制矩形框、类别标签底色刷新界面显示。关键点检测是旁路尽力而为任务画面流畅性完全由解码线程保障检测慢不会拖慢播放。七、核心设计思路视频流如何做到不卡顿现实场景解码 30FPSYOLO CPU 推理只有 3‑6FPS如果每帧都推理或者无限队列延迟会越来越大。本项目采用三流水线并行 丢帧背压策略。表格环节实现机制解码不阻塞 UIFFmpeg 解码放在独立QThread仅通过信号发送 QImageUI 线程只负责渲染解码不阻塞检测检测独立线程有界队列做解耦检测慢不拖累播放队列设置上限队列满丢弃最旧帧永远处理最新画面播放依旧保持高 FPS推理不抢占全部 CPUFFmpeg 解码器设置线程数预留 CPU 资源给 AI 推理避免画面闪烁消失保留上一次检测结果直到新推理结果到达不会因为推理间隔导致检测框瞬间消失本地文件无时间漂移使用QElapsedTimer累计时间解码速度快于文件帧率时主动 sleep 补齐时间渲染轻量化没有新检测结果直接显示原图只有检测更新时才复制图像绘制框核心思想播放和检测解耦画面优先检测尽力而为。八、项目亮点 踩坑记录8.1 亮点QImage 与 cv::Mat 零拷贝包装直接复用 QImage 内存构造 cv::Mat仅 resize 推理输入时才发生内存拷贝降低 CPU 内存开销。有界队列丢弃旧帧队列满丢掉最老帧只保留最新画面杜绝实时流延迟持续上涨是视频 AI 工程非常关键的设计。断流指数退避重连重试间隔 1s→2s→4s最大 30s 封顶sleep 支持中断关闭播放器时可以立刻退出线程不会卡死等待 sleep 结束。FFmpeg 低延迟拉流参数nobuffer、low_delay、rtsp‑transporttcp实现网络流秒开降低缓冲延迟。本地视频帧率对齐不倍速飞速播放按照源视频时间轴播放。完整可观测指标同时展示解码 FPS、检测 FPS、推理耗时方便定位性能瓶颈区分 “没有目标” 和 “还没有执行推理” 两种状态。线程安全处理自定义结构体Detection做元类型注册Detector 明确非线程安全只在检测线程串行调用FFmpeg 资源统一释放出口。8.2 踩坑记录YOLO ONNX 输出维度顺序坑YOLOv5 导出 ONNX 存在两种 shape[1,25200,85]与[1,85,25200]。如果转置逻辑写反现象很隐蔽推理耗时正常但是完全输出不到检测框。需要代码做 shape 自动判断与归一化。检测框闪烁消失问题解码 30FPS推理只有 4FPS如果推理结果一完成就清空旧结果检测框只会闪现几十毫秒肉眼几乎看不见。解决方案保留上一轮检测结果直到新结果到来才更新。BGR/RGB 通道顺序问题FFmpeg sws 输出 RGB24YOLOv5 训练输入是 RGB调用blobFromImage时swapRBfalse如果换成 OpenCV VideoCapture 读取输出 BGR此时必须开启 swapRB否则推理效果完全报废。跨线程传递自定义结构体QVectorDetection跨线程信号槽头文件Q_DECLARE_METATYPE(Detection)main 函数执行qRegisterMetaTypeQVectorDetection()否则 Qt 队列信号槽直接失效。模型修复下载的yolov5s.onnx 是 opset 17 FP16 导出的OpenCV 4.5.5 DNN 不兼容。写转换脚本 fix_all.py做了三类图变换FP16→FP32权重 Constant 节点、Split→SliceOpenCV 只支持等分切分、axes 输入转 attribute。九、后续升级扩展方向9.1 性能优化GPU 推理OpenCV DNN 切换DNN_BACKEND_CUDA推理耗时可以从 160ms 下降至 10‑20ms需要自行编译带 CUDA 支持的 OpenCV。更换推理引擎ONNX Runtime / TensorRT加载 fp16 模型进一步提速。调整推理输入尺寸640→416/320牺牲小目标检测换取速度或者更换轻量模型 YOLOv5n / YOLOv8n / YOLO11n。硬件解码FFmpeg 开启 cuvid/qsv/d3d11va 硬件解码降低 CPU 占用。9.2 新增功能目标追踪接入 ByteTrack/SORT给目标分配稳定 ID消除检测框跳动解决推理间隔带来的画面错位。周界告警越线检测、区域入侵检测弹窗 / 声音报警。截图与录像检测触发自动保存图片 / 片段。结果上报检测结果输出 JSON/CSV 日志WebSocket 推送给后端服务。多路视频多解码线程 检测线程池网格布局多路摄像头同时检测。9.3 UI 交互参数配置面板置信度阈值、NMS 阈值、检测抽帧间隔、类别过滤。检测框插值平滑推理间隔内做位置线性插值消除画面卡顿感。十、小结本项目完整落地了一个Qt 视频 AI 播放器把 FFmpeg 解码、多线程架构、背压丢帧、异常重连、OpenCV‑DNN 推理全部整合。Gitee 源码地址先空下...标签QtFFmpegOpenCVYOLOv5ONNXRTSPRTMP多线程DNN视频目标检测
返回列表