YOLOv12可视化界面;YOLOv11;YOLOv10;YOLOv8等通用可视化界面GUI设计,基于pyside6,单文件即插即用,更新ip摄像头检测,美化布局及信息输出

前言

为了更便捷地使用YOLOv12;YOLOv11;YOLOv10;YOLOv8等基于ultralytics的目标检测,尤其是对于没有深度编程经验的用户,一个可视化界面(GUI)显得尤为重要。为此,基于 PySide6 开发了一个最新的支持YOLOv12的可视化界面(GUI)(其他低版本YOLO也可用),该界面能够实现对 YOLOv11/YOLOv8模型的简单操作,包括模型选择、图片检测、视频检测、摄像头检测并进行结果展示等功能,且完全兼容官方源代码。单文件即插即用,仅300多行左右,无论是研究人员、工程师,还是学生或 AI 爱好者,都能通过这个工具更加直观和高效地进行模型应用和调试。

本文仅针对图像处理部分给出代码示例,只需要在根目录下新建一个main.py即可正常运行,需要完整功能可私聊或通过公众号购买成品

改进的模型也能用,只需要把代码插入到改进的文件夹中即可。

本文的可视化UI界面对于Ultralytics(目前的YOLOv12 & YOLOv11 & YOLOv10 & YOLOv8通用)的检测、分割、分类、姿势估算(detection, segmentation, obb, classification, and pose estimation)等均可正常显示。

上个版本链接YOLOv11(Ultralytics)可视化界面GUI设计,基于pyside6,单文件即插即用 兼容官方源码,可打包成软件_yolov11 gui-CSDN博客

此次美化了界面外观布局,添加了检测ip摄像头功能,左侧增加检测信息输出。

使用之前需要配置环境,运行有问题应该先重新按照下文配置环境。

目标检测:YOLOv11(Ultralytics)环境配置,适合0基础纯小白,超详细_yolov11环境配置-CSDN博客文章浏览阅读5.6w次,点赞211次,收藏983次。深度学习目标检测YOLOv11小白教程环境搭建,超级简单的教程,纯新手方便理解,一看就会。_yolov11环境配置https://blog.csdn.net/qq_67105081/article/details/143270109?spm=1001.2014.3001.5502

YOLOv12则看这篇文章

目标检测:YOLOv12环境配置,超详细,适合0基础纯小白-CSDN博客文章浏览阅读1.2k次,点赞30次,收藏26次。小白也可以看懂的YOLOv12教程!YOLOv12 是 YOLO 系列中首个打破传统基于卷积神经网络(CNN)方法的模型,它通过将注意力机制直接集成到目标检测过程中实现了这一突破。因此YOLOv12需要额外配置FlashAttention,此前的YOLO环境均不可用,需要按照最新的教程配置。此外,30系显卡以前的架构不支持较新的FlashAttention2.x,只能通过更换显卡解决。https://blog.csdn.net/qq_67105081/article/details/146316615?spm=1001.2014.3001.5501基于上文环境之外,只需要额外多安装一个pyside6库即可。输入如下指令

pip install pyside6

效果展示

主界面

YOLOv12可视化界面;YOLOv11;YOLOv10;YOLOv8等通用可视化界面GUI设计,基于pyside6,单文件即插即用,更新ip摄像头检测,美化布局及信息输出_第1张图片

检测效果

YOLOv12可视化界面;YOLOv11;YOLOv10;YOLOv8等通用可视化界面GUI设计,基于pyside6,单文件即插即用,更新ip摄像头检测,美化布局及信息输出_第2张图片

本文代码图片检测运行界面如下

YOLOv12可视化界面;YOLOv11;YOLOv10;YOLOv8等通用可视化界面GUI设计,基于pyside6,单文件即插即用,更新ip摄像头检测,美化布局及信息输出_第3张图片

检测效果

YOLOv12可视化界面;YOLOv11;YOLOv10;YOLOv8等通用可视化界面GUI设计,基于pyside6,单文件即插即用,更新ip摄像头检测,美化布局及信息输出_第4张图片

ip摄像头可通过这个文章使用手机测试

通过ip摄像头软件将手机变成云ip摄像头,并用Python读取视频流,可用于实时目标检测摄像头调用_ip摄像头lite-CSDN博客文章浏览阅读731次,点赞5次,收藏8次。通过将手机模拟成IP摄像头,我们可以实现将手机摄像头的画面通过网络传输,进而通过Python程序读取视频画面进行分析、处理等。本文将介绍如何通过一款局域网IP摄像头软件将手机模拟成云摄像头,并使用Python进行视频流的读取,同时运用目标检测算法进行实时物体识别。使用手机软件模拟ip摄像头相比购买专门的IP摄像头设备,成本大大降低。这里我们选择局域网的第一个MJPEG进行连接,可以将网址输入浏览器中,再输入账号密码admin进行查看,或者通过以下python代码在python上调用视频流画面,代码如下。_ip摄像头litehttps://blog.csdn.net/qq_67105081/article/details/143668267?spm=1001.2014.3001.5501

代码

import cv2,sys
import numpy as np
from PySide6.QtGui import *
from PySide6.QtWidgets import *
from PySide6.QtCore import *
from ultralytics import YOLO
from collections import Counter

class GradientWidget(QWidget):
	def paintEvent(self, event):
		painter = QPainter(self)
		gradient = QLinearGradient(0, 0, self.width(), self.height())
		gradient.setColorAt(0, QColor(240, 248, 255))
		gradient.setColorAt(1, QColor(230, 240, 250))
		painter.fillRect(self.rect(), gradient)


class MainWindow(QMainWindow):
	def __init__(self):
		super().__init__()

		self.xiaolian_ui()
		self.model = None
		self.result = None
		self.con = 0.25

	def xiaolian_ui(self):
		self.setFixedSize(1280, 590)
		self.setMinimumSize(1280, 590)
		self.setMaximumSize(1280, 590)
		self.setWindowTitle('@author:笑脸惹桃花')
		self.setWindowIcon(QIcon("icon.png"))

		# 主布局
		main_widget = GradientWidget()
		main_layout = QHBoxLayout(main_widget)
		main_layout.setContentsMargins(15, 15, 15, 15)
		main_layout.setSpacing(15)

		# ===== 左侧控制面板 =====
		left_panel = QWidget()
		left_panel.setMaximumWidth(220)
		left_layout = QVBoxLayout(left_panel)
		left_layout.setContentsMargins(5, 5, 5, 5)
		left_layout.setSpacing(8)

		# Logo
		logo = QLabel("""
YOLOv12 Detection
""") left_layout.addWidget(logo) # 操作按钮 btn_group = QGroupBox("操作面板") btn_group.setStyleSheet(""" QGroupBox { border: 1px solid #95a5a6; border-radius: 4px; margin-top: 6px; } QGroupBox::title { subcontrol-origin: margin; left: 6px; color: #34495e; font: bold 11px; } """) btn_layout = QVBoxLayout() buttons = [ ("加载模型", self.load_model), ("图片检测", self.select_image), ("停止", self.stop_detect) ] for text, slot in buttons: btn = QPushButton(text) btn.setFixedHeight(32) btn.setStyleSheet(f""" QPushButton {{ font: 12px 'Microsoft YaHei'; background: '#f8f9fa' ; border: 1px solid #ced4da; border-radius: 3px; padding: 4px; }} QPushButton:hover {{ background: #e9ecef; }} """) btn.clicked.connect(slot) btn_layout.addWidget(btn) btn_group.setLayout(btn_layout) left_layout.addWidget(btn_group) # 修改状态指示部分为信息输出框 status_group = QGroupBox("检测信息") status_group.setStyleSheet( "QGroupBox { border: 1px solid gray; border-radius: 5px; margin-top: 1ex; } QGroupBox::title { subcontrol-origin: margin; subcontrol-position: top left; padding: 0 3px; }") status_layout = QVBoxLayout() self.output_text = QTextEdit(self) self.output_text.setReadOnly(True) status_layout.addWidget(self.output_text) status_group.setLayout(status_layout) left_layout.addWidget(status_group) left_layout.addStretch() # 退出按钮 exit_btn = QPushButton("退出系统") exit_btn.setFixedHeight(30) exit_btn.setStyleSheet(""" QPushButton { background: #e74c3c; color: white; font: bold 12px 'Microsoft YaHei'; border-radius: 3px; padding: 4px; } QPushButton:hover { background: #c0392b; } """) exit_btn.clicked.connect(self.close) left_layout.addWidget(exit_btn) # ===== 右侧显示区域 ===== right_panel = QWidget() right_layout = QHBoxLayout(right_panel) right_layout.setContentsMargins(0, 0, 0, 0) right_layout.setSpacing(12) def create_display(title): box = QWidget() box.setStyleSheet(""" background: white; border: 1px solid #bdc3c7; border-radius: 5px; """) layout = QVBoxLayout(box) layout.setContentsMargins(0, 0, 0, 0) # 标题栏 title_bar = QLabel(title) title_bar.setStyleSheet(""" background: #f8f9fa; color: #2c3e50; font: bold 30px 'Microsoft YaHei'; padding: 6px; border-bottom: 1px solid #ced4da; """) title_bar.setAlignment(Qt.AlignCenter) layout.addWidget(title_bar) # 图像显示 img_label = QLabel() img_label.setAlignment(Qt.AlignCenter) img_label.setMinimumSize(500, 500) img_label.setMaximumSize(500, 500) img_label.setStyleSheet("background: #2c3e50;") layout.addWidget(img_label) return box, img_label self.cam_box, self.label1 = create_display("实时画面") self.result_box, self.label2 = create_display("检测结果") right_layout.addWidget(self.cam_box) right_layout.addWidget(self.result_box) main_layout.addWidget(left_panel) main_layout.addWidget(right_panel, 1) self.setCentralWidget(main_widget) def load_model(self): self.result = None model_path, _ = QFileDialog.getOpenFileName(self, "选择模型文件", filter='*.pt') if model_path: self.model = YOLO(model_path) def select_image(self): self.result = None image_path, fileType = QFileDialog.getOpenFileName(self, "选择图片文件", filter='*.jpg *.png *.bmp') if image_path: img = cv2.imread(image_path) self.detect_image(img) def stop_detect(self): self.result = None img = cv2.cvtColor(np.zeros((580, 550), np.uint8), cv2.COLOR_BGR2RGB) img = QImage(img.data, img.shape[1], img.shape[0], QImage.Format_RGB888) self.label1.setPixmap(QPixmap.fromImage(img)) self.label2.setPixmap(QPixmap.fromImage(img)) self.display_statistics() def close(self): exit() def detect_image(self, img): if self.model is not None: frame = img results = self.model.predict(frame,conf=self.con) image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) height1, width1, channel1 = frame.shape bytesPerLine1 = 3 * width1 qimage1 = QImage(image_rgb.data, width1, height1, bytesPerLine1, QImage.Format_RGB888) pixmap1 = QPixmap.fromImage(qimage1) self.label1.setPixmap(pixmap1.scaled(self.label1.size(), Qt.AspectRatioMode.IgnoreAspectRatio)) annotated_image = results[0].plot() annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB) # 转换为 RGB height2, width2, channel2 = annotated_image.shape bytesPerLine2 = 3 * width2 qimage2 = QImage(annotated_image.data, width2, height2, bytesPerLine2, QImage.Format_RGB888) pixmap2 = QPixmap.fromImage(qimage2) pixmap2 = pixmap2.scaled(self.label2.size(), Qt.AspectRatioMode.IgnoreAspectRatio) self.result = results self.label2.setPixmap(pixmap2) self.display_statistics() def stat(self): detected_classes = [] target_range = {0, 1} #修改为自己的类别 if self.result == None: return None for r in self.result: classes = r.boxes.cls.cpu().numpy().astype(int).tolist() # 筛选出在目标范围内的类别,并去重 detected_classes.extend([cls for cls in classes if cls in target_range]) class_counts = Counter(detected_classes) class_counts_dic = dict(class_counts) return class_counts_dic def display_statistics(self): class_counts = self.stat() if class_counts == None: self.output_text.setText('') return #修改class_labels为自己的类别对应关系,可中文 class_labels = { 0: "helmet", 1: "vest" } # 构建输出字符串 output_string = "" for class_id, count in class_counts.items(): label = class_labels.get(class_id, f"类别{class_id}") # 如果没有找到标签,则使用默认标签 output_string += f"{label}: {count} 个\n" self.output_text.setText(output_string) def closeEvent(self, event: QEvent): event.accept() if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec())

自己用需要修改自己数据集对应类别。

需要完整功能可私聊或通过公众号购买成品。有其他需求及想要定制的可以私信或通过公众号联系我,遇到报错可以在评论区交流,关注公众号获取更多资源~

你可能感兴趣的:(v11)实战,YOLO,GUI,YOLOv12,python,深度学习,目标检测)