Yolov5训练自己的数据集

Yolov5 创建自己的训练集

数据集的目录结构

首先我们需要了解训练的目录结构

跑通了官方训练集的时候我们会发现在yolov5的目录的同级目录有datasets文件夹

里面有coco128官方数据集

我们可以知道

|datasets
|	|----coco128
|	|	|-----images
|	|	|-----labels

images

在images的文件夹中我们会发现

|images
|	|-----train2017

在train2017中存放的是所需要的照片 .jpg

labels

|labels
	|-----train2017

在train2017中我们会发现是对应的标记

列如这个解释

45 0.479492 0.688771 0.955609 0.5955
45 0.736516 0.247188 0.498875 0.476417
50 0.637063 0.732938 0.494125 0.510583
45 0.339438 0.418896 0.678875 0.7815
49 0.646836 0.132552 0.118047 0.096937
49 0.773148 0.129802 0.090734 0.097229
49 0.668297 0.226906 0.131281 0.146896
49 0.642859 0.079219 0.148063 0.148062

归于第50类,然后后面的是整合后的坐标

引用数据集的目录结构

| yolov5
|	|-----data
|	|	|-----coco.yaml
|	|	|-----coco128.yaml

我们可以看到coco.yaml 和 coco128.yaml 的文件都是作为引索训练的文件配置文件

就用coco.yaml解释一下

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# COCO 2017 dataset http://cocodataset.org
# Example usage: python train.py --data coco.yaml
# parent
# ├── yolov5
# └── datasets
#     └── coco  ← downloads here


# 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, ..]
path: ../datasets/coco  # dataset root dir
train: train2017.txt  # train images (relative to 'path') 118287 images
val: val2017.txt  # train images (relative to 'path') 5000 images
test: test-dev2017.txt  # 20288 of 40670 images, submit to https://competitions.codalab.org/competitions/20794

# Classes
nc: 16  # number of classes
names: ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
        'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
        'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
        'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
        'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
        'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
        'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
        'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
        'hair drier', 'toothbrush']  # class names




这里我粗略的删除了东西因为不需要,这里重要的是

train:
test:
val :

后面的填充内容都是txt文件,冒号后面则是需要相应txt的路径

所以我们在这个目录下创建我们自己的person.yaml

内容

train: /yolov5上一级目录名称/yolov5/face_dataset/train.txt
val: /yolov5上一级目录名称/yolov5/face_dataset/val.txt
#或者用绝对路径也可以 
#这里是我们自己的训练的地方
# number of classes
nc: 16

# class names
names: []

nc 是你所需要训练的种类的类别多少

names是你所训练的类别的名字全部加入到这里

例如

names:["wuhu","aoligei"]

就先这样创建这来后面再创建face_dataset文件夹

创建生成txt文档的目录结构

首先来到yolov5的目录下 创建一个文件夹(这里名为)face_dataset

|yolov5|	|-----face_dataset

进去后我们从上面数据集的目录结构中了解到,我们需要创建出lable 已经image

进去face_dataset目录下创建两个文件夹分别为images 和 Annotations

|yolov5|	|-----face_dataset|	|	|-----images|	|	|-----Annotations

images中存放所有的照片

Annotations存放我们的标记文件.xml文件

首先我们需要做的是训练集和测试集分离就需要我们写一个py文件

存放目录:

|yolov5|	|-----face_dataset|	|	|-----images|	|	|-----Annotations|	|	|-----split_train_val.py

split_train_val.py的代码:

import osimport randomtrainval_percent = 1.0train_percent = 0.9#xml的文件路径xmlfilepath = 'Annotations'total_xml = os.listdir(xmlfilepath)num = len(total_xml)list = range(num)tv = int(num * trainval_percent)tr = int(num * train_percent)trainval = random.sample(list, tv)train = random.sample(trainval, tr)# ImageSets目录不存在,就创建if not os.path.exists('ImageSets/'):    os.makedirs('ImageSets/')# ImageSets/Main目录不存在,就创建if not os.path.exists('ImageSets/Main/'):    os.makedirs('ImageSets/Main/')ftrainval = open('ImageSets/Main/trainval.txt', 'w')ftest = open('ImageSets/Main/test.txt', 'w')ftrain = open('ImageSets/Main/train.txt', 'w')fval = open('ImageSets/Main/val.txt', 'w')for i in list:    name = 'yolov5/face_dataset/images/' + total_xml[i][:-4] + '.jpg' + '\n'    if i in trainval:        ftrainval.write(name)        if i in train:            ftrain.write(name)        else:            fval.write(name)    else:        ftest.write(name)ftrainval.close()ftrain.close()fval.close()ftest.close()

随后运行split_train_val.py就会发现目录结构有了改变

|yolov5|	|-----face_dataset|	|	|-----images|	|	|-----Annotations|	|	|-----split_train_val.py|	|	|-----ImageSets|	|	|	|-----Main|	|	|	|	|-----test.txt|	|	|	|	|-----train.txt|	|	|	|	|-----trainval.txt|	|	|	|	|-----val.txt			

我们打开train.txt 我们发现我们弄的是训练集90%的照片的引索

​ val.txt是我们10%的测试集的照片的引索

然后我们需要生成lables即可大功告成

回到目录

|yolov5|	|-----face_dataset|	|	|-----images|	|	|-----Annotations|	|	|-----split_train_val.py|	|	|-----ImageSets

创建生成labes的py文件 voc_label.py

voc_label.py代码

import xml.etree.ElementTree as ETimport pickleimport osfrom os import listdir, getcwdfrom os.path import joinimage_sets = ['train', 'val', 'test']#这里classes和上面一样存放你所有的类名比如#classes=["wuhu","aoligei"]classes = []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    print(x)    print(h)    print(y)    print(w)    isValid = True    if x == 0 or y == 0 or w == 0 or h == 0:        print(f'x :{x} y:{y} w:{w} h:{h}')        isValid = False    if box[0] == 0 or box[1] == 0 or box[2] == 0 or box[3] == 0:        print(f'box[0] :{box[0]} box[1]:{box[1]} box[2]:{box[2]} box[3]:{box[3]}')        isValid = False    return (x, y, w, h), isValiddef convert_annotation(image_id):    #我们需要引用xml中的标记进行显示对生成labes    in_file = open('Annotations/%s.xml' % (image_id.split("/").pop().split(".")[0]))    print(in_file)    out_file = open('labels/%s.txt' % (image_id.split("/").pop().split(".")[0]), 'w')    print(out_file)    tree = ET.parse(in_file)    root = tree.getroot()    size = root.find('size')    w = int(size.find('width').text)    print(w)    h = int(size.find('height').text)    print(h)    # print(root['object'])    # return    objList = root.findall('object')    # for obj in objList:    for obj in root.iter('object'):        difficult = obj.find('difficult').text        cls = obj.find('name').text        print('-------')        # 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, isValid = convert((w, h), b)        if isValid == False:            # out_file.close()            print(image_id)            return False        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')        print("文件内容:")        print(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')    out_file.flush()    out_file.close()    return Trueif not os.path.exists('labels/'):    os.makedirs('labels/')for image_set in image_sets:    # strip() 移除字符串的首尾字符,默认为空格    # split() 字符串分割,默认为所有空字符,包含空格、换行、制表符    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:        isValid = convert_annotation(image_id)        if isValid == True:            list_file.write('%s\n' % (image_id))        else:            print(f'存在无效值:{image_id}')    list_file.close()

在运行split_train_val.py的基础上才能运行voc_label.py

运行了voc_label.py后目录结构会发生改变

|yolov5|	|-----face_dataset|	|	|-----images|	|	|-----Annotations|	|	|-----split_train_val.py|	|	|-----ImageSets|	|	|-----labels|	|	|-----text.txt|	|	|-----train.txt|	|	|-----train.cache|	|	|-----train.cache.npy|	|	|-----val.txt|	|	|-----val.cache|	|	|-----val.cache.npy
|lables|	|-----照片名字.txt

我们所需要用到的就是在face_dataset的目录下的train.txttext.txtval.txt

所以person.yaml中我们设置的引索路径就是这里的

train: /yolov5_gpu/yolov5/face_dataset/train.txtval: /yolov5_gpu/yolov5/face_dataset/val.txt

准备训练前需要更改的地方

|yolov5|	|-----models|	|	|-----yolov5l.yaml|	|	|-----yolov5m.yaml|	|	|-----yolov5m.yaml|	|	|-----yolov5s.yaml|	|	|-----yolov5x.yaml

我们需要更改看我们用的是哪个的网络训练,比如说(官方默认的是yolov5s.yaml)我们点击进入对应的yaml中会看到

nc: 16  # number of classesdepth_multiple: 0.33  # model depth multiplewidth_multiple: 0.50  # layer channel multiple

我们只需要更改nc即可

nc:是我们所存有几种类

例如这里就是有16个类

|yolov5|	|-----train.py

在train.py中我们会发现

def parse_opt(known=False):    parser = argparse.ArgumentParser()    parser.add_argument('--weights', type=str, default=ROOT / 'weights/yolov5s.pt',                        help='initial weights path')    parser.add_argument('--cfg', type=str, default='', help='models/yolov5s.yaml')    parser.add_argument('--data', type=str, default=ROOT / 'data/person.yaml', help='dataset.yaml path')    parser.add_argument('--hyp', type=str, default=ROOT / 'data/hyps/hyp.scratch.yaml', help='hyperparameters path')    parser.add_argument('--epochs', type=int, default=200)    parser.add_argument('--batch-size', type=int, default=1, help='total batch size for all GPUs')    parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=240, 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 check')    parser.add_argument('--evolve', type=int, nargs='?', const=300, help='evolve hyperparameters for x generations')    parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')    parser.add_argument('--cache', type=str, nargs='?', const='ram', help='--cache images in "ram" (default) or "disk"')    parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')    parser.add_argument('--device', default='', 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('--adam', action='store_true', help='use torch.optim.Adam() 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='maximum number of dataloader workers')    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 dat aloader')    parser.add_argument('--linear-lr', action='store_true', help='linear LR')    parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')    parser.add_argument('--patience', type=int, default=100, help='EarlyStopping patience (epochs without improvement)')    parser.add_argument('--freeze', type=int, default=0, help='Number of layers to freeze. backbone=10, all=24')    parser.add_argument('--save-period', type=int, default=-1, help='Save checkpoint every x epochs (disabled if < 1)')    parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')    # Weights & Biases arguments    parser.add_argument('--entity', default=None, help='W&B: Entity')    parser.add_argument('--upload_dataset', action='store_true', help='W&B: Upload dataset as artifact table')    parser.add_argument('--bbox_interval', type=int, default=-1, help='W&B: Set bounding-box image logging interval')    parser.add_argument('--artifact_alias', type=str, default='latest', help='W&B: Version of dataset artifact to use')    opt = parser.parse_known_args()[0] if known else parser.parse_args()    return opt

我们一般需要更改的是:

  1. –weights:权值文件
  2. –cfg:所用的网络模型就是models中的yolov5s.yaml(这里是例子)
  3. –data:我们存放在data/person.yaml
  4. –hyp:这个是有关学习率和图像增强相关设置这个可以查阅一下(一般先不怎么改)
  5. –epochs:训练的次数
  6. –batch-size:一次给多少张图片

有些地方不是很对,但就这样了摆烂了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾米莉亚小汉堡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值