django视频检测

用Django做视频检测,视频最直接的检测路子是把视频拆成帧,逐帧丢给检测模型,视频再把结果拼回去。检测我去年帮一个做安防的视频朋友搭过一套,摄像头是检测海康的,RTSP流拉过来,视频Django负责调度和展示,检测检测用的视频YOLOv5。整套跑下来,检测延迟大概在1.2秒左右,视频对他来说够用了。检测

先说视频怎么进Django。视频很多人第一反应是检测上传文件,但监控场景基本是视频实时流。我的做法是单独起一个进程用OpenCV的VideoCapture拉流,Django这边通过Celery下发任务,检测完把结果帧存到Redis或者本地磁盘,前端用MJPEG流的方式推给浏览器。这里有个坑:Django的runserver是单线程的,别指望它同时处理视频流和页面请求,必须上gunicorn加gevent,不然页面直接卡死。

检测环节本身不复杂。YOLOv5的推理代码就那几行,难的是怎么和Django的请求周期解耦。我试过在视图函数里直接调model(),结果一个请求占住worker十几秒,并发一上来整个服务就崩。后来改成Celery异步任务,视图只负责返回task_id,前端轮询或者用WebSocket拿结果。这样Django只做它擅长的事——路由、鉴权、ORM,脏活累活扔给Celery worker。

数据库设计上,别把检测结果一股脑塞进JSONField。我一开始图省事,每帧的bbox坐标全存成JSON,查起来想死。后来拆成三张表:VideoTask记录任务元信息,DetectionFrame存帧号和时间戳,DetectionObject存每个目标的类别、置信度和坐标。这样要查“某个时间段内出现的人”,一条JOIN就搞定,不用在Python里遍历JSON。

前端展示用video标签加Canvas叠加框。注意视频的原始分辨率和前端显示尺寸往往不一致,坐标要按比例缩放。我见过有人直接把模型输出的像素坐标画上去,结果框全偏到姥姥家。另外,如果检测帧率低于视频帧率,画面会一顿一顿的,解决办法是前端做插值,或者干脆只展示有检测结果的关键帧,中间用淡入淡出过渡。

性能方面,GPU不是必须的,但CPU推理1080p视频大概只有3-5 FPS,体验很差。如果预算有限,可以把视频降采样到640×640再送进模型,精度掉一点,速度能翻好几倍。我那个朋友后来加了块二手Tesla P4,帧率直接拉到25 FPS,成本不到一千块。

最后说个容易忽略的点:视频检测的“检测”二字,不光是目标检测,还包括异常行为判断。比如有人翻越围栏,单纯靠YOLO输出的框是判断不了的,得结合时序信息。我的做法是在DetectionObject表里加一个track_id,用简单的IOU匹配做跟踪,然后规则引擎判断轨迹是否穿越了预设区域。这套逻辑写在Django的signals里,检测任务完成后触发,比在视图里硬编码优雅得多。

整套方案跑下来,Django更像一个胶水层,把视频流、推理引擎、存储和前端粘在一起。它的ORM和Admin确实省事,但别让它碰视频解码和模型推理,那不是它的战场。