自定义数据集labelimg标定并yolo v11使用训练

自定义数据集labelimg标定并yolo v11使用训练

labelimg标定数据集

安装

  1. 使用conda进行labelimg安装
    conda create -n labelimg python=3.8
  2. 这里创建完之后进入labelimg环境
    conda activate labelimg
  3. 进入labelimg环境之后通过pip下载labelimg
    pip install labelimg
  4. conda环境中输入labelimg进入软件

使用

  1. 创建两个文件夹,images是存放图片的位置,labels是存放图片对应的标签。
  2. 打开数据集文件夹以及labels文件夹 ,点击Open dir选择我们训练图片所在的文件夹images,选择之后会弹窗让你选择labels所在的文件夹。labels文件夹需要自己建立,目的是用来存储图片标注后的信息。
  3. labelImg生成的标签放在labels文件夹下。生成的标签文件格式:class x_center y_center width height 。每行表示一个目标对象,每行中的第一个数表示目标类别,计数从0开始,比如这里的0代表的类别。后面的4个值代表目标真实框中心点(x,y)和真实框的宽、高信息。
  4. 编辑数据集配置文件***.yaml。注意 label不用配置:train.py在训练过程中,会将路径中的images替换为 labels来寻找labels数据
#train是训练时加载的图片或者标签的路径
train: images/train
#val是验证时加载的图片或者标签的路径
val: images/train
#test是测试时加载的图片或者标签的路径
test: images/test
# 类别数
nc: 2
# 类别名称
names: ['buffalo','lion']

生成标注后图片

这个脚本会读取标签文件中的矩形框信息,将其绘制在对应的原图上,并将结果保存到指定的输出文件夹中。不同类别的矩形框和类别名称将使用不同的颜色。

import os
import cv2

# 文件夹路径
images_folder = "./data_lableimg/JPEGImages"
labels_folder = "./data_lableimg/labels"
output_folder = "./data_lableimg/output_images"
classes_file = "./data_lableimg/classes.txt"

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

# 读取类别名称
with open(classes_file, "r") as f:
    class_names = f.read().strip().split()

# 定义颜色列表(每个类别对应一种颜色)
colors = [
    (255, 0, 0),    # 红色
    (0, 255, 0),    # 绿色
    (0, 0, 255),    # 蓝色
    (255, 255, 0),  # 青色
    (255, 0, 255),  # 洋红
    (0, 255, 255),  # 黄色
    (128, 0, 0),    # 深红
    (0, 128, 0),    # 深绿
    (0, 0, 128),    # 深蓝
    # 可以根据需要添加更多颜色
]

# 遍历标签文件夹中的所有文件
for label_file in os.listdir(labels_folder):
    # 构建标签文件路径
    label_path = os.path.join(labels_folder, label_file)
    
    # 构建对应的图像文件路径
    image_file = label_file.replace(".txt", ".jpg")
    image_path = os.path.join(images_folder, image_file)
    
    # 检查图像文件是否存在
    if not os.path.exists(image_path):
        print(f"Image file '{image_file}' not found, skipping.")
        continue
    
    # 读取图像
    image = cv2.imread(image_path)
    
    # 检查图像是否成功读取
    if image is None:
        print(f"Failed to read image '{image_file}', skipping.")
        continue
    
    height, width, _ = image.shape
    
    # 读取标签文件
    with open(label_path, "r") as f:
        for line in f.readlines():
            # 解析标签文件中的每一行
            class_id, x_center, y_center, bbox_width, bbox_height = map(float, line.strip().split())
            
            # 转换坐标
            x_center *= width
            y_center *= height
            bbox_width *= width
            bbox_height *= height
            
            # 计算矩形框的左上角和右下角坐标
            x1 = int(x_center - bbox_width / 2)
            y1 = int(y_center - bbox_height / 2)
            x2 = int(x_center + bbox_width / 2)
            y2 = int(y_center + bbox_height / 2)
            
            # 获取类别对应的颜色
            color = colors[int(class_id) % len(colors)]
            
            # 绘制矩形框
            cv2.rectangle(image, (x1, y1), (x2, y2), color, 2)
            
            # 绘制类别名称
            class_name = class_names[int(class_id)]
            cv2.putText(image, class_name, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color, 2)
    
    # 保存带有矩形框的图像
    output_path = os.path.join(output_folder, image_file)
    cv2.imwrite(output_path, image)
    print(f"Saved '{output_path}'")

print("All images processed.")

yolo 训练

yolo安装

先进入自己带pytorch的虚拟环境,与之前的yolo系列安装都不太一样,yolov8仅需要安装ultralytics这一个库。
pip install ultralytics
测试yolo v11模型

from ultralytics import YOLO

# Load a model
model = YOLO("yolo11n.yaml")  # build a new model from YAML
model = YOLO("yolo11n.pt")  # load a pretrained model (recommended for training)
model = YOLO("yolo11n.yaml").load("yolo11n.pt")  # build from YAML and transfer weights

# Train the model. Device is determined automatically. If a GPU is available then it will be used, otherwise training will start on CPU.
results = model.train(data="coco8.yaml", epochs=100, imgsz=640)
# Train the model with 2 GPUs
results = model.train(data="coco8.yaml", epochs=100, imgsz=640, device=[0, 1])
# Train the model with MPS
results = model.train(data="coco8.yaml", epochs=100, imgsz=640, device="mps")

按比例划分数据集

# 作者:CSDN-笑脸惹桃花 https://blog.csdn.net/qq_67105081?type=blog
# github:peng-xiaobai https://github.com/peng-xiaobai/Dataset-Conversion
import os
import shutil
import random
 
# random.seed(0)  #随机种子,可自选开启
def split_data(file_path, label_path, new_file_path, train_rate, val_rate, test_rate):
	images = os.listdir(file_path)
	labels = os.listdir(label_path)
	images_no_ext = {os.path.splitext(image)[0]: image for image in images}
	labels_no_ext = {os.path.splitext(label)[0]: label for label in labels}
	matched_data = [(img, images_no_ext[img], labels_no_ext[img]) for img in images_no_ext if img in labels_no_ext]
 
	unmatched_images = [img for img in images_no_ext if img not in labels_no_ext]
	unmatched_labels = [label for label in labels_no_ext if label not in images_no_ext]
	if unmatched_images:
		print("未匹配的图片文件:")
		for img in unmatched_images:
			print(images_no_ext[img])
	if unmatched_labels:
		print("未匹配的标签文件:")
		for label in unmatched_labels:
			print(labels_no_ext[label])
 
	random.shuffle(matched_data)
	total = len(matched_data)
	train_data = matched_data[:int(train_rate * total)]
	val_data = matched_data[int(train_rate * total):int((train_rate + val_rate) * total)]
	test_data = matched_data[int((train_rate + val_rate) * total):]
 
	# 处理训练集
	for img_name, img_file, label_file in train_data:
		old_img_path = os.path.join(file_path, img_file)
		old_label_path = os.path.join(label_path, label_file)
		new_img_dir = os.path.join(new_file_path, 'train', 'images')
		new_label_dir = os.path.join(new_file_path, 'train', 'labels')
		os.makedirs(new_img_dir, exist_ok=True)
		os.makedirs(new_label_dir, exist_ok=True)
		shutil.copy(old_img_path, os.path.join(new_img_dir, img_file))
		shutil.copy(old_label_path, os.path.join(new_label_dir, label_file))
	# 处理验证集
	for img_name, img_file, label_file in val_data:
		old_img_path = os.path.join(file_path, img_file)
		old_label_path = os.path.join(label_path, label_file)
		new_img_dir = os.path.join(new_file_path, 'val', 'images')
		new_label_dir = os.path.join(new_file_path, 'val', 'labels')
		os.makedirs(new_img_dir, exist_ok=True)
		os.makedirs(new_label_dir, exist_ok=True)
		shutil.copy(old_img_path, os.path.join(new_img_dir, img_file))
		shutil.copy(old_label_path, os.path.join(new_label_dir, label_file))
	# 处理测试集
	for img_name, img_file, label_file in test_data:
		old_img_path = os.path.join(file_path, img_file)
		old_label_path = os.path.join(label_path, label_file)
		new_img_dir = os.path.join(new_file_path, 'test', 'images')
		new_label_dir = os.path.join(new_file_path, 'test', 'labels')
		os.makedirs(new_img_dir, exist_ok=True)
		os.makedirs(new_label_dir, exist_ok=True)
		shutil.copy(old_img_path, os.path.join(new_img_dir, img_file))
		shutil.copy(old_label_path, os.path.join(new_label_dir, label_file))
	print("数据集已划分完成")
 
if __name__ == '__main__':
	file_path = "./data_lableimg/JPEGImages"  # 图片文件夹
	label_path = './data_lableimg/labels'  # 标签文件夹
	new_file_path = "./datayolo"  # 新数据存放位置
	split_data(file_path, label_path, new_file_path, train_rate=0.8, val_rate=0.1, test_rate=0.1)

yolo使用

开始训练

from ultralytics import YOLO
pt_file = "yolo11n.pt"
model = YOLO("yolo11n.yaml").load(pt_file)  # build from YAML and transfer weights
# Train the model
results = model.train(data="data.yaml", epochs=100, imgsz=640, device="mps")

恢复训练

通过设置resume=True, train函数将使用存储在‘path/to/last.pt’文件中的状态,从它停止的地方继续训练。如果省略resume参数或将其设置为False,则train函数将开始新的训练会话。

from ultralytics import YOLO

# Load a model
model = YOLO("path/to/last.pt")  # load a partially trained model

# Resume training
results = model.train(resume=True)

参数设置

# Train the model
results = model.train(
    data=data_file,  # 数据集配置文件
    epochs=100,      # 训练周期数
    imgsz=640,       # 输入图像大小
    device="mps",    # 训练设备(例如 "cpu", "cuda", "mps")
    batch=16,        # 批处理大小
    workers=8,       # 数据加载器的工作线程数
    project="runs/train",  # 训练结果保存目录
    name="exp",      # 训练结果保存子目录名称
    exist_ok=False,  # 如果为 True,则允许覆盖现有目录
    pretrained=True, # 如果为 True,则使用预训练模型
    optimizer="SGD", # 优化器类型(例如 "SGD", "Adam")
    lr0=0.01,        # 初始学习率
    lrf=0.1,         # 最终学习率
    momentum=0.937,  # SGD 动量
    weight_decay=0.0005,  # 权重衰减
    warmup_epochs=3.0,    # 学习率预热周期数
    warmup_momentum=0.8,  # 预热动量
    warmup_bias_lr=0.1,   # 预热偏置学习率
    box=0.05,        # 边界框损失系数
    cls=0.5,         # 分类损失系数
    cls_pw=1.0,      # 分类损失权重
    obj=1.0,         # 目标损失系数
    obj_pw=1.0,      # 目标损失权重
    iou_t=0.2,       # IoU 阈值
    anchor_t=4.0,    # 锚框阈值
    fl_gamma=0.0,    # Focal Loss gamma
    hsv_h=0.015,     # HSV 色调增强
    hsv_s=0.7,       # HSV 饱和度增强
    hsv_v=0.4,       # HSV 亮度增强
    degrees=0.0,     # 图像旋转角度
    translate=0.1,   # 图像平移
    scale=0.5,       # 图像缩放
    shear=0.0,       # 图像剪切
    perspective=0.0, # 透视变换
    flipud=0.0,      # 上下翻转
    fliplr=0.5,      # 左右翻转
    mosaic=1.0,      # 马赛克数据增强
    mixup=0.0,       # MixUp 数据增强
    copy_paste=0.0,  # Copy-Paste 数据增强
)

查看训练过程

新开一个终端窗口,输入tensorboard --logdir runs/detect/train,进入tensorboard观察训练过程。浏览器打开http://localhost:6006/

YOLOv11(Ultralytics)可视化界面ui设计

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

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
 
class Worker:
    def __init__(self):
        self.model = None
        self.current_annotated_image = None
        self.detection_type = None
 
    def load_model(self):
        model_path, _ = QFileDialog.getOpenFileName(None, "选择模型文件", "", "模型文件 (*.pt)")
        if model_path:
            self.model = YOLO(model_path)
            if self.model:
                return True
            else:
                return False
 
    def detect_objects(self, frame):
        det_info = []
        class_ids = frame[0].boxes.cls
        class_names_dict = frame[0].names
        for class_id in class_ids:
            class_name = class_names_dict[int(class_id)]
            det_info.append(class_name)
        return det_info
 
    def 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;')  # 添加边框并设置背景颜色为黑色
 
        # 水平布局,用于放置左右两个 QLabel
        layout = 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_type
        if detection_type == "image":
            self.save_detection_results()
 
    def select_image(self):
        image_path, _ = QFileDialog.getOpenFileName(None, "选择图片文件", "", "图片文件 (*.jpg *.jpeg *.png)")
        self.flag = 0
        if image_path:
            self.detect_image(image_path)
 
    def detect_folder(self):
        folder_path = QFileDialog.getExistingDirectory(self, "选择图片文件夹")
        self.flag = 1
        if 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 = results
                    self.worker.current_annotated_image = results[0].plot()
                    annotated_image = self.worker.current_annotated_image
                    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
                    height1, width1, channel1 = image_rgb.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.KeepAspectRatio))
                    annotated_image = cv2.cvtColor(annotated_image, cv2.COLOR_BGR2RGB)
                    height2, width2, channel2 = annotated_image.shape
                    bytesPerLine2 = 3 * width2
                    qimage2 = 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_results
        if 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] += 1
                    else:
                        object_dict[obj] = 1
                sorted_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_())

参考: 笑脸惹桃花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值