1. 程式人生 > >darknet yolo v2 訓練自己的資料

darknet yolo v2 訓練自己的資料

        darknet訓練自己的資料,官方提供了一個訓練VOC的例子,我們參照這個例子,來訓練我們自己的資料。

1. 準備資料集

         首先我們應該準備好我們自己的資料集用於訓練。要訓練一個自己的網路,我們需要有訓練集和測試集。在這裡,我們建立兩個資料夾train和val用於存放這兩類資料。接下來,我們要做的是生成資料的標記檔案,也就是目標在圖片中的類別以及位置資訊。

1.1 生成標記檔案

生成yolo的標記檔案應該遵循以下兩個規則:

  1. 每個原影象都對應著一個標記檔案,而且檔名都相同,比如圖片的名字是1.jpg,那麼對應這張圖片的標記檔名稱應該為1.txt。
  2. 每個標記檔案中,內容應該是這樣的<object-class> <x> <y> <width> <height>,其中<x> <y> <width> <height>是相對於影象寬高的比例。

知道了這兩個規則之後,我們就可以定義我們的標記檔案了。這裡我已經有了VOC格式標記的XML檔案,那麼接下來我們使用python來生成YOLO格式的標記檔案,程式碼如下:

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join

TrainLabel_Dir = '/home/ubuntu/data/labels'  #XML所在目錄

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)

if not os.path.exists('labels/'):  #生成的label放在label目錄下
    os.makedirs('labels/')
for rootDir,dirs,files in os.walk(TrainLabel_Dir):
    for file in files:
        file_name = file.split('.')[0]
        out_file = open('labels/%s.txt'%(file_name),'w')
        in_file = open("%s/%s"%(rootDir,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)
        
        for obj in root.iter('object'):
            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("0" + " " + " ".join([str(a) for a in bb]) + '\n')     #我這裡只有一類,所以類別只是0.
        out_file.close()  

這樣我們就生成了YOLO格式的標記檔案了。如果按照上面的python程式碼,生成的標記檔案在當前路徑的label目錄下。

用此方法分別生成train和val的標記檔案

1.2 生成原圖片絕對路徑檔案

在YOLO的訓練中,還需要一個txt檔案來記錄所有待訓練圖片的絕對路徑。即train資料夾下所有圖片的絕對路徑,python程式碼如下:

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join

TrainDir = '/home/ubuntu/data/train'  #訓練檔案所在目錄

out_file = open('train.txt','w')  #生成的txt檔案
for root,dirs,files in os.walk(TrainDir):
    for file in files:
        out_file.write('%s/%s\n'%(root,file))
out_file.close()

用此方法分別生成train和val的txt檔案。

1.3 將原圖片和標記檔案放在一起

YOLO是直接通過替換原圖片絕對路徑的字尾名來找到對應標記檔案的。比如原圖片的絕對路徑為/home/ubuntu/data/train/1.jpg。則YOLO將會直接認為其對應的標記檔案路徑為/home/ubuntu/data/train/1.txt。所以,我們將之前1.1生成的標記檔案放到對應的原圖片目錄下。

2. 修改檔案

2.1 建立names檔案

在YOLO主目錄的data資料夾下,建立一個.names檔案,檔名任意。比如mydata.names。在該檔案中寫入所有類別的名稱,每一類佔一行。比如我這裡只檢測行人這一類,那麼只在第一行寫上"person"即可。

2.2 修改data檔案

接下來我們要做的是修改YOLO的cfg檔案。在darknet的主目錄下,進入cfg目錄,找到voc.data開啟,修改其中的內容

classes= 1           #訓練資料的類別數目,我這裡只有一類,所以這裡是1
train  = <path-to-voc>/train.txt             #上面1.2步驟生成的train檔案路徑
valid  = <path-to-voc>2007_test.txt         #上面1.2步驟生成的val檔案路徑
names = data/voc.names                    #上面2.1步驟建立的names檔案路徑
backup = backup                       #這是訓練得到的model的存放目錄,建議自己修改。

2.3 修改cfg檔案

如果你想應用yolo_voc.cfg網路來訓練你的資料,那麼你需要修改這個檔案中的一些內容。

  1. [region]層中classes改成你的類別數,我這裡只檢測行人,所以我改成了classes=1.
  2. [region]層上方的[convolution]層中,filters的數量改成(classes+coords+1)*NUM。我這裡改成了(1+4+1)*5=30.具體可以參考https://groups.google.com/forum/#!topic/darknet/B4rSpOo84yg

2.4 修改src/yolo.c檔案

  1. 第13行改成 char *voc_names[] = {"person"};  //如果你是一類的話,就改成這樣,如果你有多類,自己根據需求改。
  2. 第322行draw_detections函式中,最後一個引數由20改成你的類別數,我這裡是1。
  3. 第354行demo函式中,倒數第三個引數由20改成你的類別數,我這裡是1.
  4. 第17行改成 char *train_images = "<path-to-voc>/train.txt";     //上面1.2步驟生成的train檔案路徑
  5. 第18行改成 char *backup_directory = "/home/Ubuntu/Downloads/darknet-master/backup/";     //這個路徑自己指定。
  6. 第121行改成 char *base = "/home/Ubuntu/Downloads/darknet-master/results/comp4_det_test_";   //這個路徑自己指定。
  7. 第123行改成 list *plist = get_paths("<path-to-voc>/val.txt");  //上面1.2步驟生成的val檔案路徑
  8. 第209行改成 char *base = "/home/Ubuntu/Downloads/darknet-master/results/comp4_det_test_"; //這個路徑自己指定
  9. 第210行改成 list *plist = get_paths("<path-to-voc>/val.txt"); //上面1.2步驟生成的val檔案路徑

2.5 修改src/yolo_kernels.cu檔案

第62行draw_detections函式最後一個引數由20改成你的類別數,我這裡是1.

2.6 修改src/detector.c檔案

第368行改成 list *plist = get_paths("<path-to-voc>/train.txt");  #上面1.2步驟生成的train檔案路徑

第539行option_find_int函式的最後一個引數由20改成1.

2.7 重新編譯darknet yolo

cd <darknet_root>
make clean
make -j16

3. 訓練

所有的步驟都已經準備好了。最後就是訓練了。為了加快訓練速度,我們可以下載官方提供的預訓練模型。下載地址為

curl -O http://pjreddie.com/media/files/darknet19_448.conv.23

最後,我們cd到darknet的主目錄,輸入下面的指令來進行訓練

./darknet detector train cfg/voc.data cfg/yolo-voc.cfg darknet19_448.conv.23

這其中voc.data就是2.2中修改後的data檔案,yolo-voc.cfg是網路結構檔案,darknet19_448.conv.23是下載的預訓練模型。

整個的訓練時間比較長,慢慢等吧。。。。。