yolov5搭建、训练模型、使用模型

一、前言

这里简单介绍一下yolov是什么东西,yolov 是高效的单阶段目标检测算法系列,经多版本迭代优化,可快速精准识别图像或视频中目标的类别与位置,广泛用于安防监控、自动驾驶、工业质检、智能零售等领域。那这里为什么选择yolov5,yolov5在性能和准确性之间取得了很好的平衡,yolov5用于学习计算机图像识别还是很好上手的。接下来介绍yolov5搭建、训练模型、使用模型的操作,后续文章将使用训练好的模型进行游戏的自动化实战,以及GPU云服务器训练yolov5模型的教程,请持续关注。废话不多说,开始操作教程。

二、环境搭建

获取yolov5项目代码

git clone https://github.com/ultralytics/yolov5.git

安装项目依赖

pip install -r requirements.txt

三、训练模型

3.1 yolov5 目录文件讲解

在这里插入图片描述

# 重点使用到这些文件与目录,其余兴趣可以自行研究
data        ---   训练数据集配置文件
models			---		模型文件
datasets    ---   训练的数据集文件(该目录自己创建)
train.py    ---   训练生成自己的模型
detect.py   ---   使用模型进行测试
export.py   ---   将训练好的模型转换为ONNX格式
3.2 模型训练
3.2.1 放入自己要训练的数据集

不明白怎么创建数据集看➡️labelimg图片标注工具详解⬅️这一篇文章。使用 labelimg进行图片标注后,会自动生成yolov格式的标注文件,再网上搜索数据集自动分割训练集和验证集脚本,跑一下数据集的文件就可以拿去用了。
在这里插入图片描述

脚本也是网上找的,出处忘了,感谢作者的无私奉献。

import os
import random

from shutil import copy2

#如需更改训练集、验证集和测试集比例在此修改
def data_set_split(src_images_folder, src_labels_folder, target_data_folder, train_scale=0.9, val_scale=0.1, test_scale=0.1):
    '''
    读取源数据文件夹,生成划分好的文件夹,分为trian、val、test三个文件夹进行
    :param src_images_folder: 总图片目录
    :param src_labels_folder: 总标签目录
    :param target_data_folder: 存放划分数据集文件夹
    :param train_scale: 训练集比例
    :param val_scale: 验证集比例
    :param test_scale: 测试集比例
    :return:
    '''
    print("开始数据集划分")
    # 在目标目录下创建文件夹
    split_names = ['train', 'val', 'test']
    for split_name in split_names:
        split_path = os.path.join(target_data_folder, split_name)
        split_images_path = os.path.join(split_path, 'images')
        split_labels_path = os.path.join(split_path, 'labels')
        if os.path.isdir(split_path):
            pass
        else:
            os.mkdir(split_path)
        if os.path.isdir(split_images_path):
            pass
        else:
            os.mkdir(split_images_path)
        if os.path.isdir(split_labels_path):
            pass
        else:
            os.mkdir(split_labels_path)

    # 按照比例划分数据集,并进行数据图片的复制
    # 首先进行分类遍历
    current_all_images = os.listdir(src_images_folder)
    current_images_length = len(current_all_images)
    current_images_index_list = list(range(current_images_length))
    random.shuffle(current_images_index_list)

    #存放train、val、test中image和labels的路径
    train_images_folder = os.path.join(target_data_folder, 'train/images')
    val_images_folder = os.path.join(target_data_folder, 'val/images')
    test_images_folder = os.path.join(target_data_folder, 'test/images')
    train_labels_folder = os.path.join(target_data_folder, 'train/labels')
    val_labels_folder = os.path.join(target_data_folder, 'val/labels')
    test_labels_folder = os.path.join(target_data_folder, 'test/labels')
    train_stop_flag = current_images_length * train_scale
    val_stop_flag = current_images_length * (train_scale + val_scale)

    current_idx = 0
    train_num = 0
    val_num = 0
    test_num = 0

    for i in current_images_index_list:
        src_img_path = os.path.join(src_images_folder, current_all_images[i])
        # 如果图片格式不是jpg,更换则可
        src_labels_path = os.path.join(src_labels_folder, current_all_images[i].replace('jpg','txt'))
        if current_idx <= train_stop_flag:
            copy2(src_img_path, train_images_folder)
            if os.path.isdir(split_path):# 防止有些图片没有label
                try:
                    copy2(src_labels_path, train_labels_folder)
                except Exception as e:
                    print("手动",e)
                    continue
            else:
                print("缺少图片{}的label".format(current_all_images[i]))
            train_num = train_num + 1
        elif (current_idx > train_stop_flag) and (current_idx <= val_stop_flag):
            copy2(src_img_path, val_images_folder)
            if os.path.isdir(split_path):
                copy2(src_labels_path, val_labels_folder)
            else:
                print("缺少图片{}的label".format(current_all_images[i]))
            val_num = val_num + 1
        else:
            copy2(src_img_path, test_images_folder)
            if os.path.isdir(split_path):
                copy2(src_labels_path, test_labels_folder)
            else:
                print("缺少图片{}的label".format(current_all_images[i]))
            test_num = test_num + 1

        current_idx = current_idx + 1
    print("按照{}:{}:{}的比例划分完成,一共{}张图片".format( train_scale, val_scale, test_scale, current_images_length))
    print("训练集{}:{}张".format(train_images_folder, train_num))
    print("验证集{}:{}张".format(val_images_folder, val_num))
    print("测试集{}:{}张".format(test_images_folder, test_num))


if __name__ == '__main__':
    src_images_folder = "/Users/xxx/Documents/dnf/jpg_data/yolov5/datasets/images" # 图片地址
    src_labels_folder = "/Users/xxx/Documents/dnf/jpg_data/yolov5/datasets/labels"  # 标签地址
    target_data_folder = "/Users/xx/Documents/dnf/jpg_data/yolov5/datasets" #
    data_set_split(src_images_folder,src_labels_folder, target_data_folder)

分割好训练集、验证集和测试集就可以放到datasets目录下,放到其他目录下也是可以的,问题不大,主要用于训练数据集配置文件的路径引用。

在这里插入图片描述

3.2.2 修改训练配置文件
YOLOv5使用train, val, test三个文件夹来存储训练、验证和测试数据集。
训练数据集 (train):包含用于训练模型的图像。
验证数据集 (val):包含用于在训练过程中验证模型性能的图像。
测试数据集 (test):包含用于最终测试模型性能的图像。

nc: 标注有多少种类就填多少。
names: 标注的类别名称有哪些都放入到names list里

在这里插入图片描述

3.2.3 运行训练模型脚本

方法1:

执行train.py 指定参数,

train.py --cfg models/yolov5n.yaml --data models/data.yaml --device cpu

参数解析:

--cfg 模型推理解析的配置文件,配置文件对应不同规模的 YOLOv5 模型,通常以 n(nano)、s(small)、m(medium)、l(large)、x(extra - large) 命名,规模依次增大。要了解具体区别可网上搜索查看。
--data 训练数据集的配置文件
--device 使用cpu还是gpu,作者电脑没有独显卡,所以用cpu训练

方法2:

修改train.py parser.add_argument里的default默认参数,然后运行(我这里就只改了,–cfg、–data、–device),个人比较喜欢使用方法2。

parser = argparse.ArgumentParser()
    parser.add_argument("--weights", type=str, default="yolov5n.pt",
                        help="initial weights path")
    parser.add_argument("--cfg", type=str, default="models/yolov5n.yaml",
                        help="model.yaml path")
    parser.add_argument("--data", type=str, default="models/data.yaml",
                        help="dataset.yaml path")
    parser.add_argument("--hyp", type=str, default=ROOT / "data/hyps/hyp.scratch-low.yaml", help="hyperparameters path")
    parser.add_argument("--epochs", type=int, default=1000, help="total training epochs")
    parser.add_argument("--batch-size", type=int, default=16, help="total batch size for all GPUs, -1 for autobatch")
    parser.add_argument("--imgsz", "--img", "--img-size", type=int, default=640, help="train, val image size (pixels)")
    parser.add_argument("--rect", action="store_true", help="rectangular training")
    parser.add_argument("--resume", nargs="?", const=True, default=False, help="resume most recent training")
    parser.add_argument("--nosave", action="store_true", help="only save final checkpoint")
    parser.add_argument("--noval", action="store_true", help="only validate final epoch")
    parser.add_argument("--noautoanchor", action="store_true", help="disable AutoAnchor")
    parser.add_argument("--noplots", action="store_true", help="save no plot files")
    parser.add_argument("--evolve", type=int, nargs="?", const=300, help="evolve hyperparameters for x generations")
    parser.add_argument(
        "--evolve_population", type=str, default=ROOT / "data/hyps", help="location for loading population"
    )
    parser.add_argument("--resume_evolve", type=str, default=None, help="resume evolve from last generation")
    parser.add_argument("--bucket", type=str, default="", help="gsutil bucket")
    parser.add_argument("--cache", type=str, nargs="?", const="ram", help="image --cache ram/disk")
    parser.add_argument("--image-weights", action="store_true", help="use weighted image selection for training")
    parser.add_argument("--device", default="cpu", help="cuda device, i.e. 0 or 0,1,2,3 or cpu")
    parser.add_argument("--multi-scale", action="store_true", help="vary img-size +/- 50%%")
    parser.add_argument("--single-cls", action="store_true", help="train multi-class data as single-class")
    parser.add_argument("--optimizer", type=str, choices=["SGD", "Adam", "AdamW"], default="SGD", help="optimizer")
    parser.add_argument("--sync-bn", action="store_true", help="use SyncBatchNorm, only available in DDP mode")
    parser.add_argument("--workers", type=int, default=8, help="max dataloader workers (per RANK in DDP mode)")
    parser.add_argument("--project", default=ROOT / "runs/train", help="save to project/name")
    parser.add_argument("--name", default="exp", help="save to project/name")
    parser.add_argument("--exist-ok", action="store_true", help="existing project/name ok, do not increment")
    parser.add_argument("--quad", action="store_true", help="quad dataloader")
    parser.add_argument("--cos-lr", action="store_true", help="cosine LR scheduler")
    parser.add_argument("--label-smoothing", type=float, default=0.0, help="Label smoothing epsilon")
    parser.add_argument("--patience", type=int, default=0, help="EarlyStopping patience (epochs without improvement)")
    parser.add_argument("--freeze", nargs="+", type=int, default=[0], help="Freeze layers: backbone=10, first3=0 1 2")
    parser.add_argument("--save-period", type=int, default=-1, help="Save checkpoint every x epochs (disabled if < 1)")
    parser.add_argument("--seed", type=int, default=0, help="Global training seed")
    parser.add_argument("--local_rank", type=int, default=-1, help="Automatic DDP Multi-GPU argument, do not modify")

    # Logger arguments
    parser.add_argument("--entity", default=None, help="Entity")
    parser.add_argument("--upload_dataset", nargs="?", const=True, default=False, help='Upload data, "val" option')
    parser.add_argument("--bbox_interval", type=int, default=-1, help="Set bounding-box image logging interval")
    parser.add_argument("--artifact_alias", type=str, default="latest", help="Version of dataset artifact to use")

    # NDJSON logging
    parser.add_argument("--ndjson-console", action="store_true", help="Log ndjson to console")
    parser.add_argument("--ndjson-file", action="store_true", help="Log ndjson to file")

开始模型训练,本地机器配置低的机器训练百来张图片还是很吃力的,我的是macbbok2018 i9款,本地训练1000多张图片,跑一个晚上,这里只是做操作演示,真正要训练还是要有GPU服务器才行,后续会有文章介绍云GPU使用教程。

在这里插入图片描述

训练完成再runs -> train -> exp 目录下就可以看到bast.pt文件,这就是已经训练好的模型文件

在这里插入图片描述

四、使用模型

可以用torch加载本地模型实现实时检测识别,也可以使用自带detect.py对图片与文件进行识别。

detect.py

--weights 模型文件路径

在这里插入图片描述

运行完之后,就能在runs —> detect 运行模型识别图片的结果。

在这里插入图片描述

五、总结

文章大致演示了yolov5的基础使用,感兴趣的同学多实践才方便理解,后续文章将使用训练好的模型进行游戏的自动化实战,以及GPU云服务器训练yolov5模型的教程,请持续关注。微信公众号搜索关注艺说IT,分享各种原创技术干货文章,对你有用的话请一键三连,感谢🙏。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值