本文介绍了一个基于 YOLOv8 的目标检测识别管理系统。该系统提供了图形化操作界面,支持图片识别、视频识别、摄像头实时识别以及 RTSP/HTTP 实时流识别。系统通过 PySide6 构建桌面端界面,使用 Ultralytics YOLOv8 模型完成目标检测,并结合 OpenCV 进行图像与视频帧处理。用户可以通过按钮选择不同的识别源,系统会实时显示检测画面和检测结果,具有较好的交互性和实用性。

一、项目背景

随着人工智能和计算机视觉技术的发展,目标检测技术已经广泛应用于智慧安防、交通监控、工业检测、无人驾驶、行为分析等场景。YOLO 系列算法由于检测速度快、精度较高、部署方便,成为目标检测领域中非常常用的算法之一。

在实际应用中,如果只是通过命令行运行检测程序,操作不够直观,也不方便普通用户使用。因此,本文设计并实现了一个带有图形化界面的 YOLO 识别管理系统。用户无需输入复杂命令,只需要点击按钮即可完成图片、视频和实时摄像头检测。

本系统主要实现以下功能:

  1. 图片目标检测
  2. 视频目标检测
  3. 摄像头实时检测
  4. RTSP/HTTP 实时流检测
  5. 检测结果文字展示
  6. 检测画面实时显示
  7. 摄像头自动刷新与选择
  8. 多线程检测,避免界面卡死

二、开发环境

本项目使用 Python 语言开发,主要依赖如下:

Python 3.9+
PySide6
opencv-python
ultralytics

安装依赖命令如下:

pip install PySide6 opencv-python ultralytics

项目中使用的检测模型为 YOLOv8 官方模型:

yolov8n.pt

其中 yolov8n.pt 是 YOLOv8 的轻量级模型,具有速度快、占用资源少的特点,适合普通电脑进行实时检测测试。

三、系统总体设计

本系统整体采用图形化桌面程序结构,主要由两部分组成:

第一部分是检测线程 DetectWorker,负责加载 YOLO 模型、读取图片或视频帧、执行目标检测,并将检测结果返回给主界面。

第二部分是主窗口 MainWindow,负责构建界面、响应用户操作、显示检测画面和检测结果。

系统结构如下:

YOLO 识别管理系统
│
├── MainWindow 主界面
│   ├── 图片识别按钮
│   ├── 视频识别按钮
│   ├── 实时流识别按钮
│   ├── 摄像头选择框
│   ├── 开始识别按钮
│   ├── 停止识别按钮
│   ├── 画面显示区域
│   └── 检测结果显示区域
│
└── DetectWorker 检测线程
    ├── 加载 YOLOv8 模型
    ├── 图片检测
    ├── 视频检测
    ├── 摄像头检测
    ├── 实时流检测
    └── 返回检测画面和结果

为了避免检测过程阻塞界面,系统使用 QThread 将检测任务放到子线程中执行。主线程只负责界面显示和用户交互,这样在视频和摄像头实时识别时,窗口不会出现卡顿或无响应的问题。

四、核心功能介绍

1. 图片识别功能

用户点击“图片识别”按钮后,可以选择本地图片文件。系统支持常见图片格式,例如:

jpg、jpeg、png、bmp

选择图片后,点击“开始识别”,系统会调用 YOLOv8 模型进行目标检测,并将检测后的图片显示在左侧区域,同时在右侧显示识别结果。

核心代码如下:

def choose_image(self):
    file_path, _ = QFileDialog.getOpenFileName(
        self,
        "选择图片",
        str(Path.cwd()),
        "图片文件 (*.jpg *.jpeg *.png *.bmp)"
    )

    if file_path:
        self.current_source_type = "image"
        self.current_source_value = file_path
        self.result_text.append(f"已选择图片: {file_path}")

检测图片时,程序调用 YOLO 的 predict() 方法:

results = model.predict(source=image_path, verbose=False)

检测完成后,通过 r.plot() 得到带有检测框的图像:

self.frame_ready.emit(r.plot())

五、视频识别功能

系统支持用户选择本地视频文件进行目标检测。点击“视频识别”按钮后,可以选择如下格式的视频:

mp4、avi、mov、mkv

视频识别的本质是不断读取视频中的每一帧,然后将每一帧送入 YOLO 模型中进行检测。

核心代码如下:

def choose_video(self):
    file_path, _ = QFileDialog.getOpenFileName(
        self,
        "选择视频",
        str(Path.cwd()),
        "视频文件 (*.mp4 *.avi *.mov *.mkv)"
    )

    if file_path:
        self.current_source_type = "video"
        self.current_source_value = file_path
        self.result_text.append(f"已选择视频: {file_path}")

在检测线程中,视频通过 OpenCV 打开:

cap = cv2.VideoCapture(cap_source)

然后循环读取视频帧:

while self.running:
    ok, frame = cap.read()

    if not ok:
        break

    results = model.predict(source=frame, verbose=False)

这样就可以实现对视频文件的连续目标检测。

六、摄像头实时识别功能

本系统还支持本机摄像头实时识别。程序启动时会自动扫描电脑可用的摄像头,并添加到下拉框中。

摄像头刷新代码如下:

def refresh_cameras(self):
    self.combo_camera.clear()

    found = 0

    for idx in range(10):
        cap = cv2.VideoCapture(idx)

        if cap.isOpened():
            self.combo_camera.addItem(f"摄像头 {idx}", str(idx))
            found += 1

        cap.release()

    if found == 0:
        self.combo_camera.addItem("未找到摄像头", "")
        self.current_source_type = None
        self.current_source_value = None
    else:
        self.combo_camera.setCurrentIndex(0)
        self.choose_camera()

这里程序会尝试打开编号为 0 ~ 9 的摄像头。如果某个编号能够成功打开,就说明该摄像头可用。

摄像头选择函数如下:

def choose_camera(self):
    cam_data = self.combo_camera.currentData()

    if cam_data:
        self.current_source_type = "camera"
        self.current_source_value = str(cam_data)
        self.result_text.append(f"已选择摄像头: {cam_data}")
    else:
        self.current_source_type = None
        self.current_source_value = None
        self.result_text.append("未选择可用摄像头")

这个函数非常重要。因为系统支持图片、视频和摄像头多种输入源,如果用户之前选择过视频,再想切换回摄像头,就必须更新当前识别源。通过 choose_camera() 方法,可以确保用户选择摄像头时,系统会将当前识别源切换为 camera

七、实时流识别功能

除了本机摄像头,系统还支持输入 RTSP 或 HTTP 视频流地址。例如网络摄像头、监控摄像头等设备通常可以提供 RTSP 地址。

点击“实时流识别”按钮后,系统会弹出输入框:

def choose_stream(self):
    stream_url, ok = QInputDialog.getText(
        self,
        "实时流识别",
        "请输入实时流地址,例如 RTSP / HTTP:"
    )

    if ok and stream_url.strip():
        self.current_source_type = "stream"
        self.current_source_value = stream_url.strip()
        self.result_text.append(f"已设置实时流: {stream_url.strip()}")

输入流地址后,系统会通过 OpenCV 打开该视频流:

cap = cv2.VideoCapture(cap_source)

如果视频流可以正常打开,就会逐帧读取并进行 YOLO 检测。

八、检测结果展示

为了方便用户查看识别结果,系统不仅显示检测框,还会在右侧文本框中显示每个目标的类别、置信度和边界框坐标。

检测结果使用 DetectionItem 数据类保存:

@dataclass
class DetectionItem:
    cls_name: str
    conf: float
    x1: float
    y1: float
    x2: float
    y2: float

每个检测目标包含:

类别名称
置信度
左上角坐标
右下角坐标

检测结果格式化代码如下:

def _format_result_text(self, items: list[DetectionItem]) -> str:
    if not items:
        return "未检测到目标"

    lines = [f"检测到 {len(items)} 个目标:"]
    for i, it in enumerate(items, start=1):
        lines.append(
            f"{i}. {it.cls_name} | 置信度: {it.conf:.2f} | "
            f"框: ({int(it.x1)}, {int(it.y1)})-({int(it.x2)}, {int(it.y2)})"
        )
    return "\n".join(lines)

最终显示效果类似:

检测到 3 个目标:
1. person | 置信度: 0.86 | 框: (120, 80)-(320, 450)
2. car | 置信度: 0.79 | 框: (400, 180)-(680, 390)
3. dog | 置信度: 0.72 | 框: (50, 220)-(180, 410)

九、界面设计

系统采用深色主题界面,整体风格简洁清晰。顶部为功能按钮区域,左侧为检测画面显示区域,右侧为检测结果显示区域。

界面主要由以下组件组成:

QMainWindow 主窗口
QPushButton 功能按钮
QComboBox 摄像头选择框
QLabel 图像显示区域
QTextEdit 检测结果区域
QSplitter 左右分栏布局
QThread 检测线程

核心界面布局如下:

splitter = QSplitter(Qt.Horizontal)

left_panel = QWidget()
right_panel = QWidget()

splitter.addWidget(left_panel)
splitter.addWidget(right_panel)
splitter.setSizes([920, 360])

左侧用于显示实时画面,右侧用于显示检测结果:

self.video_label = QLabel("等待开始识别...")
self.result_text = QTextEdit()

为了让界面更加美观,系统使用了 Qt 样式表进行美化:

self.setStyleSheet(
    """
    QMainWindow, QWidget {
        background: #0f172a;
        color: #e2e8f0;
        font-family: 'Microsoft YaHei UI';
        font-size: 14px;
    }
    QPushButton {
        background: #1d4ed8;
        color: #ffffff;
        border: none;
        border-radius: 10px;
        padding: 8px 14px;
        font-weight: 600;
    }
    QPushButton:hover {
        background: #2563eb;
    }
    """
)

十、多线程设计

目标检测是一个比较耗时的任务,尤其是在视频和实时摄像头识别时,如果直接在主线程中运行检测,会导致界面卡死。

因此,本系统创建了一个 DetectWorker 类,继承自 QThread

class DetectWorker(QThread):
    frame_ready = Signal(object)
    log_ready = Signal(str)
    finished_ok = Signal()
    error_occurred = Signal(str)

其中定义了四个信号:

frame_ready:返回检测后的图像帧
log_ready:返回检测结果文本
finished_ok:检测结束信号
error_occurred:错误信号

主窗口通过信号槽机制接收检测结果:

self.worker.frame_ready.connect(self.update_frame)
self.worker.log_ready.connect(self.update_result)
self.worker.error_occurred.connect(self.on_error)
self.worker.finished_ok.connect(self.on_finished)

这样,检测任务在子线程中运行,界面更新在主线程中完成,保证了程序运行的稳定性和流畅性。

十一、系统运行流程

系统的整体运行流程如下:

启动程序
    ↓
加载主界面
    ↓
刷新摄像头列表
    ↓
用户选择识别源
    ↓
点击开始识别
    ↓
启动检测线程
    ↓
加载 YOLOv8 模型
    ↓
读取图片 / 视频 / 摄像头 / 实时流
    ↓
执行目标检测
    ↓
显示检测画面
    ↓
显示检测结果
    ↓
用户点击停止或检测结束

十二、关键问题与解决方案

在开发过程中,遇到了一个比较典型的问题:

用户先选择视频识别,然后再选择摄像头实时识别时,系统仍然会使用上一次的视频路径,导致摄像头识别无法正常切换。

出现这个问题的原因是程序中保存了当前识别源:

self.current_source_type
self.current_source_value

当用户选择视频后,这两个变量会变成:

self.current_source_type = "video"
self.current_source_value = file_path

如果后面没有主动切换为摄像头,程序就会一直使用视频作为识别源。

解决方法是给摄像头下拉框绑定选择事件:

self.combo_camera.activated.connect(self.choose_camera)

然后在 choose_camera() 方法中主动修改当前识别源:

def choose_camera(self):
    cam_data = self.combo_camera.currentData()

    if cam_data:
        self.current_source_type = "camera"
        self.current_source_value = str(cam_data)
        self.result_text.append(f"已选择摄像头: {cam_data}")

这样就可以实现图片、视频、摄像头和实时流之间的正常切换。

十三、系统优点

本系统具有以下优点:

第一,操作简单。用户不需要输入命令,通过图形化按钮即可完成识别操作。

第二,功能完整。系统支持图片、视频、摄像头和实时流多种识别方式。

第三,界面美观。采用深色主题设计,整体界面简洁直观。

第四,运行稳定。使用 QThread 多线程处理检测任务,避免界面卡死。

第五,扩展方便。后续可以继续增加模型切换、检测结果保存、截图保存、数据库管理等功能。

十四、后续改进方向

虽然当前系统已经实现了基础目标检测功能,但仍然可以继续扩展,例如:

  1. 增加模型选择功能,支持用户加载自己的 .pt 模型。
  2. 增加检测结果保存功能,将检测结果导出为 TXT、CSV 或 Excel。
  3. 增加截图保存功能,保存带检测框的图片。
  4. 增加视频检测结果保存功能,生成带检测框的视频。
  5. 增加置信度阈值设置功能。
  6. 增加检测类别筛选功能。
  7. 增加登录模块和用户管理模块。
  8. 增加数据库,将检测记录保存到 MySQL 或 SQLite。
  9. 增加统计图表,展示不同类别目标数量。
  10. 打包为 exe,方便在 Windows 上直接运行。

十五、总结

本文设计并实现了一个基于 PySide6 和 YOLOv8 的目标检测识别管理系统。系统通过 PySide6 构建桌面端图形界面,通过 OpenCV 读取图片、视频、摄像头和实时流数据,并调用 Ultralytics YOLOv8 模型完成目标检测。

系统支持多种识别方式,能够实时显示检测画面和检测结果,具有较强的实用性和扩展性。通过多线程设计,程序在执行检测任务时不会阻塞界面,用户体验较好。

该系统可以作为计算机视觉课程设计、毕业设计、人工智能项目实践或目标检测应用开发的基础案例。后续可以在此基础上继续扩展模型管理、结果保存、数据库管理和可视化统计等功能,使其更加接近实际应用场景。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐