如何将视频与目标检测bounding box分别上传至服务器后叠加播放
实现视频与检测框合并播放的解决方案
你可以根据业务场景选择下面两种实现路线:
方案1:服务端预渲染合并后输出带标注视频
适合需要直接输出通用可播放文件、不需要交互调整标注的场景,兼容性最强。
- 上传环节:后端接收mp4视频和对应JSON文件后,做好二者的关联存储,比如使用相同文件前缀命名,或者在数据库中建立二者的映射关系。
- 渲染环节:使用
OpenCV或FFmpeg逐帧读取视频,同时解析JSON中对应帧的bounding box坐标、类别、置信度等信息,逐帧将标注框、标签文字绘制到视频帧上。 - 输出环节:将绘制完成的帧重新编码为标准mp4文件,可直接返回前端播放或提供下载。
你可以参考下面的Python简易实现代码:
import cv2 import json # 读取检测结果JSON,需根据你自己的JSON结构调整字段 with open("detection_result.json", "r", encoding="utf-8") as f: bbox_data = json.load(f) # 读取原始视频 cap = cv2.VideoCapture("input_video.mp4") fps = cap.get(cv2.CAP_PROP_FPS) frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 初始化输出视频写入器 fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter("output_with_bbox.mp4", fourcc, fps, (frame_width, frame_height)) current_frame = 0 while cap.isOpened(): ret, frame = cap.read() if not ret: break # 获取当前帧对应的检测框 frame_bboxes = bbox_data.get(str(current_frame), []) for box in frame_bboxes: x1, y1, x2, y2 = map(int, box["coordinates"]) label = f"{box['class_name']} {box['confidence']:.2f}" # 绘制检测框 cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) # 绘制标签文本 cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2) out.write(frame) current_frame += 1 cap.release() out.release()
该方案优点是输出的是标准mp4文件,所有播放器都支持直接播放,不需要额外适配;缺点是长视频渲染耗时久,占用服务端算力,也不支持动态调整标注显示样式。
方案2:服务端返回原始资源,前端实时叠加标注
适合需要交互操作标注的场景,比如可随时切换显示/隐藏某类目标、调整标注颜色,服务端压力更小。
- 上传环节和方案1一致,做好视频与JSON的关联存储即可。
- 播放请求环节:服务端同时返回原始视频的播放地址和对应的JSON检测数据。
- 前端渲染环节:使用HTML5 Canvas或者视频播放扩展库,在视频播放过程中实时获取当前播放进度对应的帧序号,取出JSON中对应帧的检测框,绘制在视频上方的透明画布层上。
该方案优点是服务端不需要做 heavy 的渲染计算,响应速度快,支持自定义交互操作;缺点是需要前端做适配开发,无法直接导出带标注的视频文件。
可参考的开源实现
- 服务端渲染类:可以直接复用YOLO系列官方自带的检测结果可视化代码,逻辑和上述OpenCV示例完全一致,调整下JSON字段适配即可。
- 前端渲染类:可以参考常见的视频标注插件的实现逻辑,调整后即可适配检测框的实时叠加需求。
内容的提问来源于stack exchange,提问作者Jarvis098
相关产品推荐
相关产品推荐

