深度学习Y7周:YOLOv8训练自己数据集

发布于:2025-05-09 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、配置环境

1.官网下载源码

2.安装需要环境

二、准备好自己的数据

目录结构:

·主目录

        ·data

                ·images(存放图片)

                ·annotations(放置.xml文件)

                ·imagesets

                        ·main(会在该文件夹内自动生成train.txt、val.txt、test.txt、trainval.txt文件,  存放训练集、验证集、测试集图片的名字)

                ·split_train_val.py(划分训练集、验证集与测试集)

                ·voc_label.py(获取划分训练集、验证集与测试集路径)

                ·ab.yaml(数据集及数据类别声明文件)

        ·trainByK.py(代码运行文件)

1.运行split_train_val.py文件

文件代码:

import os,random,argparse

parser=argparse.ArgumentParser()

# 添加命令行参数,用于指定XML文件的路径,默认为‘Annotation'文件夹
parser.add_argument('--xml_path',default='Annotations',type=str,help='input xml label path')

#添加命令行参数,用于指定输出txt标签文件的路径,默认为'ImageSets/Main'文件
parser.add_argument('--txt_path',default='ImageSets/Main',type=str,help='output txt label path')

#解析命令行参数
opt=parser.parse_args()

#定义训练验证集和测试集的划分比例
trainval_percent=1.0  # 使用全部数据
train_percent=0.9  # 训练集占训练验证集的90%

# 设置XML文件夹的路径,根据命令行参数指定
xmlfilepath=opt.xml_path

# 设置输出txt标签文件的路径,根据命令行参数指定
txtsavepath=opt.txt_path

# 获取XML文件夹中的所有XML文件列表
total_xml=os.listdir(xmlfilepath)

# 如果输出txt标签文件的文件夹不存在,创建它
if not os.path.exists(txtsavepath):
    os.makedirs(txtsavepath)

# 获取XML文件的总数
num=len(total_xml)

# 创建一个包含所有XML文件索引的列表
list_index=range(num)

# 计算训练验证集的数量
tv=int(num*trainval_percent)

# 计算训练集的数量
tr=int(tv*train_percent)

# 从所有XML文件索引中随机选择出训练验证集的索引
trainval=random.sample(list_index,tv)

# 从训练验证集的索引中随机选择出训练集的索引
train=random.sample(trainval,tr)

# 打开要写入的训练验证集、测试集、训练集、验证集的txt文件
file_trainval=open(txtsavepath+'/trainval.txt','w')
file_test=open(txtsavepath+'/test.txt','w')
file_train=open(txtsavepath+'/train.txt','w')
file_val=open(txtsavepath+'/val.txt','w')

#遍历所有XML文件的索引
for i in list_index:
    name = total_xml[i][:-4] + '\n'  #获取XML文件的名称(去掉后缀.xml),并添加换行符

    #如果该索引在训练验证集中
    if i in trainval:
        file_trainval.write(name) #写入训练验证集txt文件
        if i in train:
            file_train.write(name)
        else:
            file_val.write(name)
    else:
        file_test.write(name)


file_trainval.close()
file_train.close()
file_val.close()
file_test.close()

运行后得到四个文件:

注:如何修改数据集中训练集、验证集、测试集的比例?

2.运行voc_label.py文件(将label格式转换为VOC格式)

文件代码:

#-*- coding:utf-8 -*-

import xml.etree.ElementTree as ET
import os
from os import getcwd

#定义数据集的名称
sets =['train','val','test']

#请根据您的数据集修改这些类别名称
# classes =['Banana','Snake fruit','Dragon fruit','Pineapple']
classes = ["banana","snake fruit","dragon fruit","pineapple"]

#获取当前工作目录的绝对路径
abs_path = os.getcwd()
print(abs_path)

#定义一个函数,将边界框的坐标从绝对值转换为相对于图像大小的比例
def convert(size,box):
    dw = 1./(size[0])     #计算图像宽度的倒数
    dh = 1./(size[1])     #计算图像高度的倒数
    x = (box[0]+box[1])/2.0-1     #计算中心点的x坐标
    y = (box[2]+box[3])/2.0-1     # 计算中心点的y坐标
    w= box[1]- box[0]           # 计算边界框的宽度
    h = box[3] - box[2]         # 计算边界框的高度
    x = x * dw  # 缩放x坐标
    w = w * dw  # 缩放宽度
    y = y * dh  # 缩放y坐标
    h=h*dh      #缩放高度
    return x, y, w, h

# 定义一个函数,将标注文件从XML格式转换为YOLO格式
def convert_annotation(image_id):
    in_file = open('./Annotations/%s.xml' % (image_id),encoding='UTF-8')  # 打开XML标注文件
    out_file = open('./labels/%s.txt'%(image_id),'w')   # 打开要写入的YOL0格式标签文件
    tree =ET.parse(in_file)     #解析XML文件
    root = tree.getroot()

    filename = root.find('filename').text  # 获取图像文件名
    filenameFormat=filename.split(".")[1]  # 获取文件格式

    size = root.find('size')  # 获取图像尺寸信息
    w= int(size.find('width').text)  # 获取图像宽度
    h=int(size.find('height').text)  #获取图像高度
    for obj in root.iter('object'):
        difficult = obj.find('difficult').text  # 获取对象的难度标志
        cls= obj.find('name').text #获取对象的类别名称
        if cls not in classes or int(difficult)== 1:
            continue
        cls_id = classes.index(cls)    # 获取类别的索引
        xmlbox = obj.find('bndbox')    # 获取边界框坐标信息
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text))
        b1,b2,b3,b4 = b
        # 标注越界修正
        if b2 > w:
            b2 = w
        if b4 > h:
            b4 = h
        b=(b1,b2,b3,b4)
        bb=convert((w,h),b)     #调用convert函数,将边界框坐标转换为Y0OLO格式
        out_file.write(str(cls_id)+" "+" ".join([str(a) for a in bb])+'\n')     #写入YOLO格式标签文件

    return filenameFormat

#获取当前工作目录
wd = getcwd()

#遍历每个数据集(train、val、test)
for image_set in sets:
    #如果labels目录不存在,创建它
    if not os.path.exists('./labels/'):
        os.makedirs('./labels/')
    #从数据集文件中获取图像ID列表
    image_ids = open('./ImageSets/Main/%s.txt'%(image_set)).read().strip().split()
    #打开要写入的文件,写入图像的文件路径和格式
    list_file =open('./%s.txt'%(image_set),'w')
    for image_id in image_ids:
        filenameFormat=convert_annotation(image_id)
        list_file.write(abs_path +'/images/%s.%s\n'%(image_id,filenameFormat)) #注意你的图片格式,如果是.jpg记得修改
    list_file.close()

运行voc_label.py,获得三个文件

3.创建ab.yaml文件

train:D:\learn\data\train.txt  #绝对路径
val:D:\learn\data\val.txt    #绝对路径

nc: 4    # number of classes

names: ["banana", "snake fruit", "dragon fruit", "pineapple"]

三、开始用自己数据集训练模型

自建train.py文件运行

from ultralytics import YOLO

if __name__ == '__main__':
    model = YOLO("yolov8s.pt")

    model.train(data=r"D:\learn\ultralytics-main\data\ab.yaml",
                seed=0,
                epoches=10,
                batch=4,
                workes=2)

修改了很久,可能环境方面出了问题,依旧连接不到我的数据文件夹里。

四、训练参数设置(defalult.yaml)

# Ultralytics YOLO 🚀, AGPL-3.0 许可证,由K同学啊注解
# 默认的训练设置和超参数,用于中度增强 COCO 训练

task: detect  # (str) YOLO 任务,例如 detect、segment、classify、pose
mode: train   # (str) YOLO 模式,例如 train、val、predict、export、track、benchmark

# 训练设置 -------------------------------------------------------------------------------------------------------
model:  # (str, 可选) 模型文件路径,例如 yolov8n.pt、yolov8n.yaml
data:   #./paper_data/ab.yaml # (str, 可选) 数据文件路径,例如 coco128.yaml

epochs: 100   # (int) 训练的轮次数
patience: 50  # (int) 提前停止训练的等待周期数,如果没有明显的改进
batch: 1      # (int) 每批处理的图像数量(-1 表示自动批处理)
imgsz: 640    # (int | list) 输入图像的大小,以像素为单位,用于训练和验证模式,或以列表[w,h]形式用于预测和导出模式
save: True    # (bool) 保存训练检查点和预测结果
save_period: -1  # (int) 每隔 x 个周期保存一个检查点(如果 < 1 则禁用)
cache: False     # (bool) 使用缓存加载数据(True/ram、disk 或 False)
device: 0          # (int | str | list, 可选) 运行模型的设备,例如 cuda device=0 或 device=0,1,2,3 或 device=cpu
workers: 4       # (int) 数据加载的工作线程数(每个 DDP 会有一个)
project:         # (str, 可选) 项目名称
name:            # (str, 可选) 实验名称,结果保存在 'project/name' 目录下
exist_ok: False  # (bool) 是否覆盖现有的实验
pretrained: True # (bool | str) 是否使用预训练模型(True 或加载权重的模型路径字符串)
optimizer: auto  # (str) 优化器选择,选项=[SGD、Adam、Adamax、AdamW、NAdam、RAdam、RMSProp、auto]
verbose: True    # (bool) 是否打印详细输出
seed: 0          # (int) 随机种子,用于可重复性
deterministic: True  # (bool) 是否启用确定性模式
single_cls: False    # (bool) 是否将多类数据训练为单一类别
rect: False          # (bool) 如果模式='train',则进行矩形训练;如果模式='val',则进行矩形验证
cos_lr: False        # (bool) 是否使用余弦学习率调度器
close_mosaic: 10     # (int) 在最后几个周期内禁用马赛克增强(0 表示禁用)
resume: False   # (bool) 是否从上次检查点恢复训练
amp: True       # (bool) 是否启用自动混合精度(AMP)训练,选项=[True, False],True 表示运行 AMP 检查
fraction: 1.0   # (float) 训练集数据分数(默认为 1.0,使用训练集中的所有图像)
profile: False  # (bool) 在训练期间记录 ONNX 和 TensorRT 速度以供记录器使用
freeze: None    # (int | list, 可选) 冻结前 n 层,或在训练期间冻结的层索引列表
# 分割
overlap_mask: True  # (bool) 训练期间是否允许蒙版重叠(仅适用于分割训练)
mask_ratio: 4       # (int) 蒙版下采样比率(仅适用于分割训练)
# 分类
dropout: 0.0  # (float) 是否使用 dropout 正则化(仅适用于分类训练)

# 验证/测试设置 ----------------------------------------------------------------------------------------------------
val: True   # (bool) 训练期间是否进行验证/测试
split: val  # (str) 用于验证的数据集分割,例如 'val'、'test' 或 'train'
save_json: False    # (bool) 是否将结果保存为 JSON 文件
save_hybrid: False  # (bool) 是否保存标签的混合版本(标签 + 额外的预测)
conf:     # (float, 可选) 用于检测的对象置信度阈值(默认 0.25 用于预测,0.001 用于验证)
iou: 0.7  # (float) NMS 的交并比(IoU)阈值
max_det: 300  # (int) 每张图像的最大检测数
half: False   # (bool) 是否使用半精度(FP16)
dnn: False    # (bool) 是否使用 OpenCV DNN 进行 ONNX 推理
plots: True   # (bool) 在训练/验证期间保存图形

# 预测设置 --------------------------------------------------------------------------------------------------
source:           # (str, 可选) 图像或视频的源目录
show: False       # (bool) 如果可能的话是否显示结果
save_txt: False   # (bool) 是否将结果保存为 .txt 文件
save_conf: False  # (bool) 是否保存带有置信度分数的结果
save_crop: False  # (bool) 是否保存裁剪后的带有结果的图像
show_labels: True # (bool) 是否在图形中显示对象标签
show_conf: True   # (bool) 是否在图形中显示对象置信度分数
vid_stride: 1     # (int) 视频帧率跨度
stream_buffer: False  # (bool) 是否缓存所有流式帧(True)或返回最新的帧(False)
line_width:       # (int, 可选) 边界框的线宽,如果缺失则自动设置
visualize: False  # (bool) 是否可视化模型特征
augment: False    # (bool) 是否对预测源应用图像增强
agnostic_nms: False  # (bool) 是否进行类别无关的 NMS
classes:             # (int | list[int], 可选) 按类别筛选结果,例如 classes=0,或 classes=[0,2,3]
retina_masks: False  # (bool) 是否使用高分辨率分割蒙版
boxes: True          # (bool) 在分割预测中显示边界框

# 导出设置 ------------------------------------------------------------------------------------------------------
format: torchscript  # (str) 导出格式,可选项请查看 https://docs.ultralytics.com/modes/export/#export-formats
keras: False         # (bool) 是否使用 Kera=s
optimize: False      # (bool) TorchScript:优化为移动设备
int8: False       # (bool) CoreML/TF INT8 量化
dynamic: False    # (bool) ONNX/TF/TensorRT:动态轴
simplify: False   # (bool) ONNX:简化模型
opset:            # (int, 可选) ONNX:opset 版本
workspace: 4      # (int) TensorRT:工作空间大小(GB)
nms: False        # (bool) CoreML:添加 NMS

# 超参数 ------------------------------------------------------------------------------------------------------
lr0: 0.01             # (float) 初始学习率(例如,SGD=1E-2,Adam=1E-3)
lrf: 0.01             # (float) 最终学习率(lr0 * lrf)
momentum: 0.937       # (float) SGD 动量/Adam beta1
weight_decay: 0.0005  # (float) 优化器权重衰减 5e-4
warmup_epochs: 3.0    # (float) 预热周期数(分数也可以)
warmup_momentum: 0.8  # (float) 预热初始动量
warmup_bias_lr: 0.1   # (float) 预热初始偏置 lr
box: 7.5     # (float) 目标框损失增益
cls: 0.5     # (float) 类别损失增益(与像素一起缩放)
dfl: 1.5     # (float) DFL 损失增益
pose: 12.0   # (float) 姿势损失增益
kobj: 1.0    # (float) 关键点 obj 损失增益
label_smoothing: 0.0  # (float) 标签平滑化(分数)
nbs: 64               # (int) 名义批次大小
hsv_h: 0.015          # (float) 图像 HSV-Hue 增强(分数)
hsv_s: 0.7      # (float) 图像 HSV-Saturation 增强(分数)
hsv_v: 0.4      # (float) 图像 HSV-Value 增强(分数)
degrees: 0.0    # (float) 图像旋转(+/- 度)
translate: 0.1  # (float) 图像平移(+/- 分数)
scale: 0.5      # (float) 图像缩放(+/- 增益)
shear: 0.0      # (float) 图像剪切(+/- 度)
perspective: 0.0  # (float) 图像透视变换(+/- 分数),范围 0-0.001
flipud: 0.0       # (float) 图像上下翻转(概率)
fliplr: 0.5       # (float) 图像左右翻转(概率)
mosaic: 1.0       # (float) 图像马赛克增强(概率)
mixup: 0.0        # (float) 图像混合增强(概率)
copy_paste: 0.0   # (float) 段复制粘贴(概率)

# 自定义 config.yaml ---------------------------------------------------------------------------------------------------
cfg:  # (str, 可选) 用于覆盖默认.yaml 的自定义配置

# 跟踪器设置 ------------------------------------------------------------------------------------------------------
tracker: botsort.yaml  # (str) 跟踪器类型,选项=[botsort.yaml, bytetrack.yaml]

五、总结

阅读代码能力比之前强了,但是还是缺少连接所有知识的能力。有的时候总会忘记之前出现问题的解决办法,导致实验无法进行。 


网站公告

今日签到

点亮在社区的每一天
去签到