10分钟上手目标检测YOLO标注训练一体化工具,支持yolov5/v8/v9/v10/v11/v12/v26,

10分钟上手目标检测YOLO标注训练一体化工具,支持yolov5/v8/v9/v10/v11/v12/v26,新手也能10分钟上手目标检测,不用懂代码,不用搭环境,解压即用,省心省力。
在这里插入图片描述

支持:懒人精灵,按键精灵,autogo,lua等多种调用模型导出
在这里插入图片描述

核心优势:在这里插入图片描述

  • 免环境部署,省时间在这里插入图片描述

  • 全模型全标注类型,

  • 在这里插入图片描述

YOLO可视化标注训练一体化工具

工具核心功能与优势说明

模块功能描述优势亮点
数据标注(Annotation)支持Detect目标检测、Segment实例分割、Classify图像分类、Pose姿态估计、OBB旋转目标检测;支持自动标注、找图匹配标注,内置快捷键提升标注效率自动标注可降低80%手动工作量,找图标注大幅提升效率,多标注类型全覆盖
图片采集(Capture)可采集训练/测试图片,快速扩充数据集无需额外工具,一站式完成数据准备
模型训练(Train)支持YOLOv5/v8/v9/v10/v11/v12/v26全系列模型训练;支持断点续训、二次训练、自定义训练参数;支持10-50系列显卡GPU加速免环境部署,训练效率高,新手友好,灵活适配不同训练需求
模型验证(Validate)对训练后的模型进行精度验证,查看检测效果快速评估模型性能,无需额外代码
模型预测(Predict)加载训练好的模型,对图片/视频进行实时检测一键测试模型效果,直观查看检测结果
模型转换(Export)一键导出ONNX、NCNN格式模型,支持懒人精灵、按键精灵、AutoGO、Lua等调用适配多场景部署,支持各类自动化脚本调用
基础设置/帮助内置完整使用说明,功能分区明确,无深度学习基础也可操作新手友好,10分钟快速上手

工具核心构建代码(Python+PyQt5+Ultralytics)

以下是工具的核心框架代码,实现标注、训练、预测、转换全流程功能:

import sys
import os
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTabWidget, QWidget, QVBoxLayout, 
                             QHBoxLayout, QPushButton, QLineEdit, QLabel, QFileDialog,
                             QSpinBox, QDoubleSpinBox, QCheckBox, QTextEdit, QComboBox,
                             QGroupBox, QScrollArea, QListWidget, QListWidgetItem)
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from ultralytics import YOLO
import cv2
import numpy as np

# 训练线程(避免界面卡顿)
class TrainThread(QThread):
    log_signal = pyqtSignal(str)
    def __init__(self, model_path, data_yaml, epochs, batch, imgsz, device, resume=False):
        super().__init__()
        self.model_path = model_path
        self.data_yaml = data_yaml
        self.epochs = epochs
        self.batch = batch
        self.imgsz = imgsz
        self.device = device
        self.resume = resume

    def run(self):
        try:
            model = YOLO(self.model_path)
            self.log_signal.emit(f"✅ 加载模型: {self.model_path}")
            model.train(
                data=self.data_yaml,
                epochs=self.epochs,
                batch=self.batch,
                imgsz=self.imgsz,
                device=self.device,
                resume=self.resume,
                verbose=True
            )
            self.log_signal.emit("✅ 训练完成!模型保存在 runs/detect/train/weights/")
        except Exception as e:
            self.log_signal.emit(f"❌ 训练出错: {str(e)}")

# 预测线程
class PredictThread(QThread):
    log_signal = pyqtSignal(str)
    result_signal = pyqtSignal(np.ndarray)
    def __init__(self, model_path, img_path, conf, iou):
        super().__init__()
        self.model_path = model_path
        self.img_path = img_path
        self.conf = conf
        self.iou = iou

    def run(self):
        try:
            model = YOLO(self.model_path)
            self.log_signal.emit(f"✅ 加载模型: {self.model_path}")
            results = model.predict(
                source=self.img_path,
                conf=self.conf,
                iou=self.iou,
                show=False,
                save=False
            )
            for result in results:
                img = result.plot()
                self.result_signal.emit(img)
                self.log_signal.emit("✅ 预测完成!")
        except Exception as e:
            self.log_signal.emit(f"❌ 预测出错: {str(e)}")

# 模型转换线程
class ExportThread(QThread):
    log_signal = pyqtSignal(str)
    def __init__(self, model_path, format, imgsz):
        super().__init__()
        self.model_path = model_path
        self.format = format
        self.imgsz = imgsz

    def run(self):
        try:
            model = YOLO(self.model_path)
            self.log_signal.emit(f"✅ 加载模型: {self.model_path}")
            model.export(format=self.format, imgsz=self.imgsz)
            self.log_signal.emit(f"✅ 转换完成!导出格式: {self.format}")
        except Exception as e:
            self.log_signal.emit(f"❌ 转换出错: {str(e)}")

# 主窗口
class YoloToolWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("YOLO全系列可视化标注训练工具 (v5/v8/v9/v10/v11/v12/v26)")
        self.setGeometry(100, 100, 1200, 900)
        self.init_ui()

    def init_ui(self):
        # 中心部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        # 选项卡
        self.tab_widget = QTabWidget()
        self.tab_widget.addTab(self.create_annotation_tab(), "数据标注 (Annotation)")
        self.tab_widget.addTab(self.create_capture_tab(), "图片采集 (Capture)")
        self.tab_widget.addTab(self.create_train_tab(), "模型训练 (Train)")
        self.tab_widget.addTab(self.create_validate_tab(), "模型验证 (Validate)")
        self.tab_widget.addTab(self.create_export_tab(), "模型转换 (Export)")
        self.tab_widget.addTab(self.create_help_tab(), "使用说明 (Help)")
        main_layout.addWidget(self.tab_widget)

    # 1. 数据标注选项卡(简化版,完整标注功能需额外实现标注画布)
    def create_annotation_tab(self):
        tab = QWidget()
        layout = QHBoxLayout(tab)

        # 左侧标注画布区域
        left_layout = QVBoxLayout()
        self.annotation_label = QLabel("标注画布区域")
        self.annotation_label.setStyleSheet("border: 1px solid black; background-color: #f0f0f0;")
        self.annotation_label.setMinimumSize(800, 600)
        left_layout.addWidget(self.annotation_label)

        # 右侧控制区域
        right_layout = QVBoxLayout()
        # 标注模式
        mode_group = QGroupBox("标注模式")
        mode_layout = QVBoxLayout()
        self.mode_combo = QComboBox()
        self.mode_combo.addItems(["Detect (目标检测)", "Segment (实例分割)", "Classify (图像分类)", "Pose (姿态估计)", "OBB (旋转目标检测)"])
        mode_layout.addWidget(self.mode_combo)
        mode_group.setLayout(mode_layout)
        right_layout.addWidget(mode_group)

        # 类别管理
        class_group = QGroupBox("类别管理")
        class_layout = QVBoxLayout()
        self.class_list = QListWidget()
        self.class_list.addItem("0. person [已选中]")
        self.class_list.addItem("1. bicycle")
        self.class_list.addItem("2. car")
        class_layout.addWidget(self.class_list)
        class_btn_layout = QHBoxLayout()
        self.add_class_btn = QPushButton("添加")
        self.del_class_btn = QPushButton("删除")
        class_btn_layout.addWidget(self.add_class_btn)
        class_btn_layout.addWidget(self.del_class_btn)
        class_layout.addLayout(class_btn_layout)
        class_group.setLayout(class_layout)
        right_layout.addWidget(class_group)

        # 文件列表
        file_group = QGroupBox("文件列表")
        file_layout = QVBoxLayout()
        self.file_list = QListWidget()
        self.file_list.addItem("000000000312.jpg")
        file_layout.addWidget(self.file_list)
        file_group.setLayout(file_layout)
        right_layout.addWidget(file_group)

        layout.addLayout(left_layout)
        layout.addLayout(right_layout)
        return tab

    # 2. 图片采集选项卡
    def create_capture_tab(self):
        tab = QWidget()
        layout = QVBoxLayout(tab)
        label = QLabel("图片采集功能(支持摄像头/视频截图采集)")
        layout.addWidget(label)
        return tab

    # 3. 模型训练选项卡
    def create_train_tab(self):
        tab = QWidget()
        layout = QHBoxLayout(tab)

        # 左侧参数设置
        left_layout = QVBoxLayout()
        # 模型/数据设置
        model_group = QGroupBox("数据/模型")
        model_layout = QFormLayout()
        self.model_path_edit = QLineEdit("yolo26n.pt")
        self.browse_model_btn = QPushButton("浏览")
        self.browse_model_btn.clicked.connect(lambda: self.browse_file(self.model_path_edit, "模型文件 (*.pt)"))
        model_path_layout = QHBoxLayout()
        model_path_layout.addWidget(self.model_path_edit)
        model_path_layout.addWidget(self.browse_model_btn)
        model_layout.addRow("模型路径:", model_path_layout)

        self.data_yaml_edit = QLineEdit("")
        self.browse_data_btn = QPushButton("浏览")
        self.browse_data_btn.clicked.connect(lambda: self.browse_file(self.data_yaml_edit, "数据集配置文件 (*.yaml)"))
        data_path_layout = QHBoxLayout()
        data_path_layout.addWidget(self.data_yaml_edit)
        data_path_layout.addWidget(self.browse_data_btn)
        model_layout.addRow("数据集配置:", data_path_layout)

        self.train_ratio_spin = QSpinBox()
        self.train_ratio_spin.setValue(80)
        model_layout.addRow("训练集比例:", self.train_ratio_spin)
        model_group.setLayout(model_layout)
        left_layout.addWidget(model_group)

        # 训练参数
        param_group = QGroupBox("训练参数")
        param_layout = QFormLayout()
        self.epoch_spin = QSpinBox()
        self.epoch_spin.setValue(200)
        param_layout.addRow("训练轮数:", self.epoch_spin)
        self.batch_spin = QSpinBox()
        self.batch_spin.setValue(8)
        param_layout.addRow("批次大小:", self.batch_spin)
        self.imgsz_spin = QSpinBox()
        self.imgsz_spin.setValue(640)
        param_layout.addRow("图片尺寸:", self.imgsz_spin)
        self.device_spin = QSpinBox()
        self.device_spin.setValue(0)
        param_layout.addRow("设备 (GPU):", self.device_spin)
        self.resume_check = QCheckBox("断点续训")
        param_layout.addRow("", self.resume_check)
        param_group.setLayout(param_layout)
        left_layout.addWidget(param_group)

        # 训练按钮
        self.start_train_btn = QPushButton("开始训练")
        self.start_train_btn.clicked.connect(self.start_train)
        self.stop_train_btn = QPushButton("停止训练")
        left_layout.addWidget(self.start_train_btn)
        left_layout.addWidget(self.stop_train_btn)
        layout.addLayout(left_layout)

        # 右侧日志
        right_layout = QVBoxLayout()
        self.train_log_edit = QTextEdit()
        self.train_log_edit.setReadOnly(True)
        right_layout.addWidget(self.train_log_edit)
        layout.addLayout(right_layout)
        return tab

    # 4. 模型验证/预测选项卡
    def create_validate_tab(self):
        tab = QWidget()
        layout = QHBoxLayout(tab)

        # 左侧参数设置
        left_layout = QVBoxLayout()
        # 模型/输入设置
        model_group = QGroupBox("模型/输入设置")
        model_layout = QFormLayout()
        self.pred_model_edit = QLineEdit("runs/detect/train/weights/best.pt")
        self.browse_pred_model_btn = QPushButton("浏览")
        self.browse_pred_model_btn.clicked.connect(lambda: self.browse_file(self.pred_model_edit, "模型文件 (*.pt)"))
        pred_model_layout = QHBoxLayout()
        pred_model_layout.addWidget(self.pred_model_edit)
        pred_model_layout.addWidget(self.browse_pred_model_btn)
        model_layout.addRow("模型路径:", pred_model_layout)

        self.pred_input_edit = QLineEdit("测试样本/1.jpg")
        self.browse_input_btn = QPushButton("浏览")
        self.browse_input_btn.clicked.connect(lambda: self.browse_file(self.pred_input_edit, "图片/视频文件 (*.jpg *.png *.mp4)"))
        pred_input_layout = QHBoxLayout()
        pred_input_layout.addWidget(self.pred_input_edit)
        pred_input_layout.addWidget(self.browse_input_btn)
        model_layout.addRow("输入源:", pred_input_layout)

        self.conf_spin = QDoubleSpinBox()
        self.conf_spin.setValue(0.25)
        model_layout.addRow("置信度 (Conf):", self.conf_spin)
        self.iou_spin = QDoubleSpinBox()
        self.iou_spin.setValue(0.7)
        model_layout.addRow("NMS (IoU):", self.iou_spin)
        model_group.setLayout(model_layout)
        left_layout.addWidget(model_group)

        self.start_pred_btn = QPushButton("开始预测")
        self.start_pred_btn.clicked.connect(self.start_predict)
        left_layout.addWidget(self.start_pred_btn)
        layout.addLayout(left_layout)

        # 右侧结果显示
        right_layout = QVBoxLayout()
        self.pred_result_label = QLabel("预测结果显示区域")
        self.pred_result_label.setStyleSheet("border: 1px solid black; background-color: #f0f0f0;")
        self.pred_result_label.setMinimumSize(800, 600)
        right_layout.addWidget(self.pred_result_label)
        self.pred_log_edit = QTextEdit()
        self.pred_log_edit.setReadOnly(True)
        right_layout.addWidget(self.pred_log_edit)
        layout.addLayout(right_layout)
        return tab

    # 5. 模型转换选项卡
    def create_export_tab(self):
        tab = QWidget()
        layout = QVBoxLayout(tab)

        # 转换设置
        export_group = QGroupBox("转换设置")
        export_layout = QFormLayout()
        self.export_model_edit = QLineEdit("yolo26n.pt")
        self.browse_export_model_btn = QPushButton("浏览")
        self.browse_export_model_btn.clicked.connect(lambda: self.browse_file(self.export_model_edit, "模型文件 (*.pt)"))
        export_model_layout = QHBoxLayout()
        export_model_layout.addWidget(self.export_model_edit)
        export_model_layout.addWidget(self.browse_export_model_btn)
        export_layout.addRow("模型路径 (.pt):", export_model_layout)

        self.export_format_combo = QComboBox()
        self.export_format_combo.addItems(["onnx", "ncnn", "torchscript", "tensorrt"])
        export_layout.addRow("导出格式:", self.export_format_combo)

        self.export_imgsz_spin = QSpinBox()
        self.export_imgsz_spin.setValue(640)
        export_layout.addRow("Image Size:", self.export_imgsz_spin)
        export_group.setLayout(export_layout)
        layout.addWidget(export_group)

        self.start_export_btn = QPushButton("开始转换")
        self.start_export_btn.clicked.connect(self.start_export)
        layout.addWidget(self.start_export_btn)

        # 转换日志
        self.export_log_edit = QTextEdit()
        self.export_log_edit.setReadOnly(True)
        layout.addWidget(self.export_log_edit)
        return tab

    # 6. 使用说明选项卡
    def create_help_tab(self):
        tab = QWidget()
        layout = QVBoxLayout(tab)
        help_text = QTextEdit()
        help_text.setReadOnly(True)
        help_text.setMarkdown("""
# YOLO全系列可视化标注训练工具
支持:v5/v8/v9/v10/v11/v12/v26
作者:小刀  QQ: 1733617157

---
## 一、数据标注 (Annotation)
1. 标注模式说明
- Detect (目标检测): 绘制矩形框标注目标,适用物体定位、计数
- Segment (实例分割): 点击绘制多边形轮廓,双击完成,适用不规则物体分割
- Classify (图像分类): 点击设置整图类别,自动按类别文件夹组织图片
- Pose (姿态估计): 先画边界框,再标注关键点,支持关键点拖动编辑
- OBB (旋转目标检测): 绘制可旋转的矩形框,适用文字检测、密集物体

2. 全局快捷键(仅在标注画布内有效)
| 快捷键 | 功能说明 |
| :--- | :--- |
| A / D | 上一张 / 下一张图片 |
| W / S | 上一个 / 下一个类别 |
| F | 模板匹配找图(仅Detect模式) |
| 空格 Space | 跳转到第一张未标注图片 |
| Delete | 删除选中的标注(多选时批量删除) |
| Ctrl+S | 手动保存当前标注(换图时自动保存) |
        """)
        layout.addWidget(help_text)
        return tab

    # 通用文件浏览
    def browse_file(self, line_edit, filter):
        path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", filter)
        if path:
            line_edit.setText(path)

    # 开始训练
    def start_train(self):
        model_path = self.model_path_edit.text()
        data_yaml = self.data_yaml_edit.text()
        epochs = self.epoch_spin.value()
        batch = self.batch_spin.value()
        imgsz = self.imgsz_spin.value()
        device = self.device_spin.value()
        resume = self.resume_check.isChecked()

        if not os.path.exists(model_path):
            self.train_log_edit.append("❌ 模型文件不存在!")
            return
        if not os.path.exists(data_yaml):
            self.train_log_edit.append("❌ 数据集配置文件不存在!")
            return

        self.train_thread = TrainThread(model_path, data_yaml, epochs, batch, imgsz, device, resume)
        self.train_thread.log_signal.connect(self.train_log_edit.append)
        self.train_thread.start()

    # 开始预测
    def start_predict(self):
        model_path = self.pred_model_edit.text()
        img_path = self.pred_input_edit.text()
        conf = self.conf_spin.value()
        iou = self.iou_spin.value()

        if not os.path.exists(model_path):
            self.pred_log_edit.append("❌ 模型文件不存在!")
            return
        if not os.path.exists(img_path):
            self.pred_log_edit.append("❌ 输入文件不存在!")
            return

        self.pred_thread = PredictThread(model_path, img_path, conf, iou)
        self.pred_thread.log_signal.connect(self.pred_log_edit.append)
        self.pred_thread.result_signal.connect(self.show_pred_result)
        self.pred_thread.start()

    # 显示预测结果
    def show_pred_result(self, img_np):
        # OpenCV转Qt显示
        img_rgb = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB)
        h, w, c = img_rgb.shape
        bytes_per_line = c * w
        q_img = QImage(img_rgb.data, w, h, bytes_per_line, QImage.Format_RGB888)
        pixmap = QPixmap.fromImage(q_img)
        self.pred_result_label.setPixmap(pixmap.scaled(self.pred_result_label.size(), Qt.KeepAspectRatio))

    # 开始模型转换
    def start_export(self):
        model_path = self.export_model_edit.text()
        format = self.export_format_combo.currentText()
        imgsz = self.export_imgsz_spin.value()

        if not os.path.exists(model_path):
            self.export_log_edit.append("❌ 模型文件不存在!")
            return

        self.export_thread = ExportThread(model_path, format, imgsz)
        self.export_thread.log_signal.connect(self.export_log_edit.append)
        self.export_thread.start()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = YoloToolWindow()
    window.show()
    sys.exit(app.exec_())

工具部署说明

  1. 环境依赖
    pip install ultralytics opencv-python pyqt5 numpy
    
  2. 运行方式
    • 安装依赖后,直接运行上述Python脚本即可启动工具
    • 如需打包为exe文件,可使用pyinstaller命令:
      pyinstaller -F -w --add-data "ultralytics;ultralytics" yolo_tool.py
      
  3. 使用流程
    1. 数据标注:导入图片,使用自动标注/手动标注完成数据集标注
    2. 生成数据集:工具自动生成YOLO格式的训练配置文件(yaml)
    3. 模型训练:选择预训练模型,设置训练参数,开始训练
    4. 模型预测:加载训练后的模型,测试检测效果
    5. 模型转换:导出ONNX/NCNN格式模型,用于各类自动化脚本调用

工具适配说明

导出的ONNX/NCNN模型,可直接在以下场景调用:

  • 懒人精灵:通过内置的模型加载接口调用ONNX模型
  • 按键精灵:使用第三方插件加载NCNN/ONNX模型
  • AutoGO:通过Lua脚本调用NCNN模型
  • 其他Lua自动化框架:支持NCNN/ONNX格式模型的通用调用方式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值