前言
本文預設已安裝好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中,具體目錄結構如下圖:

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三個檔案。如下圖所示:
3. 配置模型檔案及訓練
主要指coco.yaml與yolo5l.yaml兩個檔案,如下圖所示:
1.coco.yaml最好複制一份到dataset目錄下進行修改,修改内容如下圖:
修改為dataset目錄下的test.txt、train.txt、val.txt,而不是其他目錄下的檔案。
2.yolo5l.yaml需要修改如紅框所示,即識别類别數量;
3.訓練時,需要修改train.py中的幾個參數,如下圖所示:
需要将剛才修改過的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/(具體見控制台輸出)
至此,建構資料集及訓練全部介紹完畢。值得注意的是過程中涉及到模型的下載下傳和選取,可自行查詢資料。值得注意的在開始訓練時,需要通過train_batch圖檔檢查自己的labels是否完全覆寫,可有效避免大規模訓練後出現label缺失的問題。