天天看點

YOLOv5建構自己的資料集并訓練

前言

本文預設已安裝好Anaconda等python環境,并已下載下傳好YOLO項目且可運作DEMO。接下來将着重在資料集建構的介紹上。

目錄

前言

1.Environment

2.建構資料集

2.1 目錄建構

2.2 資料集劃分

2.3 标記檔案轉換

3. 配置模型檔案及訓練

4. 可視化

1.Environment

本文所用環境:代碼版本V3.0,源碼下載下傳位址:https://github.com/ultralytics/yolov5.git

Pytorch:1.6.0

Cuda:10.1

Python:3.7

官方要求Python>=3.8 and PyTorch>=1.6.

通過git clone https://github.com/ultralytics/yolov5.git将YOLOv5源碼下載下傳到本地,建立好虛拟環境,并通過pip install -r requirements.txt安裝依賴包

2.建構資料集

2.1 目錄建構

本文資料标注使用labelImg,将标注中産生的*.xml檔案放入Annotations裡,将用于标注的圖檔放入images中,具體目錄結構如下圖:

YOLOv5建構自己的資料集并訓練

2.2 資料集劃分

在dataset目錄下建立python檔案split_train_val.py用于資料劃分,運作之後将會在dataset目錄下生成ImageSets/Main ,在Main檔案夾内自動生成train.txt,val.txt,test.txt和trainval.txt四個檔案,存放訓練集、驗證集、測試集圖檔的名字(無字尾.jpg),源碼如下:

# 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 = 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()
           

2.3 标記檔案轉換

由于yolo是是支援voc資料類型的,是以我們需要對此進行裝換,同樣在dataset目錄下建立voc_worktxt.py檔案,檔案中源碼如下:

# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
import os
from os import getcwd

sets = ['train', 'val', 'test']
classes = ["plate_switch_close", "plate_switch_open"]   # 改成自己的類别
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
    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
    return x, y, w, h

def convert_annotation(image_id):
    in_file = open('Annotations/%s.xml' % (image_id), encoding='UTF-8')
    out_file = open('worktxt/%s.txt' % (image_id), 'w')
    tree = ET.parse(in_file)
    root = tree.getroot()
    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
        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)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')

wd = getcwd()
for image_set in sets:
    if not os.path.exists('worktxt/'):
        os.makedirs('worktxt/')
    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:
        list_file.write(abs_path + '/images/%s.jpg\n' % (image_id))
        convert_annotation(image_id)
    list_file.close()
           

此段代碼運作之後,會在dataset目錄下生成worktxt檔案,此目錄中就是已經裝換後的标記檔案,并且會生成test.txt、train.txt、val.txt三個檔案。如下圖所示:

YOLOv5建構自己的資料集并訓練

3. 配置模型檔案及訓練

主要指coco.yaml與yolo5l.yaml兩個檔案,如下圖所示:

YOLOv5建構自己的資料集并訓練

1.coco.yaml最好複制一份到dataset目錄下進行修改,修改内容如下圖:

YOLOv5建構自己的資料集并訓練

修改為dataset目錄下的test.txt、train.txt、val.txt,而不是其他目錄下的檔案。

2.yolo5l.yaml需要修改如紅框所示,即識别類别數量;

YOLOv5建構自己的資料集并訓練

3.訓練時,需要修改train.py中的幾個參數,如下圖所示:

YOLOv5建構自己的資料集并訓練

需要将剛才修改過的coco.yaml引入進來,如果還涉及到其他參數的修改,參考下方參數解釋:

epochs 指的就是訓練過程中整個資料集将被疊代多少次
batch-size 一次看完多少張圖檔才進行權重更新,梯度下降的mini-batch
cfg 存儲模型結構的配置檔案
data 存儲訓練、測試資料的檔案
img-size 輸入圖檔寬高
rect 進行矩形訓練
resume 恢複最近儲存的模型開始訓練
nosave 僅儲存最終checkpoint
notest 僅測試最後的epoch
evolve 進化超參數
bucket gsutil bucket
cache-images 緩存圖像以加快訓練速度
weights 權重檔案路徑
name  重命名results.txt to results_name.txt
device cuda device, i.e. 0 or 0,1,2,3 or cpu
adam 使用adam優化
multi-scale 多尺度訓練,img-size +/- 50%
single-cls 單類别的訓練集

4.執行指令

python train.py --img 640 --batch 16 --epoch 300 --data data/ab.yaml --cfg models/yolov5s.yaml --weights weights/yolov5s.pt --device '0'     # 0号GPU
           

4. 可視化

在pycharm終端中運作tensorboard --logdir runs/train,然後在浏覽器中通路http://localhost:6006/(具體見控制台輸出)

YOLOv5建構自己的資料集并訓練
YOLOv5建構自己的資料集并訓練

至此,建構資料集及訓練全部介紹完畢。值得注意的是過程中涉及到模型的下載下傳和選取,可自行查詢資料。值得注意的在開始訓練時,需要通過train_batch圖檔檢查自己的labels是否完全覆寫,可有效避免大規模訓練後出現label缺失的問題。

繼續閱讀