
简介面向视频监控、智能交通、工业自动化等场景开发者资源提供了一套基于YOLOv8的RTSP实时视频流目标检测方案覆盖视频流接入、模型推理、结果可视化等环节适合具备一定深度学习基础、希望快速落地应用的工程人员。包体共467个文件压缩包约169.25MB文件类型以Python源码145个py、编译文件215个pyc为主并含80个yaml模型配置、6个pt预训练权重、部署脚本、测试图片以及基于Vue和Element UI的Web演示界面便于直接运行与二次开发。资源已有220人次学习下载。借助README说明、带标注的测试样张和摄像头演示视频可直观理解YOLOv8在RTSP流上的工作方式也能根据自身摄像头地址与识别目标调整配置和参数显著节省从零搭建环境的时间。 做视觉落地的同学应该都有过这种经历模型在本地图片测试集上跑得好好的一接到“把检测接到摄像头实时流上”的需求就各种翻车。我去年接到一个项目要把工位附近的海康摄像头拉RTSP流实时检测人员和车辆最后还要部署到边缘盒子。折腾了半个多月把拉流、解码、推理、部署这条链路里能踩的坑基本都踩了一遍。这篇文章就把整个思路和实操记录下来让后来的人少走弯路。这个项目用到的核心组合就是YOLOv8和RTSP。前者是目前工业界应用最广泛的检测模型之一后者是网络摄像头的标准传输协议两者搭配基本覆盖了安防、交通、园区管理这类常见的实时检测场景。无论你是刚入门想做个小demo还是已经在做嵌入式部署这篇内容都会对你有帮助。我会从技术选型、拉流解码、数据训练、推理代码组织一直到边缘设备部署把每个环节的具体做法和容易出错的地方讲清楚。1. 技术选型不是拍脑袋为什么是YOLOv8和RTSP1.1 从YOLOv5到YOLOv8到底改了什么很多老项目还在用YOLOv5不是说不能用而是YOLOv8作为Ultralytics推出的迭代版本在结构上确实做了几处让我觉得“值得迁移”的改动。最明显的是它把检测头换成了anchor-free不再需要预设anchor box省去了聚类计算anchor尺寸的步骤训练配置更简单。同时主干网络里的C2f模块替换了原来的C3模块通过更丰富的梯度流来提升特征提取能力在同等算力下精度普遍好一点。模型的Decoupled Head把分类和回归分支分开收敛速度更快对小目标也友好一些。这些改动带来的实际收益是同样的数据集YOLOv8s往往比YOLOv5s的mAP高1到3个点推理速度不会有明显下降。对于RTSP实时流这种要求低延迟的场景我优先考虑的是模型的吞吐量而YOLOv8的n/s/m系列提供了不错的精度-速度平衡。1.2 RTSP协议在实时检测里的定位RTSP全称Real Time Streaming Protocol是网络摄像机IPC领域的事实标准。海康、大华、小米等品牌摄像头都支持通过RTSP地址输出视频流。它可以基于TCP或UDP传输默认端口554地址格式大致是rtsp://用户名:密码IP地址:554/Streaming/Channels/101不同品牌的路径不同。海康的101代表主码流第一通道102代表子码流第一通道小米一般类似rtsp://user:passip:8554/live大华则是/cam/realmonitor?channel1subtype0。做目标检测时一般建议拉主码流拿清晰度但如果硬件性能紧张可以拉子码流分辨率低一档检测速度会快不少。我实测过一个500万像素的海康摄像头主码流25帧1080p拉流加解码就已经占了单核CPU大量资源所以后面一定要做硬解码或降低输入分辨率。1.3 先想清楚检测对象和硬件再选模型尺寸很多人一上来就问“预测代码怎么写”其实第一步应该反问自己检测对象是什么部署在什么硬件上如果是接GPU服务器做园区车辆检测那直接上YOLOv8x都可以如果是部署到Jetson Orin Nano或者RK3588这类边缘设备YOLOv8n/s加上TensorRT或RKNN加速可能是唯一可行方案。我的原则是先定硬件再定模型。硬件决定了你能跑多大的模型模型再决定能达到多少精度。GTX 1660Ti这种6GB显存的卡跑YOLOv8s的实时视频流完全没有问题也就是几百FPS的推理能力瓶颈反而不在GPU而在解码和传输。2. 拉流解码被很多人低估的第一道坎2.1 OpenCV直接读流为什么延迟高最直观的做法是cv2.VideoCapture(rtsp://...)然后循环读取。这个方案在小项目里确实能跑通但实际使用中会遇到两个让人头疼的问题延迟越拉越大以及断流后不会自动重连。延迟大的原因在于OpenCV在拉RTSP流时内部会把多帧缓冲到队列里解码速度跟不上采集速度时队列积压你看到的画面就会越来越“慢”。网上有人教你把CAP_PROP_BUFFERSIZE设置为1但在许多平台这个参数对RTSP根本不生效。我这里给出一个从实践中来的方案使用FFmpeg的-fflags nobuffer参数或者直接用FFmpeg把RTSP转成原始帧再送进OpenCV延迟能明显降低。ffmpeg -rtsp_transport tcp -fflags nobuffer \ -i rtsp://user:passip:554/Streaming/Channels/101 \ -f rawvideo -pix_fmt bgr24 -s 1280x720 - \然后用管道读取或者直接用FFmpeg的Python绑定比如ffmpeg-python。如果你用的是NVIDIA显卡可以加-hwaccel cuda做硬解码CPU占用能降一大截。2.2 TCP还是UDP断流重连的姿势RTSP默认传输协议在不同客户端里可能不太一样OpenCV默认用UDP但UDP在弱网环境下丢包严重画面容易出现马赛克和绿屏。做检测时我都是强制切到TCPcv2.VideoCapture(rtsp://user:passip:554/Streaming/Channels/101?tcp)或者用FFmpeg时加-rtsp_transport tcp。TCP消耗带宽多一点但网络稳定画质可靠。断流重连是另一个不得不处理的问题。摄像头重启、网络抖动都可能让拉流线程挂掉。我的处理方法是开一个专门线程循环读取每次read()返回False时主动释放cap对象sleep 1秒后重新创建。这个逻辑看起来简单但很多项目没有写重连机制导致挂在墙上的监控画面黑屏之后程序里还在空转。2.3 不要忽略分辨率与像素格式RTSP流的分辨率、帧率、编码格式都影响检测效果。我经常看到有人把2K主码流直接喂给YOLOv8推理速度慢不说小目标也没变清晰多少。最合理的做法是把输入分辨率统一到640x640或者1280x640通过解码端缩放尽量保持宽高比而不是直接resize到正方形导致形变。在OpenCV任务流里CAP_PROP_FRAME_WIDTH和CAP_PROP_FRAME_HEIGHT在读取RTSP时设置不一定生效更靠谱的做法是用FFmpeg的-s参数控制输出尺寸。像素格式这边大部分摄像头输出H.264解码后是YUVOpenCV读取时已经转成BGR后续不需要再额外转。3. 模型准备从随便用用到针对你的场景训练3.1 先跑通预训练模型再谈自定义接触一个新项目时我会先用Ultralytics提供的COCO预训练权重把RTSP流跑通验证整个管道正常再考虑要不要自己训练。这一步能帮你把问题隔离如果预训练模型检测框正常说明拉流解码没问题如果框乱跳那就要检查解码帧率和输入尺寸。pip install ultralytics yolo predict modelyolov8s.pt sourcertsp://user:passip:554/Streaming/Channels/101这条命令可以直接跑起一个检测窗口。预览模式下能看到效果如果要在代码里集成再写Python调用。先跑这个demo能帮你快速判断摄像头取流是否OK避免一上来就陷入代码调试。3.2 标注自己的数据集yaml文件配置最容易错业务场景里我们常常只关心人、车、安全帽之类这时候COCO的80类就不够用了需要自己准备数据集。如果数据量不大用LabelImg或X-AnyLabeling标注成YOLO格式每张图对应一个txt文件每一行是class_id cx cy w h坐标值归一化到0~1。训练前要写一个dataset.yaml我最常犯的错是路径写成了绝对路径换机器就要改更好的做法是相对路径加path:字段指向数据集根目录。一个标准示例path: ./datasets/my_dataset train: images/train val: images/val names: 0: person 1: car 2: helmet尤其需要注意类别ID必须从0开始连续不能跳过。如果之前标注时类别从1开始训练时会直接报错或类别错乱。3.3 训练命令与两个必盯的指标训练命令很简单yolo train datadataset.yaml modelyolov8s.yaml epochs100 batch16 imgsz640但真正重要的不是命令而是训练过程中要盯的两类指标loss曲线的收敛情况和验证集上的mAP50、mAP50-95。很多人只看mAP涨没涨忽略了过拟合信号。如果训练loss一直下降、验证loss却开始上升那就是过拟合了可以加早停或者加大数据增强。我习惯用TensorBoard或Ultralytics自动生成的results.png看四条曲线box_loss、cls_loss、dfl_loss以及验证集mAP。前面三个都在稳步下降说明训练正常如果后面某条曲线在某个epoch开始抖动上升就要考虑减小学习率。3.4 YOLOv8数据增强参数别拉满Ultralytics默认开启的增强包括马赛克、随机透视、翻转、颜色抖动等。马赛克增强在训练初期很有用但训到最后阶段再继续用会干扰模型学习所以官方会在最后10个epoch自动关闭Mosaic。实际项目中如果数据集本身是小样本几百张增强拉满容易学不到真实分布我一般只开hsv_h0.015、fliplr0.5这类轻度增强默认值和上述类似。我也踩过“过分增强导致检测框偏移”的坑开启了大量旋转和透视后安全帽这类小目标在增强后的图片里可能已经严重变形模型学到的是变形的特征真实场景里反而性能下降。所以我的经验是小目标场景少用旋转增强多补数据。4. 核心推理代码怎么组织才不像玩具项目4.1 单路RTSP检测的骨架当拉流、模型都就绪后可以用一个相对简洁的类来组织代码。下面是一个基础的推理线程骨架核心思想是采集和推理解耦。import cv2 import time import threading from collections import deque from ultralytics import YOLO class RTSPDetector: def __init__(self, rtsp_url, model_path, use_tcpTrue): self.rtsp_url rtsp_url (?tcp if use_tcp else ) self.model YOLO(model_path) self.frame_queue deque(maxlen8) self.running True def capture_loop(self): cap cv2.VideoCapture(self.rtsp_url) while self.running: ret, frame cap.read() if not ret: cap.release() time.sleep(1) cap cv2.VideoCapture(self.rtsp_url) continue if len(self.frame_queue) self.frame_queue.maxlen: self.frame_queue.append(frame) cap.release() def detect_loop(self): while self.running: if not self.frame_queue: time.sleep(0.001) continue frame self.frame_queue.popleft() results self.model.predict(frame, imgsz640, conf0.35, verboseFalse) annotated results[0].plot() cv2.imshow(detection, annotated) if cv2.waitKey(1) 0xFF ord(q): self.running False def start(self): threading.Thread(targetself.capture_loop, daemonTrue).start() threading.Thread(targetself.detect_loop, daemonTrue).start()这段代码里我用了一个有界队列deque(maxlen8)控制内存的同时自然形成滑动窗口。采集线程只负责把最新帧塞进队列推理线程只负责从队列取帧。如果推理慢队列会被填满采集线程会跳过中间帧保证实时性而不是无限积压。4.2 多线程视频采集和推理必须分离很多人把cap.read()和model.predict()写在一个循环里面这是延迟的主要来源之一。因为read()是阻塞式的底层在等待网络数据predict()也是阻塞式的GPU跑一次推理要十几毫秒到几十毫秒。两者串行一卡都卡。分离之后采集线程能稳定保持25到30帧的读取即使推理只能跑到10FPS我们看到的画面依然是接近实时的只是检测框更新频率低一些不会出现越拖越慢的卡顿感。这个方法在CPU和GPU上都适用强烈建议所有RTSP实时检测项目都采用“生产者-消费者”模式。4.3 如果有多路视频流怎么压榨GPU做安防项目往往不会只有一路摄像头。如果同时处理4路RTSP我的做法是先用FFmpeg把所有解码帧收集起来凑成一个batch喂给YOLOv8。YOLOv8的predict支持传入batch实际上model.predict([frame1, frame2, frame3, frame4])会自动做batch推理。这样可以明显提升GPU利用率。但要注意在不同摄像头分辨率不一致时预先将它们统一尺寸否则batch会报错。5. 部署到边缘设备GTX1660Ti / Jetson / RK35885.1 先搞清楚你的GPU能不能跑在PC上用GTX1660Ti跑YOLOv8s视频流基本没压力实测1080p输入、640推理尺寸下FP16精度能跑到50到70FPS。瓶颈不再是推理而是解码和显示。所以我给所有准备上线的项目都加一句先跑一次nvidia-smi看看显存占用和GPU利用率不要一上来就怀疑模型太慢。如果是Jetson Orin Nano或者RK3588事情就不一样。Jetson需要把YOLOv8导出为TensorRT的engine文件RK3588需要导出为RKNN格式。它们都不适合直接跑PyTorch模型。Ultralytics提供了一键导出命令yolo export modelyolov8s.pt formatengine device0 halfTrueRK3588的话通常需要先转ONNX再用RKNN-Toolkit2做量化转换量化精度需要拿几百张真实场景图做校准集。5.2 TensorRT部署一次转换处处踩坑TensorRT导出成功后你在新设备上重新推理时不要再走PyTorch路径。加载engine文件的代码和普通模型加载不一样通常通过tensorrt库或者Ultralytics的YOLO(model.engine)。注意TensorRT是绑定硬件和精度的比如你在RTX 3060上导出的engine放到GTX 1660Ti上就加载不了必须在目标设备上重新导出。边缘设备上我还建议优先使用FP16推理。INT8虽然更快但量化后可能掉点明显尤其是小目标。我的实测是YOLOv8s在RK3588上FP16实际上是RKNN的混合量化能跑到20到30FPSINT8能到50FPS但小目标mAP下降2到3个点。具体怎么选看业务对召回率的要求。5.3 部署包体积和工程化边缘设备上的运行环境通常精简不要把整个ultralytics包都打进去。更稳的做法是用ONNX Runtime加载导出的ONNX模型自己写前处理和NMS。这样包体积小、依赖少还避免版本冲突。YOLOv8的ONNX输出通常是一个(1, 84, 8400)的张量前4维是cx, cy, w, h后面80维是每个类别的score。解析这个输出再做非极大值抑制整个推理代码只需要不到200行。6. 实测中绕不开的坑与优化方向6.1 小目标检测为什么远处的人总是会丢在园区场景里摄像头往往架得很高远处的人可能只占几十个像素。YOLOv8虽然有P5输出层但对微小目标依然吃力。我第一次部署到现场发现画面里2米外的人几乎检不到回来后做了一系列改进把输入分辨率从640提到960甚至1280虽然推理慢一些但小目标特征更清晰。在模型配置里增加P2检测头也就是所谓的“小目标检测头”特殊场景下可以提高小目标的召回率。增大训练集中小目标样本的比例利用sahi切片推理库对大图做切片检测但切片推理不适合实时流只适合离线分析。在实时视频流中如果小目标漏检严重我建议优先调大输入尺寸而不是换复杂模型。YOLOv8x的n/s/m系列在不同分辨率下的表现我整理过一个粗略参考见下表具体数值因设备而异。模型输入尺寸950像素宽画面中的小目标检测率定性推理耗时YOLOv8n640低最省YOLOv8s640中低省YOLOv8s1280中高中等YOLOv8m1280高较重6.2 运动物体经过摄像头只识别一次别慌这是缺跟踪热词里有一个问题很典型“运动的物体经过摄像头只识别一次YOLOv8 seg”。如果只做逐帧检测物体经过视野的过程中每帧都应该是检测到的出现只识别一次大概率是置信度阈值设太高或者关键帧被队列丢弃。逐帧检测本来就不稳定需要给检测框加一个简单的跟踪器如ByteTrack把短时间的漏检帧自动补上让同一个ID持续存在。我在很多项目里都把YOLOv8和ByteTrack搭配使用。检测器只负责每一帧输出框跟踪器负责给框分配ID并维持轨迹。这样物体被遮挡一两帧后轨迹不会立刻丢满足“只识别一次”的需求本质上是要“只识别一个ID”而不是每帧都打新框。6.3 用公开RTSP测试流验证延时和FPS没有摄像头时可以用公开的RTSP测试流来验证代码。网上有很多公开的RTSP地址比如一些演示流媒体服务器提供的h264测试源。搜索“public rtsp test stream”可以找到但这类地址容易失效稳定性没法保证。更推荐的方式是本地用FFmpeg推一路测试流ffmpeg -re -i local_video.mp4 -c copy -f rtsp -rtsp_transport tcp rtsp://192.168.1.100:8554/test这样既能测试代码又能完全掌控推流端的状态。测延迟也方便把拍摄到的时钟画面和当前系统时间对比基本能算出真实延迟。这里说一个我的经验视频检测项目里95%的问题都出在视频链路上而不是模型。模型输出一个框很简单怎么稳定、低延迟、不丢帧地把视频画面送进模型、再把结果送到业务方才是真正的工程题。对整个链路做稳定性测试时我一般跑四十八小时的长时间压测重点观察内存是否缓慢上涨、队列长度是否持续堆积、断流重连是否生效。如果这三项都通过项目基本就能上线。最后分享一个很实用的调试技巧在部署现场随身带一台能显示系统进程和GPU利用率的电脑一旦画面卡顿先看CPU解码线程是不是已经满了。大多数卡顿都不是模型慢而是解码线程卡死拖累了整个生产者消费者链路。本文还有配套的精品资源点击获取