YOLOv3訓練本身的數據

 

1.  下載預訓練權重文件

YOLOv3使用在Imagenet上預訓練好的模型參數(文件名稱: darknet53.conv.74,大小76MB)基礎上繼續訓練。
darknet53.conv.74下載連接:  https://pjreddie.com/media/files/darknet53.conv.74,下載完成後放在darknet主目錄。python

也能夠直接在darknet目錄下經過wget命令下載:git

wget https://pjreddie.com/media/files/darknet53.conv.74


2.  準備打標工具並對本身的圖片數據打標

打標工具推薦使用 labelImg,下載地址:https://github.com/tzutalin/labelImghttp://download.csdn.net/download/dcrmg/9974195
labelImg使用很簡單,在圖片的物體上畫框而後給一個標籤就能夠了,打標結果的保存格式是xml文件。
例如對於train1.jpg,打標結果保存爲train1.xmlgithub

 

3.  xml標籤文件格式轉換

YOLO訓練的標籤文件是txt格式,須要把第2步中的xml文件轉換。工具

  •  1) 在darknet主目錄下建立4個文件夾: trainImage、validateImage、trainImageXML 和 validateImageXML,並分別存放第2步中的訓練集圖片、驗證集圖片、訓練集xml標籤和驗證集xml標籤
  •  2) 藉助createID.py生成訓練集和驗證集的圖片名稱列表trainImageId.txt和validateImageId.txt。

     createID.py 代碼:測試

# -*- coding: utf-8 -*-
import os;
import shutil;
 
def listname(path,idtxtpath):
    filelist = os.listdir(path);  # 該文件夾下全部的文件(包括文件夾)
    filelist.sort()
    f = open(idtxtpath, 'w');
    for files in filelist:  # 遍歷全部文件
        Olddir = os.path.join(path, files);  # 原來的文件路徑
        if os.path.isdir(Olddir):  # 若是是文件夾則跳過
            continue;
        f.write(files);
        f.write('\n');
    f.close();
 
savepath = os.getcwd()
imgidtxttrainpath = savepath+"/trainImageId.txt"
imgidtxtvalpath = savepath + "/validateImageId.txt"
listname(savepath + "/trainImage",imgidtxttrainpath)
listname(savepath + "/validateImage",imgidtxtvalpath)
print "trainImageId.txt && validateImageId.txt have been created!"

  3) 藉助trans.py生成訓練集和驗證集的完整路徑列表並完成標籤xml文件到txt文件的轉換
  trans.py代碼spa

import xml.etree.ElementTree as ET
import pickle
import string
import os
import shutil
from os import listdir, getcwd
from os.path import join
import cv2
 
sets=[('2012', 'train')]
 
classes = ["class1","class2","class3","class4"]
 
def convert(size, box):
    dw = 1./size[0]
    dh = 1./size[1]
    x = (box[0] + box[1])/2.0
    y = (box[2] + box[3])/2.0
    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,flag,savepath):
 
    if flag == 0:
        in_file = open(savepath+'/trainImageXML/%s.xml' % (os.path.splitext(image_id)[0]))
        out_file = open(savepath+'/trainImage/%s.txt' % (os.path.splitext(image_id)[0]), 'w')
        tree = ET.parse(in_file)
        root = tree.getroot()
        size = root.find('size')
 
        img = cv2.imread('./trainImage/'+str(image_id))
        h = img.shape[0]
        w = img.shape[1]
 
    elif flag == 1:
        in_file = open(savepath+'/validateImageXML/%s.xml' % (os.path.splitext(image_id)[0]))
        out_file = open(savepath+'/validateImage/%s.txt' % (os.path.splitext(image_id)[0]), 'w')
 
        tree = ET.parse(in_file)
        root = tree.getroot()
        size = root.find('size')
 
        img = cv2.imread('./validateImage/' + str(image_id))
        h = img.shape[0]
        w = img.shape[1]
 
    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')
 
wd = getcwd()
 
for year, image_set in sets:
    savepath = os.getcwd();
    idtxt = savepath + "/validateImageId.txt";
    pathtxt = savepath + "/validateImagePath.txt";
    image_ids = open(idtxt).read().strip().split()
    list_file = open(pathtxt, 'w')
    s = '\xef\xbb\xbf'
    for image_id in image_ids:
        nPos = image_id.find(s)
        if nPos >= 0:
            image_id = image_id[3:]
        list_file.write('%s/validateImage/%s\n' % (wd, image_id))
        print(image_id)
        convert_annotation(image_id, 1, savepath)
    list_file.close()
 
    idtxt = savepath + "/trainImageId.txt";
    pathtxt = savepath + "/trainImagePath.txt" ;
    image_ids = open(idtxt).read().strip().split()
    list_file = open(pathtxt, 'w')
    s = '\xef\xbb\xbf'
    for image_id in image_ids:
        nPos = image_id.find(s)
        if nPos >= 0:
           image_id = image_id[3:]
        list_file.write('%s/trainImage/%s\n'%(wd,image_id))
        print(image_id)
        convert_annotation(image_id,0,savepath)
    list_file.close()

注意: 須要根據本身的類別更改trans.py文件第12行的classes,有幾個類別寫幾個。
執行以後在darknet主目錄下生成trainImagePath.txt、validateImagePath.txt和全部的txt標註文件。.net

 

4. 修改配置文件

  •   1) 修改data/voc.names 文件

     把 voc.names文件內容改爲本身的分類,例若有3個分類class_1,class_2,class_3,則voc.names內容改成:
      class_1
      class_2
      class_3code

 

  •   2) 修改cfg/voc.data文件

  根據本身的實際狀況作如下修改:
   classes = N       #(N爲本身的分類數量,若有10類不一樣的對象,N = 10)
   train = /home/XXX/darknet/trainImagePath.txt    # 訓練集完整路徑列表
   valid = /home/XXX/darknet/validateImagePath.txt   # 測試集完整路徑列表
   names = data/voc.names    # 類別文件
   backup = backup     #(訓練結果保存在darknet/backup/目錄下)xml


 

  •    3) 修改cfg/yolov3-voc.cfg 文件

   1. classes = N (N爲本身的分類數)
   2. 修改每個[yolo]層(一共有3處)以前的filters爲 3*(classes+1+4),若有3個分類,則修改 filters = 24
   3. (可選) 修改訓練的最大迭代次數, max_batches = N對象

 

5. YOLOv3訓練

./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74

訓練完成後結果文件 ‘yolov3-voc_final.weights’ 保存在 backup文件中。

 

6. 自訓練模型測試

./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights 01.jpg
相關文章
相關標籤/搜索