如何用yolov5训练自己的数据(简要版)

1.创建虚拟环境 

conda create -n yolov5a python=3.8

2.安装labelimg

pip install labelimg

            or

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple labelimg

3.终端输入labelimg

  把你的数据集(你的图片放在一个文件夹例如:images),另外创建一个生成后的数据保存文件夹(例如:Annotations),点击file-open dir(这是你的数据集路径),点击file-chenge save dir(这是你的输出路径)

voc标注方式,最后生成的是.xml格式的文件,

而再次点击它(PascalVoc)会出现yolo格式的标注,最会生成的txt格式的文件

 最后我们需要的是.txt文件格式的标注,但是如果你要是忘了后面还是有代码将xml转换为txt格式的代码,快捷键:W是启动标注,A是上一张,D是下一张图片,(就像我们以前打CF前后左右键)在view里面点击自动保存。

 

    数据集就标注完成了,现在你手里有两个文件夹一个存放原始图片的,一个是存放标注文件的,

4.然后再yolov5的源码里要修改哪些地方呢

 (1)首先你应该把你刚刚的两个文件放到data文件夹里面去:把原图片放到JPEGimages文件夹,把标签文件还是放在原来的文件里面,images里面是源码自带的文件夹所以不管他,

  现在我们训练是需要两个文件train.txt、val.txt、原图片、.txt格式的标注文件。所以我们这里要运行一个代码将数据集分为训练集、测试集、验证集等几个txt文件(先不用管几个反正需要的只有train、val),就在data目录下创建一个python代码:

# coding:utf-8
 
import os
import random
import argparse
 
parser = argparse.ArgumentParser()
#xml文件的地址,根据自己的数据进行修改 xml一般存放在Annotations下
parser.add_argument('--xml_path', default='Annotations', type=str, help='input xml label path')
#数据集的划分,地址选择自己数据下的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
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 = 'D:/FOD/yolov5/yolov5_4/data/images/'+total_xml[i][:-4] +'.jpg' '\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()

运行完这个代码会出现以下文件夹:

imagesets-mian里面就存放着我们一会需要的train.txt, val.txt等四个文件, 

最重要的问题也是经常训练出错的问题:没有找到图片啊,图片加载失败啊什么的

  就是刚刚我们生成数据集的代码里面,生成的四个文件主要是存放的数据集的路径:

  这四个文件里面存放的是我们的图片路径,所以我们就要改一下上面name的代码,改成你自己的文件路径:比如D:/张三/李四/yolov5/data/JPEGimages/img.jpg, 记住一定要是英文路径,斜杠一定要这个斜杠,必须要有后缀。我们这里JPEGimages存放的原图片所以就写成JPEGimages;
————————————————

我们的标注文件默认为.xml,如果你已经是.txt格式的你就直接在data文件夹下面创建一个labels文件夹把他们放到里面去,为了以防万一再把所有的txt文件放到JPEGimages存放原图的文件夹如下:你这里应该是JPEGimages下面

  labels文件

  如果是.xml的话我们运行下面的代码:将xml格式转换为txt格式的就完事了;这个代码创建在项目的文件下也就是和你的train.py在一起创建,

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
 
# 数据标签
classes = ['person'] #需要修改
 
def convert(size, box):
    dw = 1./(size[0])
    dh = 1./(size[1])
    x = (box[0] + box[1])/2.0 - 1
    y = (box[2] + box[3])/2.0 - 1
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    if w>=1:
        w=0.99
    if h>=1:
        h=0.99
    return (x,y,w,h)
 
def convert_annotation(rootpath,xmlname):
    xmlpath = rootpath + '/Annotations'
    xmlfile = os.path.join(xmlpath,xmlname)
    with open(xmlfile, "r", encoding='UTF-8') as in_file:
      txtname = xmlname[:-4]+'.txt'
      print(txtname)
      txtpath = rootpath + '/labels'  #生成的.txt文件会被保存在labels目录下
      if not os.path.exists(txtpath):
        os.makedirs(txtpath)
      txtfile = os.path.join(txtpath,txtname)
      with open(txtfile, "w+" ,encoding='UTF-8') as out_file:
        tree=ET.parse(in_file)
        root = tree.getroot()
        size = root.find('size')
        w = int(size.find('width').text)
        h = int(size.find('height').text)
        out_file.truncate()
        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))
            bb = convert((w,h), b)
            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
 
 
if __name__ == "__main__":
    rootpath='F:\\QQ\yolov5\yolov5\\yolov5_4\\data'  ##需要修改的地方改成你的路径
    xmlpath=rootpath+'\\Annotations'这就是xml的路径
    list=os.listdir(xmlpath)
    for i in range(0,len(list)) :
        path = os.path.join(xmlpath,list[i])
        if ('.xml' in path)or('.XML' in path):
            convert_annotation(rootpath,list[i])
            print('done', i)
        else:
            print('not xml file',i)
 

运行完之后

 数据集分配问题解决了之后我们要修改coco.yaml, 与 models文件夹下面yolov5s.yaml文件的东西,

coco.yaml里面存放的是train.txt,和val.txt的存放路径,以及类别数量,和类别名字:也就是我们刚刚代码生成的文件路径,

  yolov5s.yaml改一下类别就可以了,改成你自己的类别数量   如我的类别是1,所以nc=1

 基本上没有需要改的了,我们直接打开train.py看看:直接划到最下面参数部分

代码里面的data,从data里面的coco.yaml读取train.txt(训练集的地址),train.txt就是存放的图片路径这样就可以读取到图片,标签的话自动定位到对应到labels文件的标签,weights就是预训练模型,epoch训练的轮数,我一般设置的是200,300,batch_size是多少张图片打包,如果电脑不好就是1,2,8,16,32,64,越大就是电脑需要的性能越好,device:设置为0,workers:代表启动的线程数,如果电脑不好就设置为0,表示主线程。

    这样我们就可以直接运行这个代码了,运行完之后在根目录下面runs--train里面找到自己的权重,有一个best.pt用来去检测。

如出现报错 AssertionError: train: No labels in E:\yolov5\yolov5\data_area\lables\train.cache. Can 

首先找到utils文件,再utils文件中找到dataloaders.py文件,ctrl+F搜define label

  将第二行改为自己存放自己图片的文件夹名称即 如我的图片文件夹是JPEGimages,就把这里的images改成JPEGimages

原文链接:https://blog.csdn.net/qq_52859223/article/details/123701798

本文是在博主小吴的文章上基础上转载简化的,如想了解详细版本点以上链接

猜你喜欢

转载自blog.csdn.net/m0_71816999/article/details/129990772