手把手教会你使用机器学习拥有YOLOV5自己的图像识别

目录

前期的准备

下载机器学习训练源码

数据集的收集与制作

文件配置

 配置训练集测试集划分txt文件

将划分完的测试训练集xml文件转为yolov5可识别的数据集

创建自己的模型

        下载预训练模型

        训练模型


导言

发这篇文章的目的不仅仅是教会小白也可以使用模型训练,拥有自己的模型,也算是对我这段时间的一个学习的记录吧,万一之后某一天还需要用到的时候可以再次捡起来进行学习和操作。本文采用Python 3.8 版本,使用的是Pycharm 进行教学,文中用到的库,在文件配置有提及。

更新时间:2022 年 01月  26日  21:08 

更新时间:2022 年 02月  02日  12:00

更新时间:2022 年 11月  25日  11:14

        更新了被和谐的模型下载链接

前期的准备

下载机器学习训练源码

1、YOLOv5的代码链接(大概4M):

GitHub - ultralytics/yolov5: YOLOv5 🚀 官方下载(推荐):https://github.com/ultralytics/yolov5
 

环境:

Python版本:官方文档给出的是Python3.8,但是其他博主说3.7左右也可以具体没试过

运行yolov5的包都在代码内的 requirements.txt 文件下,缺什么装什么就行了

 这边直接给出CMD命令安装。记得切换到你下载的yolov5的文件夹下后再执行以下命令!

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

在pip install的时候,可能会出现read timeout的情况多重复运行几次就行了。

数据集的收集与制作

首先得有数据,你才能训练和制作模型,这一步你可以寻找开源的数据,也可以自己爬虫,制作数据集是一个繁琐且枯燥的过程,这里需要使用LabelImg工具

这里提供链接省的各位找:LabelImg工具下载 提取码:fmcg

具体步骤就不展开了,大家可以看我的这篇博客:使用labelImg标注图像产生yolov5数据集

但是大家标注具体类别的时候一定要细心,因为这会决定你的预测结果。

这是一篇教学文章,为了让大家快速上手,避免浪费大量时间收集数据

数据已经给各位准备好了

安全帽数据集 提取码:03g2 https://pan.baidu.com/s/16UDG3nlx8ZY4QZ4Gmzxc3g%C2%A0数据集是放在百度网盘的(挺大的),有需要的可以在评论区留下你的邮箱,我私发给你!
 

文件配置

        配置训练集测试集划分txt文件

首先在下载好的文件解压到data文件夹内

(或者不下载数据集,直接在data文件夹下创建VOC2028文件夹,文件夹下包含这两个文件)

注意: JPEGimages内为数据集原始图片,Annotations内为标注的xml文件)
你需要将标注完之后将图片和标注文件放入这两个文件夹内。

分割测试集训练集代码:

import argparse
import os
import random

parser = argparse.ArgumentParser()
# xml文件的地址,根据自己的数据进行修改 xml一般存放在Annotations下
parser.add_argument('--xml_path', default='VOC2028/Annotations', type=str, help='input xml label path')
# 数据集的划分,地址选择自己数据下的ImageSets/Main
parser.add_argument('--txt_path', default='VOC2028/ImageSets/Main', type=str, help='output txt label path')
opt = parser.parse_args()

trainval_percent = 0.8  # 训练集和验证集所占比例。 这里划分0.8的测试集,可自己进行调整
train_percent = 0.9  # 训练集所占比例,可自己进行调整
xmlfilepath = opt.xml_path
txtsavepath = opt.txt_path
total_xml = os.listdir(xmlfilepath)
if not os.path.exists(txtsavepath):
    os.makedirs(txtsavepath)

num = len(total_xml)
list_index = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list_index, tv)
train = random.sample(trainval, tr)

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')

for i in list_index:
    name = total_xml[i][:-4] + '\n'
    if i in trainval:
        file_trainval.write(name)
        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()

以上代码存放在data文件夹下(就是和VOC2028文件夹放在一块),我代码叫NO1.py,这个随便自己取都行,叫123.py也可以(这里最好按照命名规则来,我这里是为了方便查找)

执行完毕,查看是否正确执行

数据集内的 VOC2028\ImageSets 文件夹下有个Main文件,这是配置好的训练集和测试集

路径和我一样的就会在 VOC2028\ImageSets 文件夹下有个Main文件,文件内就包含数据集测试集的划分内容

 有了这些就可以让程序去划分图像,分为测试集验证集

将划分完的测试训练集xml文件转为yolov5可识别的数据集

NO2.py  (路径和NO1.py文件是一样的存放位置,都是放在data文件夹内)

import os
import shutil
from pathlib import Path
from shutil import copyfile
from xml.dom.minidom import parse

import numpy as np
from PIL import Image, ImageDraw
from tqdm import tqdm

my_class = ['helmet', 'person', 'hat']  # xml打上的标签类别
image = '.jpg' # 图像文件的统一格式
FILE_ROOT = Path(r"../data")  # data的相对路径

# 原始数据集
IMAGE_SET_ROOT = FILE_ROOT.joinpath(r"VOC2028/ImageSets/Main")  # 图片区分文件的路径
IMAGE_PATH = FILE_ROOT.joinpath(r"VOC2028/JPEGImages")  # 图片的位置
ANNOTATIONS_PATH = FILE_ROOT.joinpath(r"VOC2028/Annotations")  # 数据集标签文件的位置
LABELS_ROOT = FILE_ROOT.joinpath(r"VOC2028/Labels")  # 进行归一化之后的标签位置

# YOLO 需要的数据集形式的新数据集
DEST_IMAGES_PATH = Path(r"Safety_Helmet_Train_dataset/score/images")  # 区分训练集、测试集、验证集的图片目标路径
DEST_LABELS_PATH = Path(r"Safety_Helmet_Train_dataset/score/labels")  # 区分训练集、测试集、验证集的标签文件目标路径


def cord_converter(size, box):
    """
    将标注的 xml 文件标注转换为 darknet 形的坐标
    :param size: 图片的尺寸: [w,h]
    :param box: anchor box 的坐标 [左上角x,左上角y,右下角x,右下角y,]
    :return: 转换后的 [x,y,w,h]
    """

    x1 = int(box[0])
    y1 = int(box[1])
    x2 = int(box[2])
    y2 = int(box[3])

    dw = np.float32(1. / int(size[0]))
    dh = np.float32(1. / int(size[1]))

    w = x2 - x1
    h = y2 - y1
    x = x1 + (w / 2)
    y = y1 + (h / 2)

    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return [x, y, w, h]


def save_label_file(img_jpg_file_name, size, img_box):
    """
    保存标签的解析文件
    :param img_jpg_file_name:
    :param size:
    :param img_box:
    :return:
    """
    save_file_name = LABELS_ROOT.joinpath(img_jpg_file_name).with_suffix('.txt')
    with open(save_file_name, "a+") as f:
        for box in img_box:
            cls_num = my_class.index(box[0])
            # print(box[0], cls_num)
        """# 原版代码是需要手动修改类别,改为上述的自动识别了
        for box in img_box:
            if box[0] == 'person':  # 数据集 xml 中的 hat 指的是头
                cls_num = 1
            elif box[0] == 'hat':
                cls_num = 2
            else:
                continue"""

        new_box = cord_converter(size, box[1:])  # 转换坐标
        f.write(f"{cls_num} {new_box[0]} {new_box[1]} {new_box[2]} {new_box[3]}\n")


def test_dataset_box_feature(file_name, point_array):
    """
    使用样本数据测试数据集的建议框
    :param file_name: 图片文件名
    :param point_array: 全部的点 [建议框sx1,sy1,sx2,sy2]
    :return: None
    """
    im = Image.open(IMAGE_PATH.joinpath(file_name).with_suffix(image))
    im_draw = ImageDraw.Draw(im)
    for box in point_array:
        x1 = box[1]
        y1 = box[2]
        x2 = box[3]
        y2 = box[4]
        im_draw.rectangle((x1, y1, x2, y2), outline='red')

    im.show()


def get_xml_data(img_xml_file: Path):
    """
    获取 xml 数据
    :param img_xml_file: 图片路径
    :return:
    """
    dom = parse(str(img_xml_file))
    xml_root = dom.documentElement
    img_name = xml_root.getElementsByTagName("filename")[0].childNodes[0].data
    img_size = xml_root.getElementsByTagName("size")[0]
    objects = xml_root.getElementsByTagName("object")
    img_w = img_size.getElementsByTagName("width")[0].childNodes[0].data
    img_h = img_size.getElementsByTagName("height")[0].childNodes[0].data
    img_c = img_size.getElementsByTagName("depth")[0].childNodes[0].data
    img_box = []
    for box in objects:
        cls_name = box.getElementsByTagName("name")[0].childNodes[0].data
        x1 = int(box.getElementsByTagName("xmin")[0].childNodes[0].data)
        y1 = int(box.getElementsByTagName("ymin")[0].childNodes[0].data)
        x2 = int(box.getElementsByTagName("xmax")[0].childNodes[0].data)
        y2 = int(box.getElementsByTagName("ymax")[0].childNodes[0].data)
        img_box.append([cls_name, x1, y1, x2, y2])

    # test_dataset_box_feature(img_xml_file.name, img_box)
    save_label_file(img_xml_file.name, [img_w, img_h], img_box)


def copy_data(img_set_source, img_labels_root, imgs_source, dataset_type):
    """
    将标签文件和图片复制到最终数据集文件夹中
    :param img_set_source: 原数据集图片总路径
    :param img_labels_root: 生成的 txt 标签总路径
    :param imgs_source:
    :param dataset_type: 生成数据集的种类
    :return:
    """
    file_name = img_set_source.joinpath(dataset_type).with_suffix(".txt")  # 获取对应数据集种类的图片

    # 判断目标图片文件夹和标签文件夹是否存在,不存在则创建
    os.makedirs(FILE_ROOT.joinpath(DEST_IMAGES_PATH, dataset_type), exist_ok=True)
    os.makedirs(FILE_ROOT.joinpath(DEST_LABELS_PATH, dataset_type), exist_ok=True)

    with open(file_name, encoding="UTF-8") as f:
        for img_name in tqdm(f.read().splitlines()):
            img_sor_file = imgs_source.joinpath(img_name).with_suffix(image)
            label_sor_file = img_labels_root.joinpath(img_name).with_suffix('.txt')

            # 复制图片
            dict_file = FILE_ROOT.joinpath(DEST_IMAGES_PATH, dataset_type, img_name).with_suffix(image)
            copyfile(img_sor_file, dict_file)

            # 复制 label
            dict_file = FILE_ROOT.joinpath(DEST_LABELS_PATH, dataset_type, img_name).with_suffix('.txt')
            copyfile(label_sor_file, dict_file)


if __name__ == '__main__':
    root = ANNOTATIONS_PATH  # 数据集 xml 标签的位置

    if LABELS_ROOT.exists():
        # 清空标签文件夹
        print("Cleaning Label dir for safety generating label, pls wait...")
        shutil.rmtree(LABELS_ROOT)
        print("Cleaning Label dir done!")
    LABELS_ROOT.mkdir(exist_ok=True)  # 建立 Label 文件夹

    # 生成标签
    print("Generating Label files...")
    with tqdm(total=len(os.listdir(root))) as p_bar:
        for file in root.iterdir():
            p_bar.update(1)
            get_xml_data(file)

    # 将文件进行 train、val、test 的区分
    for dataset_input_type in ["train", "val", "test"]:
        # print(f"Copying data {dataset_input_type}, pls wait...")
        copy_data(IMAGE_SET_ROOT, LABELS_ROOT, IMAGE_PATH, dataset_input_type)

运行之后和我一样,那么恭喜你完成一半了 !

 等到百分之百之后就完成了,会在文件下生成 Safety_Helmet_Train_dataset 文件

一定要检查一下 yolov5-master\data\Safety_Helmet_Train_dataset\Labels 文件夹下的txt 文件是否拥有数据!!!!

没有数据就代表你之前设置的类别有问题

解决方法:上一步中  NO2.py 文件内classes 数组的类别重新修改为自己的类别,必须与xml标注文件内的标签一致!

正确操作步骤之后 执行的效果如下:

到这里你已经完成了训练模型的所有文件配置。可以开始准备着手训练模型了!

创建自己的模型

        下载预训练模型

                进入到  yolov5-master\weights 文件夹放置预训练模型,这里我使用的是small版本的模型,模型更小训练更快

下载链接: yolov5s预训练模型文件(又又又更新)(github)(09.03)11-25再次更新https://objects.githubusercontent.com/github-production-release-asset-2e65be/264818686/14327886-3839-4fa5-96c3-d52cfa73cdc5?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20221125%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20221125T031110Z&X-Amz-Expires=300&X-Amz-Signature=ed1e5ed2f12783fc00ac22b85e8a49dbd348bb3a3866834a300d015c1f04df54&X-Amz-SignedHeaders=host&actor_id=92858429&key_id=0&repo_id=264818686&response-content-disposition=attachment%3B%20filename%3Dyolov5s.pt&response-content-type=application%2Foctet-stream

因为链接老是被和谐,这里给了github的官方下载地址。      = = 

11-25又又又更新了一次,再被和谐只能去GItHub搜索yolov5在这点击下载就可以了

 

(这里使用的是轻量部署模型,yolov5s,训练速度快,需要更好的模型可以在官方网站下载) 

然后放置到

在路径  yolov5-master/data/  文件夹中创建自己的数据集配置文件custom_data.yaml

 代码: 

# Custom data for safety helmet

# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
train: ./data/Safety_Helmet_Train_dataset/score/images/train
val: ./data/Safety_Helmet_Train_dataset/score/images/val

nc: 3  # number of classes

names: ['person', 'head', 'helmet'] # my classes

训练模型

在cmd中进入yolov5 文件夹(在编译器内进入也行,我自己是在Pycharm内进入的,效果一样)

方法一、

方法二、

 

我这里是在Pycharm中打开终端,没有Pycharm也可以选cmd打开(效果一样)

记得进去yolov5的目录下 ​

然后输入以下指令:

python train.py --img 640 --batch 16 --epochs 50 --data ./data/custom_data.yaml --weights ./weights/yolov5s.pt

注意

--batch 16 一次喂多少数据,我这内存就能给16,所以可以不传按默认16

        (如果内存比较小的,建议改为8,或者4)

        (但是也需要根据实际情况,看自身内存的)

--epochs 50 代表迭代五十次,可自行修改 

--data ./data/custom_data.yaml   代表数据集配置文件

--weights  代表预训练模型

当你等待一段时间之后,看见以下图片,就证明模型训练成功了!在你等待大概十七个小时之后就可以拥有自己的数据模型PT了!(GPU训练很快,下次出个GPU安装的教程)

(因为我没有使用GPU进行训练,在运行的时候一直提示我CUDA不可用,一般忽略就行。 )

 warnings.warn('User provided device_type of \'cuda\', but CUDA is not available. Disabling')

大概意思就是我可以使用GPU进行训练,但是我没有使用

模型保存位置: yolov5-master\runs\train\exp2\weights\best.pt 


训练完的模型怎么使用呢?

更新:2022年 02月02日 14:37

更新:2022年 07月01日 15:57

基于yolov5模型训练之后的图像识别_顽童任逍遥的博客-CSDN博客基于yolov5模型训练之后的图像识别https://blog.csdn.net/qq_42368762/article/details/122769145

  • 3
    点赞
  • 89
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
yolov5是一种用于图像识别的模型。它有四种不同的预训练模型,分别是yolov5s、yolov5m、yolov5l和yolov5x。这些模型在效果和精度上有所不同。你可以根据自己的需求选择合适的模型进行训练。在进行图像检测时,你可以使用已经下载好的模型进行识别。例如,如果你选择了yolov5x模型,你可以使用--weights yolov5x.pt来进行图像识别。推荐使用yolov5s模型,除非你对准确度有非常高的要求,否则训练它需要花费很长时间和足够的硬件支持。你可以参考\[2\]和\[3\]中的链接获取更多关于yolov5模型训练和图像识别的信息。 #### 引用[.reference_title] - *1* [基于yolov5图像识别](https://blog.csdn.net/LateNight_LL/article/details/125615068)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [手把手教会使用机器学习拥有YOLOV5自己的图像识别](https://blog.csdn.net/qq_42368762/article/details/122690675)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [使用yolov5实现图像识别](https://blog.csdn.net/qq_41974199/article/details/130975885)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值