基于目标识别结果在QML视频流上叠加绘制矩形的实现方法咨询
实现方案
两种方案都可行,无需自行生成叠加图层,优先走「C++侧绑定帧与检测数据+QML侧绘制」的路径即可解决同步问题,具体实现逻辑如下:
1. 核心同步逻辑
你不需要额外开发叠加图层,只需要把连通分量矩形列表和对应视频帧做强绑定即可:
- 你在C++侧处理完每一帧源图像、得到连通分量结果的同时,和触发
onNewVideoContentReceived()信号的时机完全对齐,emit你自定义的「检测结果更新」信号,信号参数携带当前帧对应的矩形列表(包含x、y、width、height)以及可选的帧序号/时间戳,保证视频帧和检测框数据是同批次更新的。 - 将处理视频的C++类注册到QML上下文,把检测结果列表用
QVariantList类型的属性暴露给QML。
2. QML侧绘制实现
根据你的检测框数量选择以下两种实现即可:
方案A:Repeater动态生成矩形(适合单帧检测框<50的场景)
优势是代码简单,维护成本低,性能满足绝大多数场景:
VideoOutput { id: videoOutput source: myVideoProducer anchors.fill: parent // 直接在VideoOutput下加Repeater,和视频同层级渲染 Repeater { model: myVideoProcessor.detectedRects // 绑定C++暴露的QVariantList属性 delegate: Rectangle { // 坐标需要根据视频的实际缩放做映射,避免视频拉伸时框错位 x: model.x * videoOutput.contentScale + videoOutput.contentX y: model.y * videoOutput.contentScale + videoOutput.contentY width: model.width * videoOutput.contentScale height: model.height * videoOutput.contentScale color: "transparent" border.color: "#ff3333" border.width: 2 } } }
方案B:Canvas批量绘制(适合单帧检测框>50的场景)
如果检测框数量较多,用Repeater生成大量Item会有性能损耗,换成Canvas批量绘制即可:
VideoOutput { id: videoOutput source: myVideoProducer anchors.fill: parent Canvas { id: canvas anchors.fill: parent // 绑定C++侧和视频帧同步发出的检测结果更新信号 Connections { target: myVideoProcessor function onDetectedRectsUpdated() { canvas.requestPaint() } } onPaint: { const ctx = getContext("2d") ctx.clearRect(0, 0, width, height) ctx.strokeStyle = "#ff3333" ctx.lineWidth = 2 const scale = videoOutput.contentScale const offsetX = videoOutput.contentX const offsetY = videoOutput.contentY // 批量遍历所有检测框绘制 const rects = myVideoProcessor.detectedRects for(let i=0;i<rects.length;i++) { const r = rects[i] ctx.strokeRect(r.x*scale + offsetX, r.y*scale + offsetY, r.width*scale, r.height*scale) } } } }
3. 常见同步问题排查
你之前看到的示例叠加层不同步,核心原因是叠加层的更新时机和视频帧更新时机是独立的,只要你保证检测结果更新、视频帧刷新两个操作在C++侧同一时序触发,Qt Quick的渲染管线会自动保证两者同步,不需要额外做对齐逻辑。
内容的提问来源于stack exchange,提问作者artless-noise-bye-due2AI
相关产品推荐
相关产品推荐

