
在工业安全生产监管中手套佩戴识别一直是重要的安全防护环节。传统的人工巡检方式效率低下且容易遗漏而基于深度学习的自动化检测系统能够有效解决这一问题。本文将详细介绍如何基于YOLOv8算法构建一套完整的安全手套佩戴识别检测系统包含从环境配置、模型训练到UI界面开发的完整流程。1. 项目背景与核心概念1.1 安全手套识别的重要性在建筑工地、工厂车间、电力作业等高危工作环境中规范佩戴安全手套是防止手部伤害的基本要求。传统的人工监控存在以下痛点监控盲区难以覆盖人工巡检成本高实时性差无法及时预警主观判断标准不一致基于YOLOv8的自动识别系统能够实现7×24小时不间断监控准确识别作业人员是否规范佩戴手套有效提升安全生产管理的智能化水平。1.2 YOLOv8算法简介YOLOv8是Ultralytics公司推出的最新一代目标检测算法相比前代版本在精度和速度上都有显著提升。其主要特点包括骨干网络优化采用更高效的CSPDarknet53结构特征金字塔增强改进的PAN-FPN结构提升多尺度检测能力损失函数改进使用CIoU Loss提高边界框回归精度训练策略优化引入Mosaic数据增强和自适应锚框计算1.3 系统架构概述整个系统采用模块化设计主要包括数据预处理模块图像增强、标注格式转换模型训练模块YOLOv8模型训练与优化推理检测模块实时目标检测与结果可视化UI交互模块基于PyQt5的用户界面2. 环境配置与依赖安装2.1 系统环境要求推荐使用以下环境配置操作系统Windows 10/11 或 Ubuntu 18.04Python版本3.8-3.10深度学习框架PyTorch 1.12GPU支持NVIDIA GPU可选推荐GTX 1060以上2.2 创建虚拟环境使用Anaconda创建独立的Python环境避免依赖冲突# 创建名为yolov8的虚拟环境 conda create -n yolov8 python3.9 # 激活环境 conda activate yolov82.3 安装核心依赖库创建requirements.txt文件包含项目所需的所有依赖# requirements.txt ultralytics8.0.0 torch1.12.0 torchvision0.13.0 opencv-python4.5.0 PyQt55.15.0 numpy1.21.0 pillow8.0.0 matplotlib3.5.0 seaborn0.11.0 pandas1.3.0使用pip批量安装依赖pip install -r requirements.txt2.4 PyTorch GPU版本安装可选如果使用GPU加速训练需要安装CUDA版本的PyTorch# 根据CUDA版本选择对应的PyTorch pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu1173. 数据集准备与处理3.1 数据集结构设计安全手套识别数据集包含两个类别Gloves佩戴手套NO-Gloves未佩戴手套数据集按照YOLO格式组织datasets/ ├── images/ │ ├── train/ # 训练集图像 │ ├── val/ # 验证集图像 │ └── test/ # 测试集图像 └── labels/ ├── train/ # 训练集标注 ├── val/ # 验证集标注 └── test/ # 测试集标注3.2 数据标注规范使用LabelImg等工具进行标注标注文件为YOLO格式的txt文件# 标注格式class_id x_center y_center width height 0 0.512 0.634 0.124 0.256 1 0.723 0.445 0.089 0.1673.3 数据集配置文件创建data.yaml配置文件定义数据集路径和类别信息# data.yaml path: F:\安全手套佩戴识别检测数据集 train: images/train val: images/val test: images/test nc: 2 # 类别数量 names: [Gloves, NO-Gloves] # 类别名称 # 下载命令/URL可选 download: None3.4 数据增强策略为提高模型泛化能力采用以下数据增强技术# 数据增强配置示例 augmentation { hsv_h: 0.015, # 色调调整 hsv_s: 0.7, # 饱和度调整 hsv_v: 0.4, # 明度调整 translate: 0.1, # 平移 scale: 0.5, # 缩放 flipud: 0.0, # 上下翻转 fliplr: 0.5, # 左右翻转 mosaic: 1.0, # 马赛克增强 mixup: 0.0 # MixUp增强 }4. 模型训练与优化4.1 模型选择策略YOLOv8提供多种规模的预训练模型根据实际需求选择# 模型规模对比 model_configs { yolov8n: {参数: 3.2M, 速度: 最快, 精度: 基础}, yolov8s: {参数: 11.2M, 速度: 快, 精度: 平衡}, yolov8m: {参数: 25.9M, 速度: 中等, 精度: 较好}, yolov8l: {参数: 43.7M, 速度: 较慢, 精度: 高}, yolov8x: {参数: 68.2M, 速度: 慢, 精度: 最高} }4.2 训练代码实现创建完整的训练脚本# train.py from ultralytics import YOLO import argparse def main(): parser argparse.ArgumentParser(descriptionYOLOv8安全手套识别训练脚本) parser.add_argument(--model, typestr, defaultyolov8s.pt, help预训练模型路径) parser.add_argument(--data, typestr, defaultdatasets/data.yaml, help数据集配置文件) parser.add_argument(--epochs, typeint, default500, help训练轮数) parser.add_argument(--batch, typeint, default64, help批次大小) parser.add_argument(--imgsz, typeint, default640, help输入图像尺寸) parser.add_argument(--device, typestr, default0, help训练设备) args parser.parse_args() # 加载模型 model YOLO(args.model) # 开始训练 results model.train( dataargs.data, epochsargs.epochs, batchargs.batch, imgszargs.imgsz, deviceargs.device, workers0, projectruns/detect, namegloves_detection, saveTrue, exist_okTrue ) print(训练完成) if __name__ __main__: main()4.3 训练参数调优关键训练参数配置说明training_config { lr0: 0.01, # 初始学习率 lrf: 0.01, # 最终学习率 momentum: 0.937, # 动量 weight_decay: 0.0005, # 权重衰减 warmup_epochs: 3.0, # 热身轮数 warmup_momentum: 0.8,# 热身动量 warmup_bias_lr: 0.1, # 热身偏置学习率 box: 7.5, # 边界框损失权重 cls: 0.5, # 分类损失权重 dfl: 1.5, # DFL损失权重 close_mosaic: 10 # 关闭马赛克增强的轮数 }4.4 训练过程监控使用TensorBoard监控训练过程# 启动TensorBoard tensorboard --logdir runs/detect关键监控指标损失函数变化box_loss, cls_loss, dfl_loss验证集精度precision, recall, mAP50, mAP50-95学习率变化曲线5. 模型评估与测试5.1 评估指标解读# 模型评估脚本 from ultralytics import YOLO def evaluate_model(): # 加载最佳模型 model YOLO(runs/detect/gloves_detection/weights/best.pt) # 在验证集上评估 metrics model.val( datadatasets/data.yaml, splitval, batch16, imgsz640, conf0.25, iou0.45 ) # 输出评估结果 print(fmAP50: {metrics.box.map50:.4f}) print(fmAP50-95: {metrics.box.map:.4f}) print(fPrecision: {metrics.box.precision:.4f}) print(fRecall: {metrics.box.recall:.4f}) if __name__ __main__: evaluate_model()5.2 混淆矩阵分析通过混淆矩阵分析模型在不同类别上的表现# 生成混淆矩阵 from ultralytics import YOLO import matplotlib.pyplot as plt model YOLO(runs/detect/gloves_detection/weights/best.pt) model.confusion_matrix()5.3 测试集性能验证在独立测试集上验证模型泛化能力def test_model(): model YOLO(runs/detect/gloves_detection/weights/best.pt) # 测试集评估 test_metrics model.val( datadatasets/data.yaml, splittest, batch16 ) return test_metrics6. UI界面开发6.1 PyQt5界面设计创建主界面类实现完整的用户交互功能# main_window.py import sys import os import cv2 import numpy as np from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt, QTimer, pyqtSignal from PyQt5.QtGui import QImage, QPixmap, QIcon, QFont from PyQt5.QtWidgets import (QMainWindow, QFileDialog, QMessageBox, QTableWidgetItem, QHeaderView, QProgressBar) from ultralytics import YOLO class DetectionThread(QtCore.QThread): 检测线程类避免界面卡顿 finished_signal pyqtSignal(object) error_signal pyqtSignal(str) def __init__(self, model, image, conf_threshold, iou_threshold): super().__init__() self.model model self.image image self.conf_threshold conf_threshold self.iou_threshold iou_threshold def run(self): try: results self.model.predict( self.image, confself.conf_threshold, iouself.iou_threshold, verboseFalse ) self.finished_signal.emit(results) except Exception as e: self.error_signal.emit(str(e)) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.model None self.current_image None self.current_results None self.cap None self.timer QTimer() self.video_writer None self.output_dir output # 创建输出目录 if not os.path.exists(self.output_dir): os.makedirs(self.output_dir) self.setup_ui() self.connect_signals() def setup_ui(self): 设置用户界面 self.setWindowTitle(YOLOv8安全手套识别系统) self.setGeometry(100, 100, 1600, 900) # 设置窗口图标 self.setWindowIcon(QIcon(icon.ico)) # 创建中央部件 central_widget QtWidgets.QWidget() self.setCentralWidget(central_widget) # 主布局 main_layout QtWidgets.QHBoxLayout(central_widget) main_layout.setContentsMargins(10, 10, 10, 10) main_layout.setSpacing(15) # 左侧图像显示区域 left_layout self.create_image_display() main_layout.addLayout(left_layout, 3) # 右侧控制面板 right_layout self.create_control_panel() main_layout.addLayout(right_layout, 1) # 状态栏 self.setup_statusbar() def create_image_display(self): 创建图像显示区域 layout QtWidgets.QVBoxLayout() layout.setSpacing(15) # 原始图像显示 original_group QtWidgets.QGroupBox(原始图像) original_group.setMinimumHeight(400) self.original_label QtWidgets.QLabel() self.original_label.setAlignment(Qt.AlignCenter) self.original_label.setText(等待加载图像...) self.original_label.setStyleSheet(border: 1px solid #cccccc; background-color: #f8f9fa;) original_layout QtWidgets.QVBoxLayout() original_layout.addWidget(self.original_label) original_group.setLayout(original_layout) layout.addWidget(original_group) # 检测结果图像显示 result_group QtWidgets.QGroupBox(检测结果) result_group.setMinimumHeight(400) self.result_label QtWidgets.QLabel() self.result_label.setAlignment(Qt.AlignCenter) self.result_label.setText(检测结果将显示在这里) self.result_label.setStyleSheet(border: 1px solid #cccccc; background-color: #f8f9fa;) result_layout QtWidgets.QVBoxLayout() result_layout.addWidget(self.result_label) result_group.setLayout(result_layout) layout.addWidget(result_group) return layout def create_control_panel(self): 创建控制面板 layout QtWidgets.QVBoxLayout() layout.setSpacing(15) # 模型设置组 model_group self.create_model_group() layout.addWidget(model_group) # 参数设置组 param_group self.create_parameter_group() layout.addWidget(param_group) # 功能按钮组 func_group self.create_function_group() layout.addWidget(func_group) # 检测结果表格 table_group self.create_result_table() layout.addWidget(table_group, 1) return layout def create_model_group(self): 创建模型设置组 group QtWidgets.QGroupBox(模型设置) layout QtWidgets.QVBoxLayout() # 模型选择 self.model_combo QtWidgets.QComboBox() self.model_combo.addItems([yolov8n.pt, yolov8s.pt, yolov8m.pt, best.pt]) # 加载模型按钮 self.load_btn QtWidgets.QPushButton(加载模型) self.load_btn.setStyleSheet(self.get_button_style(#4CAF50)) layout.addWidget(QtWidgets.QLabel(选择模型:)) layout.addWidget(self.model_combo) layout.addWidget(self.load_btn) group.setLayout(layout) return group def create_parameter_group(self): 创建参数设置组 group QtWidgets.QGroupBox(检测参数) layout QtWidgets.QFormLayout() # 置信度阈值 self.conf_slider QtWidgets.QSlider(Qt.Horizontal) self.conf_slider.setRange(1, 99) self.conf_slider.setValue(25) self.conf_label QtWidgets.QLabel(0.25) # IoU阈值 self.iou_slider QtWidgets.QSlider(Qt.Horizontal) self.iou_slider.setRange(1, 99) self.iou_slider.setValue(45) self.iou_label QtWidgets.QLabel(0.45) layout.addRow(置信度阈值:, self.conf_slider) layout.addRow(当前值:, self.conf_label) layout.addRow(IoU阈值:, self.iou_slider) layout.addRow(当前值:, self.iou_label) group.setLayout(layout) return group def create_function_group(self): 创建功能按钮组 group QtWidgets.QGroupBox(检测功能) layout QtWidgets.QVBoxLayout() # 功能按钮 self.image_btn QtWidgets.QPushButton(图片检测) self.video_btn QtWidgets.QPushButton(视频检测) self.camera_btn QtWidgets.QPushButton(摄像头检测) self.stop_btn QtWidgets.QPushButton(停止检测) self.save_btn QtWidgets.QPushButton(保存结果) # 设置按钮样式 buttons [self.image_btn, self.video_btn, self.camera_btn, self.stop_btn, self.save_btn] colors [#2196F3, #2196F3, #2196F3, #f44336, #ff9800] for btn, color in zip(buttons, colors): btn.setStyleSheet(self.get_button_style(color)) layout.addWidget(btn) # 初始状态设置 self.stop_btn.setEnabled(False) self.save_btn.setEnabled(False) group.setLayout(layout) return group def create_result_table(self): 创建结果表格 group QtWidgets.QGroupBox(检测结果详情) layout QtWidgets.QVBoxLayout() self.result_table QtWidgets.QTableWidget() self.result_table.setColumnCount(5) self.result_table.setHorizontalHeaderLabels([ID, 类别, 置信度, 位置, 状态]) self.result_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) layout.addWidget(self.result_table) group.setLayout(layout) return group def setup_statusbar(self): 设置状态栏 self.status_bar self.statusBar() self.status_bar.showMessage(就绪) # 添加进度条 self.progress_bar QProgressBar() self.progress_bar.setMaximumWidth(200) self.progress_bar.setVisible(False) self.status_bar.addPermanentWidget(self.progress_bar) def get_button_style(self, color): 获取按钮样式 return f QPushButton {{ padding: 10px; background-color: {color}; color: white; border: none; border-radius: 4px; font-weight: bold; }} QPushButton:hover {{ background-color: {self.darken_color(color)}; }} QPushButton:disabled {{ background-color: #cccccc; }} def darken_color(self, color): 颜色变暗 return f#{hex(int(color[1:3], 16) - 30)[2:]:02}{hex(int(color[3:5], 16) - 30)[2:]:02}{hex(int(color[5:7], 16) - 30)[2:]:02} def connect_signals(self): 连接信号槽 self.load_btn.clicked.connect(self.load_model) self.image_btn.clicked.connect(self.detect_image) self.video_btn.clicked.connect(self.detect_video) self.camera_btn.clicked.connect(self.detect_camera) self.stop_btn.clicked.connect(self.stop_detection) self.save_btn.clicked.connect(self.save_result) self.conf_slider.valueChanged.connect(self.update_conf_value) self.iou_slider.valueChanged.connect(self.update_iou_value) self.timer.timeout.connect(self.update_frame) def load_model(self): 加载模型 try: model_path self.model_combo.currentText() self.model YOLO(model_path) self.status_bar.showMessage(f模型 {model_path} 加载成功) # 启用检测按钮 self.image_btn.setEnabled(True) self.video_btn.setEnabled(True) self.camera_btn.setEnabled(True) except Exception as e: QMessageBox.critical(self, 错误, f模型加载失败: {str(e)}) def update_conf_value(self): 更新置信度阈值显示 conf self.conf_slider.value() / 100 self.conf_label.setText(f{conf:.2f}) def update_iou_value(self): 更新IoU阈值显示 iou self.iou_slider.value() / 100 self.iou_label.setText(f{iou:.2f}) def detect_image(self): 图片检测 if not self.model: QMessageBox.warning(self, 警告, 请先加载模型) return file_path, _ QFileDialog.getOpenFileName( self, 选择图片, , 图片文件 (*.jpg *.jpeg *.png *.bmp);;所有文件 (*) ) if file_path: self.process_image(file_path) def process_image(self, file_path): 处理单张图片 try: # 读取图片 img cv2.imread(file_path) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 显示原始图片 self.display_image(img_rgb, self.original_label) self.current_image img_rgb.copy() # 开始检测 self.start_detection(img_rgb, file_path) except Exception as e: QMessageBox.critical(self, 错误, f图片处理失败: {str(e)}) def start_detection(self, image, source_name): 开始目标检测 self.progress_bar.setVisible(True) self.status_bar.showMessage(f正在检测: {os.path.basename(source_name)}...) # 创建检测线程 self.detection_thread DetectionThread( self.model, image, self.conf_slider.value() / 100, self.iou_slider.value() / 100 ) self.detection_thread.finished_signal.connect(self.on_detection_finished) self.detection_thread.error_signal.connect(self.on_detection_error) self.detection_thread.start() def on_detection_finished(self, results): 检测完成回调 self.progress_bar.setVisible(False) try: # 获取检测结果 result_img results[0].plot() self.display_image(result_img, self.result_label) self.current_results results[0] # 更新结果表格 self.update_result_table(results[0]) self.save_btn.setEnabled(True) self.status_bar.showMessage(检测完成) except Exception as e: QMessageBox.critical(self, 错误, f结果处理失败: {str(e)}) def on_detection_error(self, error_msg): 检测错误回调 self.progress_bar.setVisible(False) QMessageBox.critical(self, 错误, f检测过程出错: {error_msg}) def display_image(self, image, label): 在QLabel中显示图像 h, w, ch image.shape bytes_per_line ch * w q_img QImage(image.data, w, h, bytes_per_line, QImage.Format_RGB888) pixmap QPixmap.fromImage(q_img) # 缩放适应标签大小 scaled_pixmap pixmap.scaled( label.width() - 10, label.height() - 10, Qt.KeepAspectRatio, Qt.SmoothTransformation ) label.setPixmap(scaled_pixmap) def update_result_table(self, results): 更新结果表格 self.result_table.setRowCount(0) if hasattr(results, boxes) and results.boxes is not None: boxes results.boxes for i, (xyxy, conf, cls) in enumerate(zip(boxes.xyxy, boxes.conf, boxes.cls)): self.result_table.insertRow(i) # 类别名称 class_name results.names[int(cls)] # 位置信息 x1, y1, x2, y2 map(int, xyxy) position f({x1}, {y1}) - ({x2}, {y2}) # 状态判断 status 合规 if class_name Gloves else 违规 # 填充表格 self.result_table.setItem(i, 0, QTableWidgetItem(str(i1))) self.result_table.setItem(i, 1, QTableWidgetItem(class_name)) self.result_table.setItem(i, 2, QTableWidgetItem(f{conf:.3f})) self.result_table.setItem(i, 3, QTableWidgetItem(position)) self.result_table.setItem(i, 4, QTableWidgetItem(status)) def detect_video(self): 视频检测 if not self.model: QMessageBox.warning(self, 警告, 请先加载模型) return file_path, _ QFileDialog.getOpenFileName( self, 选择视频, , 视频文件 (*.mp4 *.avi *.mov *.mkv);;所有文件 (*) ) if file_path: self.start_video_detection(file_path) def start_video_detection(self, file_path): 开始视频检测 try: self.cap cv2.VideoCapture(file_path) if not self.cap.isOpened(): raise Exception(无法打开视频文件) # 获取视频信息 self.fps self.cap.get(cv2.CAP_PROP_FPS) self.width int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)) self.height int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 设置按钮状态 self.stop_btn.setEnabled(True) self.image_btn.setEnabled(False) self.video_btn.setEnabled(False) self.camera_btn.setEnabled(False) # 开始定时器 self.timer.start(int(1000 / self.fps)) self.status_bar.showMessage(f正在处理视频: {os.path.basename(file_path)}) except Exception as e: QMessageBox.critical(self, 错误, f视频检测失败: {str(e)}) def detect_camera(self): 摄像头检测 if not self.model: QMessageBox.warning(self, 警告, 请先加载模型) return try: # 尝试打开默认摄像头 self.cap cv2.VideoCapture(0) if not self.cap.isOpened(): raise Exception(无法打开摄像头) # 设置按钮状态 self.stop_btn.setEnabled(True) self.image_btn.setEnabled(False) self.video_btn.setEnabled(False) self.camera_btn.setEnabled(False) # 开始定时器 self.timer.start(30) # 约30fps self.status_bar.showMessage(摄像头实时检测中...) except Exception as e: QMessageBox.critical(self, 错误, f摄像头检测失败: {str(e)}) def update_frame(self): 更新视频/摄像头帧 if self.cap and self.cap.isOpened(): ret, frame self.cap.read() if ret: # 转换颜色空间 frame_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 显示原始帧 self.display_image(frame_rgb, self.original_label) # 进行检测 results self.model.predict( frame_rgb, confself.conf_slider.value() / 100, iouself.iou_slider.value() / 100, verboseFalse ) # 显示检测结果 result_frame results[0].plot() self.display_image(result_frame, self.result_label) # 更新结果表格 self.update_result_table(results[0]) def stop_detection(self): 停止检测 self.timer.stop() if self.cap: self.cap.release() self.cap None # 恢复按钮状态 self.stop_btn.setEnabled(False) self.image_btn.setEnabled(True) self.video_btn.setEnabled(True) self.camera_btn.setEnabled(True) self.status_bar.showMessage(检测已停止) def save_result(self): 保存检测结果 if self.current_results is None: QMessageBox.warning(self, 警告, 没有可保存的检测结果) return try: file_path, _ QFileDialog.getSaveFileName( self, 保存结果, os.path.join(self.output_dir, detection_result.jpg), 图片文件 (*.jpg *.png) ) if file_path: # 保存结果图像 result_img_bgr cv2.cvtColor(self.current_results.plot(), cv2.COLOR_RGB2BGR) cv2.imwrite(file_path, result_img_bgr) # 保存检测信息到文本文件 info_file file_path.replace(.jpg, _info.txt).replace(.png, _info.txt) with open(info_file, w, encodingutf-8) as f: f.write(安全手套检测结果报告\n) f.write( * 50 \n) if hasattr(self.current_results, boxes) and self.current_results.boxes is not None: boxes self.current_results.boxes for i, (xyxy, conf, cls) in enumerate(zip(boxes.xyxy, boxes.conf, boxes.cls)): class_name self.current_results.names[int(cls)] status 合规 if class_name Gloves else 违规 f.write(f检测目标 {i1}:\n) f.write(f 类别: {class_name}\n) f.write(f 置信度: {conf:.3f}\n) f.write(f 状态: {status}\n) f.write(f 位置: {xyxy.tolist()}\n\n) QMessageBox.information(self, 成功, f结果已保存到:\n{file_path}) except Exception as e: QMessageBox.critical(self, 错误, f保存失败: {str(e)}) def main(): app QtWidgets.QApplication(sys.argv) app.setFont(QFont(Microsoft YaHei, 9)) window MainWindow() window.show() sys.exit(app.exec_()) if __name__ __main__: main()6.2 界面样式优化创建专业的CSS样式表提升用户体验/* styles.css */ QMainWindow { background-color: #f5f5f5; font-family: Microsoft YaHei, sans-serif; } QGroupBox { border: 2px solid #e0e0e0; border-radius: 8px; margin-top: 10px; padding-top: 15px; background-color: white; } QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 8px; background-color: white; color: #333; font-weight: bold; } QLabel { color: #333; font-size: 9pt; } QPushButton { padding: 8px 16px; border: none; border-radius: 4px; font-weight: bold; min-height: 20px; } QPushButton:hover { opacity: 0.9; } QPushButton:disabled { background-color: #cccccc; color: #666666; } QTableWidget { border: 1px solid #e0e0e0; alternate-background-color: #f9f9f9; selection-background-color: #e3f2fd; } QHeaderView::section { background-color: #2196F3; color: white; padding: 6px; border: none; font-weight: bold; } QSlider::groove:horizontal { height: 6px; background: #e0e0e0; border-radius: 3px; } QSlider::handle:horizontal { width: 16px; height: 16px; margin: -5px 0; background: #2196F3; border-radius: 8px; } QSlider::sub-page:horizontal { background: #2196F3; border-radius: 3px; } QProgressBar { border: 1px solid #ccc; border-radius: 3px; text-align: center; } QProgressBar::chunk { background-color: #4CAF50; width: 10px; }7. 系统部署与优化7.1 模型量化与加速为提升推理速度可以对模型进行量化# 模型量化脚本 from ultralytics import YOLO def quantize_model(): # 加载训练好的模型 model YOLO(runs/detect/gloves_detection/weights/best.pt) # 导出为ONNX格式包含量化 model.export( formatonnx, dynamicTrue, simplifyTrue, opset12 )