04 yolo检测摄像头的视频流

一、测试摄像头的视频流

在进行动态检测视频流的对象之前,需要先把摄像头的视频播放出来。

找一个摄像头,配置好IP地址,找到它的流播放地址,比如我手上用的地址是:  

rtsp://192.168.12.100/stream1

把这个地址复制到播放器里打开,可以进行播放,表示这个流是我们可以获取的,有流需要用户名和密码,具体看自己使用的

我使用的PotPlayer播放器

OK,已经正常播放视频

 二、在python里播放视频流

我们采用opencv。

OpenCV(open source computer vision library)是一个基于BSD许可(开源)发行的跨平台计算机视觉库,是一款应用很广的开源库。

首先先安装opencv

pip install opencv-python

安装成功: 

 新建一个play.py文件

编写如下代码

import cv2

rtsp_url = "rtsp://192.168.12.100/stream1"
cap = cv2.VideoCapture(rtsp_url)

# 创建可调整大小的窗口
cv2.namedWindow('RTSP Stream', cv2.WINDOW_NORMAL)

while True:
    ret, frame = cap.read()
    if not ret:
        print("连接中断,尝试重连...")
        cap = cv2.reopen_stream(rtsp_url)  # 自定义重连函数
        continue

        # 显示视频帧
    cv2.imshow('RTSP Stream', frame)

    # 监听窗口调整事件
    key = cv2.waitKey(1) & 0xFF
    if key == 27:  # ESC键退出
        break

cap.release()
cv2.destroyAllWindows()

然后执行,等待一会,播放成功

三、实现视频流动态检测显示检测目标

新建一个detect_rtsp.py

import cv2
from ultralytics import YOLO
import time


class RTSPYOLODetector:
    def __init__(self, rtsp_url, model_path="yolo11n.pt"):
        self.rtsp_url = rtsp_url
        self.model = YOLO(model_path)  #
        self.cap = None
        self.last_frame = None
        self.reconnect_interval = 3  # 重连等待时间(秒)
        self.frame_skip = 2  # 跳帧检测以降低延迟

    def start_detection(self):
        cv2.namedWindow("YOLO RTSP Detection", cv2.WINDOW_NORMAL)
        self._connect_stream()

        frame_count = 0
        while True:
            try:
                if not self.cap.isOpened():
                    self._reconnect()
                    continue

                ret, frame = self.cap.read()
                if not ret:
                    print("视频流中断,尝试重连...")
                    self._reconnect()
                    continue

                    # 跳帧处理:每3帧处理1次以降低延迟
                frame_count += 1
                if frame_count % self.frame_skip != 0:
                    continue

                    # YOLO检测
                results = self.model.predict(
                    frame,
                    conf=0.6,  # 置信度阈值
                    iou=0.45,  # IOU阈值
                    classes=[0, 2, 3, 5],  # 只检测人、车、摩托车、公交车 
                    verbose=False
                )

                # 绘制检测结果 
                annotated_frame = results[0].plot()

                # 自适应窗口缩放 
                h, w = annotated_frame.shape[:2]
                win_w = cv2.getWindowImageRect("YOLO RTSP Detection")[2]
                win_h = int(win_w * h / w)
                resized_frame = cv2.resize(annotated_frame, (win_w, win_h))

                cv2.imshow("YOLO RTSP Detection", resized_frame)

                # ESC退出 
                if cv2.waitKey(1) == 27:
                    break

            except Exception as e:
                print(f"发生错误: {str(e)}")
                self._reconnect()

        self.cap.release()
        cv2.destroyAllWindows()

    def _connect_stream(self):
        if self.cap:
            self.cap.release()
        # 优化RTSP参数减少延迟 
        self.cap = cv2.VideoCapture(self.rtsp_url)
        self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)  # 缓冲区大小
        self.cap.set(cv2.CAP_PROP_OPEN_TIMEOUT_MSEC, 3000)  # 超时时间 
        time.sleep(self.reconnect_interval)


if __name__ == "__main__":
    # RTSP示例地址(替换为实际摄像头地址)
    rtsp_url = "rtsp://192.168.12.100/stream1"

    # 初始化检测器
    detector = RTSPYOLODetector(
        rtsp_url,
        model_path="yolo11n.pt"
    )
    detector.start_detection()

运行,效果如下

四、给检测框添加尺寸显示

新建一个detect_rtsp_xy.py

import cv2
from ultralytics import YOLO
import time


class RTSPYOLODetector:
    def __init__(self, rtsp_url, model_path="yolo11n.pt"):
        self.rtsp_url = rtsp_url
        self.model = YOLO(model_path)
        self.cap = None
        self.last_frame = None
        self.reconnect_interval = 3  # 重连等待时间(秒)
        self.frame_skip = 2  # 跳帧检测以降低延迟

    def start_detection(self):
        cv2.namedWindow("YOLO RTSP Detection", cv2.WINDOW_NORMAL)
        self._connect_stream()

        frame_count = 0
        while True:
            try:
                if not self.cap.isOpened():
                    self._reconnect()
                    continue

                ret, frame = self.cap.read()
                if not ret:
                    print("视频流中断,尝试重连...")
                    self._reconnect()
                    continue

                # 跳帧处理:每3帧处理1次以降低延迟
                frame_count += 1
                if frame_count % self.frame_skip != 0:
                    continue

                # YOLO检测
                results = self.model.predict(
                    frame,
                    conf=0.6,
                    iou=0.45,
                    classes=[0, 2, 3, 5],
                    verbose=False
                )

                # 创建带尺寸标注的画面
                annotated_frame = frame.copy()
                if results[0].boxes:
                    for box in results[0].boxes:
                        # 获取坐标、类别、置信度
                        x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
                        cls_id = int(box.cls[0])
                        conf = float(box.conf[0])
                        width = x2 - x1
                        height = y2 - y1

                        # 绘制检测框
                        color = (0, 255, 0)  # 绿色边框
                        cv2.rectangle(annotated_frame, (x1, y1), (x2, y2), color, 2)

                        # 构造带尺寸的标签
                        class_name = results[0].names[cls_id]
                        label = f"{class_name} {conf:.2f} W:{width} H:{height}"

                        # 计算文本位置(确保在画面内)
                        (text_w, text_h), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2)
                        text_y = y1 - text_h - 5 if y1 > text_h + 5 else y1 + 20

                        # 绘制文本背景
                        cv2.rectangle(annotated_frame,
                                      (x1, text_y - text_h - 5),
                                      (x1 + text_w, text_y + 5),
                                      color, -1)

                        # 绘制文本
                        cv2.putText(annotated_frame, label,
                                    (x1, text_y),
                                    cv2.FONT_HERSHEY_SIMPLEX,
                                    0.6, (0, 0, 0), 2)

                # 自适应窗口缩放
                h, w = annotated_frame.shape[:2]
                win_w = cv2.getWindowImageRect("YOLO RTSP Detection")[2]
                win_h = int(win_w * h / w)
                resized_frame = cv2.resize(annotated_frame, (win_w, win_h))

                cv2.imshow("YOLO RTSP Detection", resized_frame)

                # ESC退出
                if cv2.waitKey(1) == 27:
                    break

            except Exception as e:
                print(f"发生错误: {str(e)}")
                self._reconnect()

        self.cap.release()
        cv2.destroyAllWindows()

    def _connect_stream(self):
        if self.cap:
            self.cap.release()
        self.cap = cv2.VideoCapture(self.rtsp_url)
        self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
        self.cap.set(cv2.CAP_PROP_OPEN_TIMEOUT_MSEC, 3000)
        time.sleep(self.reconnect_interval)


if __name__ == "__main__":
    rtsp_url = "rtsp://192.168.12.100/stream1"
    detector = RTSPYOLODetector(rtsp_url, model_path="yolo11n.pt")
    detector.start_detection()

运行效果如下:

 代码点这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爬呀爬的水滴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值