Darknet的整體框架,安裝,訓練與測試


目錄

一、Darknet優勢

二、Darknet的結構

三、Darknet安裝

四、Darknet的訓練

五、Darknet的檢測

 

正文

一、Darknet優勢

darknet是一個由純C編寫的深度學習框架,它有着其它深度學習框架無法相比的優勢:

1.易於安裝:在makefile里面選擇自己需要的附加項(cuda,cudnn,opencv等)直接make即可,幾分鍾完成安裝;
2.沒有任何依賴項:整個框架都用C語言進行編寫,可以不依賴任何庫,連opencv作者都編寫了可以對其進行替代的函數;
3.結構明晰,源代碼查看、修改方便:其框架的基礎文件都在src文件夾,而定義的一些檢測、分類函數則在example文件夾,可根據需要直接對源代碼進行查看和修改;
4.友好python接口:雖然darknet使用c語言進行編寫,但是也提供了python的接口,通過python函數,能夠使用python直接對訓練好的.weight格式的模型進行調用;
5.易於移植:部署到機器本地十分簡單,且可以根據機器情況,使用cpu和gpu,特別是檢測識別任務的本地端部署。

 

二、Darknet結構

    darknet整理結構圖:

 |--\cfg
 |------coco.data
 |------darknet.cfg
 |------...
 |------yolov3.cfg
 |--\data
 |------coco.names
 |------...
 |--\examples
 |------classifier.c
 |------detector.c
 |------...
 |--\include
 |------darknet.h
 |--\python
 |------darknet.py
 |------...
 |--\scripts
 |------get_coco_dataset.sh
 |------...
 |--\src
 |------convolutional_layer.c
 |------convolutional_layer.h
 |------convolutional_kernels.cu
 |------...
 |--darknet53.conv.74
 |--LICENSE
 |--Makefile
 |--ReadMe.md
View Code

    各文件夾功能解釋:

    1.cfg文件夾內是一些模型的架構,通過該文件定義整個模型的架構

    2.data文件夾內放置了一些label文件,和一些樣例圖

    3.src文件夾內全是最底層的框架定義文件,所有層的定義等最基本的函數全部在該文件夾內

    4.examples文件夾是更為高層的一些函數,如檢測函數,識別函數等,這些函數直接調用了底層的函數,我們經常使用的就是example中的函數;

    5.include文件夾,存放頭文件的地方;

    6.python文件夾里是使用python對模型的調用方法,基本都在darknet.py中; 

    7.scripts文件夾中是一些腳本,如下載coco數據集,將voc格式的數據集轉換為訓練所需格式的腳本等

    8.除了license文件,剩下的就是Makefile文件

 

三、Darknet安裝

    1、打開Makefile文件,將需要的選項設置為1,使用GPU和CUDNN:

在這里插入圖片描述

   2、打開終端,進入到darknet文件夾根目錄,輸入make,開始編譯

   3、編譯完成后,在根目錄下,會多出一些文件夾和文件:obj文件夾中存放了編譯過程中的.o文件,另外,還生成了三個文件:可執行文件darknet.exe,靜態鏈接庫libdarknet.a和動態鏈接庫libdarknet.so。本地進行模型調用可直接使用darknet.exe,而如果要移植到其它平台,就需要用到libdarknet.so這個動態鏈接庫。不過,該動態鏈接庫只包含了src文件夾中定義的框架基礎函數,並沒有包含examples中的上層函數,所以在調用過程中需要自己去定義檢測函數。

 

四、Darknet的訓練

     1、數據准備

        將數據的groundtruth轉化為darknet需要的格式,如果你的gt為voc格式的xml,可以通過如下腳本進行轉換

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
classes = ["car"]#類別改為自己需要檢測的所有類別
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):
    in_file = open(xml_path)#與圖片對應的xml文件所在的地址
    out_file = open(txt_save_path,'w') #與此xml對應的轉換后的txt,這個txt的保存完整路徑
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')  #訪問size標簽的數據
    w = int(size.find('width').text)#讀取size標簽中寬度的數據
    h = int(size.find('height').text)#讀取size標簽中高度的數據

    for obj in root.iter('object'):
        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')
View Code

     需要自行設置xml_path和txt_save_path

從上面的代碼可以看到,對於object的位置x_min,x_max,y_min,y_max,先求得其中心點坐標center_x,center_y以及位置框的長寬width_rect,height_rect,再將這四個值分別除以長寬以將數據歸一化。

     2、*.data文件准備

     訓練的時候必須的項目有“class”,“train”,“backup”。“names”最好也設置上,方便以后調用。

     “class”表示你要檢測的類別個數,如檢測類別為4則class=4
     “backup”表示訓練過程中的緩存和保存的模型。訓練過程中,會在該路徑下生成一個后綴為.backup的文件,該文件每100個step將模型更新一遍,以防止訓練忽然終端而沒有保存模型。並且,訓練保存的模型也會存在該路徑下。默認情況下,每10000step還是多少會保存一個模型,命名為yolov3_迭代次數.weights,最終訓練完成還會保存一個yolov3_final.weights。這些模型都會保存在backup路徑下
     “names”為保存檢測object名稱的路徑,names=plate.names
     “train”為你訓練集的list路徑,如train=data/trainlist.txt,trainlist.txt中保存了所有訓練集圖像的路徑:

    /home/jim/yolov3/data/car/image/1101.jpg

    /home/jim/yolov3/data/car/image/1104.jpg

    /home/jim/yolov3/data/car/image/1134.jpg

    可通過如下命令生成文件:

        find image_path -name \*.jpg > trainlist.txt     ::image_path為你數據集的路徑

    3、*.cfg文件准備

如果要調用yolo v3,可以直接使用cfg文件夾下的yolov3.cfg,但是需要做如下幾個修改:
首先,將最上方的

# Testing
batch=1
subdivisions=1
# Training
# batch=64
# subdivisions=16
修改為

# Testing
#batch=1
#subdivisions=1
# Training
batch=64
subdivisions=16
View Code

其中batch表示batchsize,而subdivisions是為了解決想要大batchsize而顯存又不夠的情況,每次代碼只讀取batchsize/subdivisions 個圖像,如圖中設置為64/16=4,但是會將16次的結果也就是64張圖的結果,作為一個batch來統一處理; 

然后,根據自己檢測的類別,將每個[yolo](共有三個[yolo]) 下方的classes修改為自己需要檢測的類別,如果只檢測一類則classes=1
然后將每個[yolo] 上方的第一個filters的值進行修改,計算方式為(5+classes)*3,如果classes為1,則為18,修改前后的對比:

[convolutional]
size=1
stride=1
pad=1
filters=255
activation=linear

[yolo]
mask = 0,1,2
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=80
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=1

[convolutional]
size=1
stride=1
pad=1
filters=18
activation=linear

[yolo]
mask = 0,1,2
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=1
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=1
View Code

其中:random表示論文中提及的resize network來增強網絡的適應性,如果顯存足夠,最好設置為1,如果顯存不夠,也可以將其設置為0,即不進行network resizing

   4、weights文件准備

      如果你使用的是作者提供的cfg模型結構,如yolov3,那么可以到官網去下載預訓練模型來初始化模型參數,這樣可以加快收斂。

      當然,你也可以不使用預訓練模型進行訓練

   5、開始訓練

     如果使用預訓練模型則使用如下命令

     ./darknet detector train data/detect.data data/yolov3.cfg data/yolov3.weight

     否則,使用如下命令:

      ./darknet detector train data/detect.data data/yolov3.cfg

     注:分類模型使用如下命令:

      ./darknet classifier train cfg/cifar.data cfg/cifar_small.cfg (xxx.weights)

 

五、Darknet的檢測

     檢測使用如下命令:

      ./darknet detector test data/detect.data data/yolov3.cfg data/yolov3.weight

       其中./darknet為前面編譯生成的darknet.exe文件,darknet.exe首先調用example文件夾下的darknet.c,該文件中的main函數需要預定義參數,detector即為預定義參數,如下代碼:

       else if (0 == strcmp(argv[1], "detector")){ run_detector(argc, argv);}

  由‘detector’轉而調用run_detector,run_detector存在於example文件夾下的detector.c中,再根據預定義參數,確定是調用檢測函數,訓練函數還是驗證函數:

if(0==strcmp(argv[2], "test")) test_detector(datacfg, cfg, weights, filename, thresh, hier_thresh, outfile, fullscreen);
else if(0==strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear);
else if(0==strcmp(argv[2], "valid")) validate_detector(datacfg, cfg, weights, outfile);
else if(0==strcmp(argv[2], "valid2")) validate_detector_flip(datacfg, cfg, weights, outfile);
else if(0==strcmp(argv[2], "recall")) validate_detector_recall(cfg, weights);
else if(0==strcmp(argv[2], "demo"))

   其中test表示檢測,train表示訓練,valid表示驗證,recall表示測試其召回率,demo為調用攝像頭的實時檢測,命令最后的三個參數表示運行需要的文件,.data文件記錄了模型檢測的類別,類名文件等,如下:

classes= 1
train = /home/jim/yolov3/data/car/train.list
names = data/plate/car.names
backup = /home/jim/yolov3/data/car/models

class表示檢測類別,train為訓練中需要用到的訓練數據的列表,valid為驗證集列表,names為檢測類別的名稱,backup為訓練中用到的存放訓練模型的路徑

.cfg文件定義了模型結構,而.weight文件為調用的模型權重文件。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM