YOLOv11(Ultralytics)可视化界面ui设计,基于pyqt5,单文件即插即用,支持文件夹检测及云摄像头检测并保存

本文的可视化界面对于YOLOv11/Ultralytics/YOLOv8的检测、分割、分类、姿势估算(detection, segmentation, obb, classification, and pose estimation)等均可正常显示。本次新增了图片及视频的保存,可以选择传入文件夹进行检测并显示,可以对本地摄像头或者云摄像头获取的视频进行分段保存,本文仅针对图像处理部分给出代码示例,所有代码只需要在根目录下新建一个main.py即可正常运行,对于视频及摄像头处理可以根据图像处理进行修改后实现功能,或者私聊我获取成品,之前购买过的可私信我免费获取最新的代码。

目录

1.准备工作

1.1 YOLOv11(Ultralytics)源码获取

1.2 YOLOv11环境配置

2.完整界面展示

2.1 主界面展示

2.2 功能展示

2.3 完整功能展示

3.界面实现

3.1 相关库

3.2 导入库

3.3 功能实现

3.3.1 添加按钮

3.3.2 功能函数定义

3.3.3 完整代码

3.4 界面展示


1.准备工作

1.1 YOLOv11(Ultralytics)源码获取

源代码文件获取请查看之前文章,或者点此下载,压缩包内为整合源码及权重文件夹。

YOLOv11官方地址为 

 https://github.com/ultralytics/ultralytics

1.2 YOLOv11环境配置

环境异常请根据下文配置相应python环境,再尝试使用本文提供的可视化界面

目标检测:YOLOv11(Ultralytics)环境配置,适合0基础纯小白,超详细-CSDN博客文章浏览阅读4k次,点赞28次,收藏67次。YOLO11是Ultralytics公司YOLO系列实时目标检测器的最新迭代版本,它以尖端的准确性、速度和效率重新定义了可能实现的性能。在之前YOLO版本取得的显著进步基础上,YOLO11在架构和训练方法上进行了重大改进,使其成为各种计算机视觉任务中的通用选择。除了传统的目标检测外,YOLO11 还支持目标跟踪、实例分割、姿态估计、OBB定向物体检测(旋转目标检测)等视觉任务。如果已经会配置YOLOv8的环境,本文不需要重复配置,下载最新的YOLOv11训练文件即可。_yolov11https://blog.csdn.net/qq_67105081/article/details/143270109?spm=1001.2014.3001.5502建议使用Anaconda3+pycharm,下载8.3.20版本源码。

2.完整界面展示

2.1 主界面展示

界面整体分为三部分,左右图像展示框以及下方功能按钮,下图为运行后界面展示

2.2 功能展示

首先选择模型,选择完之后可以分别点击图片检测选择单张图片检测后显示在界面上,可点击保存到指定位置,点击文件夹检测可以选择一个文件夹后将其按照一定的速度展示,文件夹检测会将检测结果自动保存,视频检测完可以选择保存视频,也可以在检测过程中将视频分段保存,摄像头可选本地和云摄像头,本地会自动获取摄像头编号可选择,云摄像头则需要输入ip后开始检测,均可点击保存为视频。检测之后的图像会实时显示在界面上,左边显示原始图像,右边显示检测后的图像。

也可以选择视频进行检测,效果如下图,可以点击查看当前检测到的所有物体

2.3 完整功能展示

每个按钮的功能及云摄像头的调用都试了一下,效果如下图

有其它需求可私信联系定制。 

3.界面实现

本文仅对图片检测进行展示,如需其它功能界面请私聊获取。

3.1 相关库

除了yolov8所用库之外,本文所用到的额外库为pyqt5,输入指令进行安装

pip install PyQt5

3.2 导入库

我这里导入的是以下这些,同官方源码兼容。

import sys
import os
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QPushButton, QHBoxLayout, QFileDialog, QMessageBox
from PyQt5.QtGui import QImage, QPixmap, QIcon
import cv2
from ultralytics import YOLO

3.3 功能实现

3.3.1 添加按钮

这里实现了权重选择和选择图片及选择文件夹功能并添加了对应的按钮

# 添加模型选择按钮
self.load_model_button = QPushButton("👆模型选择")
self.load_model_button.clicked.connect(self.load_model)
self.load_model_button.setFixedSize(120, 30)
hbox_buttons.addWidget(self.load_model_button)# 添加图片检测按钮
self.image_detect_button = QPushButton("🖼️️图片检测")
self.image_detect_button.clicked.connect(self.select_image)
self.image_detect_button.setEnabled(False)
self.image_detect_button.setFixedSize(120, 30)
hbox_buttons.addWidget(self.image_detect_button)# 添加图片文件夹检测按钮
self.folder_detect_button = QPushButton("️📁文件夹检测")
self.folder_detect_button.clicked.connect(self.detect_folder)
self.folder_detect_button.setEnabled(False)
self.folder_detect_button.setFixedSize(120, 30)
hbox_buttons.addWidget(self.folder_detect_button)# 添加显示检测物体按钮
self.display_objects_button = QPushButton("🔍显示检测物体")
self.display_objects_button.clicked.connect(self.show_detected_objects)
self.display_objects_button.setEnabled(False)
self.display_objects_button.setFixedSize(120, 30)
hbox_buttons.addWidget(self.display_objects_button)# # 添加保存检测结果按钮
self.save_button = QPushButton("💾保存检测结果")
self.save_button.clicked.connect(self.save_detection)
self.save_button.setEnabled(False)
self.save_button.setFixedSize(120, 30)
hbox_buttons.addWidget(self.save_button)# 添加退出按钮
self.exit_button = QPushButton("❌退出")
self.exit_button.clicked.connect(self.exit_application)
self.exit_button.setFixedSize(120, 30)
hbox_buttons.addWidget(self.exit_button)

3.3.2 功能函数定义

检测图片并分别在左右窗口进行显示

def detect_image(self, image_path):if image_path:print(image_path)image = cv2.imread(image_path)if image is not None:if self.flag == 0:results = self.worker.model.predict(image)elif self.flag == 1:results = self.worker.model.predict(image_path, save=True)self.worker.detection_type = "image"if results:self.current_results = resultsself.worker.current_annotated_image = results[0].plot()annotated_image = self.worker.current_annotated_imageimage_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)height1, width1, channel1 = image_rgb.shapebytesPerLine1 = 3 * width1qimage1 = QImage(image_rgb.data, width1, height1, bytesPerLine1, QImage.Format_RGB888)pixmap1 = QPixmap.fromImage(qimage1)self.label1.setPixmap(pixmap1.scaled(self.label1.size(), Qt.KeepAspectRatio))annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)height2, width2, channel2 = annotated_image.shapebytesPerLine2 = 3 * width2qimage2 = QImage(annotated_image.data, width2, height2, bytesPerLine2, QImage.Format_RGB888)pixmap2 = QPixmap.fromImage(qimage2)self.label2.setPixmap(pixmap2.scaled(self.label2.size(), Qt.KeepAspectRatio))self.save_button.setEnabled(True)

加载模型部分代码

def load_model(self):model_path, _ = QFileDialog.getOpenFileName(None, "选择模型文件", "", "模型文件 (*.pt)")if model_path:self.model = YOLO(model_path)return self.model is not Nonereturn False

 选择图片/文件夹部分代码

    def select_image(self):image_path, _ = QFileDialog.getOpenFileName(None, "选择图片文件", "", "图片文件 (*.jpg *.jpeg *.png)")self.flag = 0if image_path:self.detect_image(image_path)def detect_folder(self):folder_path = QFileDialog.getExistingDirectory(self, "选择图片文件夹")self.flag = 1if folder_path:image_paths = []for filename in os.listdir(folder_path):if filename.lower().endswith((".jpg", ".jpeg", ".png")):image_path = os.path.join(folder_path, filename)image_paths.append(image_path)for image_path in image_paths:self.detect_image(image_path)

3.3.3 完整代码

完整代码如下,全部复制后粘贴进一个空白的py文件即可运行,想要调整文件夹下图片切换速度可以修改 cv2.waitKey(300) 的参数,1秒为1000

import sys
import os
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QPushButton, QHBoxLayout, QFileDialog, QMessageBox
from PyQt5.QtGui import QImage, QPixmap, QIcon
import cv2
from ultralytics import YOLOclass Worker:def __init__(self):self.model = Noneself.current_annotated_image = Noneself.detection_type = Nonedef load_model(self):model_path, _ = QFileDialog.getOpenFileName(None, "选择模型文件", "", "模型文件 (*.pt)")if model_path:self.model = YOLO(model_path)if self.model:return Trueelse:return Falsedef detect_objects(self, frame):det_info = []class_ids = frame[0].boxes.clsclass_names_dict = frame[0].namesfor class_id in class_ids:class_name = class_names_dict[int(class_id)]det_info.append(class_name)return det_infodef save_image(self, image):if image is not None:file_name, _ = QFileDialog.getSaveFileName(None, "保存图片", "", "JPEG (*.jpg);;PNG (*.png);;All Files (*)")if file_name:cv2.imwrite(file_name, image)class MainWindow(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("@author:笑脸惹桃花")#self.setWindowIcon(QIcon("icon.png"))self.setGeometry(300, 150, 1200, 600)# 创建两个 QLabel 分别显示左右图像self.label1 = QLabel()self.label1.setAlignment(Qt.AlignCenter)self.label1.setMinimumSize(580, 450)  # 设置大小self.label1.setStyleSheet('border:3px solid #6950a1; background-color: black;')  # 添加边框并设置背景颜色为黑色self.label2 = QLabel()self.label2.setAlignment(Qt.AlignCenter)self.label2.setMinimumSize(580, 450)  # 设置大小self.label2.setStyleSheet('border:3px solid #6950a1; background-color: black;')  # 添加边框并设置背景颜色为黑色# 水平布局,用于放置左右两个 QLabellayout = QVBoxLayout()hbox_video = QHBoxLayout()hbox_video.addWidget(self.label1)hbox_video.addWidget(self.label2)layout.addLayout(hbox_video)self.worker = Worker()# 创建按钮布局hbox_buttons = QHBoxLayout()# 添加模型选择按钮self.load_model_button = QPushButton("👆模型选择")self.load_model_button.clicked.connect(self.load_model)self.load_model_button.setFixedSize(120, 30)hbox_buttons.addWidget(self.load_model_button)# 添加图片检测按钮self.image_detect_button = QPushButton("🖼️️图片检测")self.image_detect_button.clicked.connect(self.select_image)self.image_detect_button.setEnabled(False)self.image_detect_button.setFixedSize(120, 30)hbox_buttons.addWidget(self.image_detect_button)# 添加图片文件夹检测按钮self.folder_detect_button = QPushButton("️📁文件夹检测")self.folder_detect_button.clicked.connect(self.detect_folder)self.folder_detect_button.setEnabled(False)self.folder_detect_button.setFixedSize(120, 30)hbox_buttons.addWidget(self.folder_detect_button)# 添加显示检测物体按钮self.display_objects_button = QPushButton("🔍显示检测物体")self.display_objects_button.clicked.connect(self.show_detected_objects)self.display_objects_button.setEnabled(False)self.display_objects_button.setFixedSize(120, 30)hbox_buttons.addWidget(self.display_objects_button)# # 添加保存检测结果按钮self.save_button = QPushButton("💾保存检测结果")self.save_button.clicked.connect(self.save_detection)self.save_button.setEnabled(False)self.save_button.setFixedSize(120, 30)hbox_buttons.addWidget(self.save_button)# 添加退出按钮self.exit_button = QPushButton("❌退出")self.exit_button.clicked.connect(self.exit_application)self.exit_button.setFixedSize(120, 30)hbox_buttons.addWidget(self.exit_button)layout.addLayout(hbox_buttons)central_widget = QWidget()central_widget.setLayout(layout)self.setCentralWidget(central_widget)def save_detection(self):detection_type = self.worker.detection_typeif detection_type == "image":self.save_detection_results()def select_image(self):image_path, _ = QFileDialog.getOpenFileName(None, "选择图片文件", "", "图片文件 (*.jpg *.jpeg *.png)")self.flag = 0if image_path:self.detect_image(image_path)def detect_folder(self):folder_path = QFileDialog.getExistingDirectory(self, "选择图片文件夹")self.flag = 1if folder_path:image_paths = []for filename in os.listdir(folder_path):if filename.lower().endswith((".jpg", ".jpeg", ".png")):image_path = os.path.join(folder_path, filename)image_paths.append(image_path)for image_path in image_paths:self.detect_image(image_path)def detect_image(self, image_path):if image_path:print(image_path)image = cv2.imread(image_path)if image is not None:if self.flag == 0:results = self.worker.model.predict(image)elif self.flag == 1:results = self.worker.model.predict(image_path, save=True)self.worker.detection_type = "image"if results:self.current_results = resultsself.worker.current_annotated_image = results[0].plot()annotated_image = self.worker.current_annotated_imageimage_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)height1, width1, channel1 = image_rgb.shapebytesPerLine1 = 3 * width1qimage1 = QImage(image_rgb.data, width1, height1, bytesPerLine1, QImage.Format_RGB888)pixmap1 = QPixmap.fromImage(qimage1)self.label1.setPixmap(pixmap1.scaled(self.label1.size(), Qt.KeepAspectRatio))annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)height2, width2, channel2 = annotated_image.shapebytesPerLine2 = 3 * width2qimage2 = QImage(annotated_image.data, width2, height2, bytesPerLine2, QImage.Format_RGB888)pixmap2 = QPixmap.fromImage(qimage2)self.label2.setPixmap(pixmap2.scaled(self.label2.size(), Qt.KeepAspectRatio))self.save_button.setEnabled(True)cv2.waitKey(300) # 修改图片切换时间def save_detection_results(self):if self.worker.current_annotated_image is not None:self.worker.save_image(self.worker.current_annotated_image)def show_detected_objects(self):frame = self.current_resultsif frame:det_info = self.worker.detect_objects(frame)if det_info:object_count = len(det_info)object_info = f"识别到的物体总个数:{object_count}\n"object_dict = {}for obj in det_info:if obj in object_dict:object_dict[obj] += 1else:object_dict[obj] = 1sorted_objects = sorted(object_dict.items(), key=lambda x: x[1], reverse=True)for obj_name, obj_count in sorted_objects:object_info += f"{obj_name}: {obj_count}\n"self.show_message_box("识别结果", object_info)else:self.show_message_box("识别结果", "未检测到物体")def show_message_box(self, title, message):msg_box = QMessageBox(self)msg_box.setWindowTitle(title)msg_box.setText(message)msg_box.exec_()def load_model(self):if self.worker.load_model():self.image_detect_button.setEnabled(True)self.folder_detect_button.setEnabled(True)self.display_objects_button.setEnabled(True)def exit_application(self):sys.exit()if __name__ == '__main__':app = QApplication(sys.argv)window = MainWindow()window.show()sys.exit(app.exec_())

 使用本代码仅需在Ultralytics文件夹中新建一个main.py或者其它名字的py文件然后运行即可,运行有报错可以发在评论区,看到都会及时回复。

3.4 界面展示

这样一个简单的ui界面就写好了

需要更多功能的及其他需求可以私聊,遇到报错可以在评论区交流~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/60291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用python开发坦克大战重制版

Python 开发坦克大战重制版:全面教程 引言 坦克大战是一款经典的街机游戏,自1985年首次推出以来,便吸引了无数玩家。随着时间的推移,许多游戏开发者开始尝试重制这款经典游戏。本文将指导你如何使用 Python 和 Pygame 库开发一个…

链式结构二叉树

数据结构 结点申请 树🌲行结构 前中后序遍历 二叉树结点个数 二叉树叶子节点个数 第k层结点个数 二叉树深度 二叉树查找值为x的结点 二叉树销毁

【2024软考架构案例题】你知道什么是 RESTful 风格吗?

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO 专家博主 ⛪️ 个人社区&#x…

Java 封装(Encapsulation)详解

封装是面向对象编程(OOP)中的一个核心概念,它涉及将数据(变量)和操作这些数据的方法(函数)捆绑成一个单一的单元或类。封装的主要目的是限制对对象某些组件的直接访问,从而保护数据的…

wordpress站外调用指定ID分类下的推荐内容

在WordPress中,如果你想从站外调用指定ID分类下的推荐内容,你可以使用WordPress REST API来实现。以下是一个基本的步骤指南: 1. 启用REST API 确保你的WordPress站点已经启用了REST API。大多数现代WordPress版本默认启用此功能。 2. 获取…

#渗透测试#SRC漏洞挖掘#深入挖掘CSRF漏洞02

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停…

自动驾驶革命:从特斯拉到百度,谁将主宰未来交通?

内容概要 自动驾驶技术正在经历一个前所未有的革命性变化,各大企业纷纷抢占这一充满潜力的新市场。以特斯拉和百度为代表的行业巨头,正利用各自的优势在这一技术的赛道上展开激烈竞争。特斯拉凭借其在电动汽车和自动驾驶领域的前瞻性设计与不断革新的技…

反向代理开发

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求,然后将请求转发给内部网络上的服务器,将从服务器上得到的结果返回给客户端,此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说,反向代理就相当于…

语义SOP(Semantic SOP)

语义SOP(Semantic SOP)指的是将标准操作流程(Standard Operating Procedures,SOP)融入语义信息,以便更智能地管理、执行和优化流程。通过引入语义技术,可以增强 SOP 的可理解性、自动化水平和灵…

【Python】爬虫通过验证码

1、将验证码下载至本地 # 获取验证码界面html url http://www.example.com/a.html resp requests.get(url) soup BeautifulSoup(resp.content.decode(UTF-8), html.parser)#找到验证码图片标签,获取其地址 src soup.select_one(div.captcha-row img)[src]# 验证…

【C#】深拷贝和浅拷贝、区别

深拷贝和浅拷贝的概念 在 C# 中,深拷贝和浅拷贝是两种不同的对象复制方式,用来复制对象中的数据到新的对象。它们的主要区别在于是否会复制对象引用的子对象。 浅拷贝(Shallow Copy): 浅拷贝只复制对象的引用&#xf…

Spring中的 bean 标签中的 factory-bean , factory-method

1.首先说说 factory-method 是指定创造实例的工厂方法,用法: factory-method 和 class 配合使用,这时 factory-method 必须是class所指定的类中的一个静态方法,也就是Spring会直接调用 class 所指定的类的静态工厂方法创建一个实例…

【大数据测试 Elasticsearch — 详细教程及实例】

大数据测试 Elasticsearch — 详细教程及实例 1. Elasticsearch 基础概述核心概念 2. 搭建 Elasticsearch 环境2.1 安装 Elasticsearch2.2 配置 Elasticsearch 3. 大数据测试的常见方法3.1 使用 Logstash 导入大数据3.2 使用 Elasticsearch 的 Bulk API3.3 使用 Benchmark 工具…

简记Vue3(五)—— Pinia

个人简介 👀个人主页: 前端杂货铺 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…

C++11语法介绍(1) -- 列表初始化{},左值和右值,右值引用和移动语义,引用折叠,完美转发

目录 1.C11的发展时间线 2.列表初始化 2.1C98传统的{} 2.2C11中的{} 2.3C11中的std::initializer_list 2.3.1vector中initializer list构造的模拟实现 2.3.2以vector为例演示initializer_list版本的构造 3.右值引用和移动语义 3.1左值和右值 3.2左值引用和右值引用 3.3…

C++编程:利用环形缓冲区优化 TCP 发送流程,避免 Short Write 问题

文章目录 1. 什么是 Short Write 问题?2. 如何解决 Short Write 问题?2.1 方法 1:将 Socket 设置为阻塞模式2.2 方法 2:用户态维护发送缓冲区 3. 用户态维护发送缓冲区实现3.1 核心要点3.2 代码实现3.3 测试程序 参考文档 1. 什么…

集群如何延长作业时间

修改时间 要将作业时间延长1天&#xff0c;可以使用以下命令格式&#xff0c;将 TimeLimit 设置为1-00:00:00&#xff0c;表示延长1天&#xff1a; scontrol update jobid<job_id> TimeLimit1-00:00:00在此格式中&#xff1a; 1-00:00:00 表示1天0小时0分钟0秒。 如何…

第十三届交通运输研究(上海)论坛┆智能网联汽车技术现状与研究实践

0.简介 交通运输研究&#xff08;上海&#xff09;论坛&#xff08;简称为TRF&#xff09;是按照国际会议的组织原则&#xff0c;为综合交通运输领域学者们构建的良好合作交流平台。交通运输研究&#xff08;上海&#xff09;论坛已经成功举办了十二届&#xff0c;凝聚了全国百…

SpringBoot开发——Spring Boot 3种定时任务方式

文章目录 一、什么是定时任务二、代码示例1、 @Scheduled 定时任务2、多线程定时任务3、基于接口(SchedulingConfigurer)实现动态更改定时任务3.1 数据库中存储cron信息3.2 pom.xml文件中增加mysql依赖3.3 application.yaml文件中增加mysql数据库配置:3.4 创建定时器3.5 启动…

CMS那点事

大家好&#xff0c;今天我们来深入探讨JVM垃圾回收机制中备受关注的老年代垃圾回收器——CMS&#xff08;Concurrent Mark Sweep&#xff09;。 CMS垃圾回收算法&#xff1a;标记-清理 CMS的核心算法是标记-清理。简单来说&#xff0c;它分为两个主要步骤&#xff1a; 标记&a…