darknet命令解釋


 

https://blog.csdn.net/u010122972/article/details/83541978

  • 優點
    Darknet是一個比較小眾的深度學習框架,沒有社區,主要靠作者團隊維護,所以推廣較弱,用的人不多。而且由於維護人員有限,功能也不如tensorflow等框架那么強大,但是該框架還是有一些獨有的優點:
    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源代碼下載解壓后文件夾的分布情況:
    darknet文件夾
    1.cfg文件夾內是一些模型的架構,每個cfg文件類似與caffe的prototxt文件,通過該文件定義的整個模型的架構
    2.data文件夾內放置了一些label文件,如coco9k的類別名等,和一些樣例圖(該文件夾主要為演示用,或者是直接訓練coco等對應數據集時有用,如果要用自己的數據自行訓練,該文件夾內的東西都不是我們需要的)
    3.src文件夾內全是最底層的框架定義文件,所有層的定義等最基本的函數全部在該文件夾內,可以理解為該文件夾就是框架的源碼;
    4.examples文件夾是更為高層的一些函數,如檢測函數,識別函數等,這些函數直接調用了底層的函數,我們經常使用的就是example中的函數;
    5.include文件夾,顧名思義,存放頭文件的地方;
    6.python文件夾里是使用python對模型的調用方法,基本都在darknet.py中。當然,要實現python的調用,還需要用到darknet的動態庫libdarknet.so,這個動態庫稍后再介紹;
    7.scripts文件夾中是一些腳本,如下載coco數據集,將voc格式的數據集轉換為訓練所需格式的腳本等
    8.除了license文件,剩下的就是Makefile文件,如下圖,在問價開頭有一些選項,把你需要使用的選項設為1即可
    Makefile

  • 安裝
    1.點開Makefile,將需要的選項設置為1,如圖,使用GPU和CUDNN
    在這里插入圖片描述
    2.打開終端,進入到darknet文件夾根目錄,輸入make,開始編譯
    3.幾分鍾后編譯完成,文件夾中會多出一些文件夾和文件,obj文件中存放了編譯過程中的.o文件,其他的幾個空文件夾也不需要太大關注,這里最重要的就是三個:名為darknet的exe文件,名為libdarknet.a的靜態鏈接庫和名為libdarknet.so的動態鏈接庫。如果直接在本地進行模型調用嘗試,可以直接運行darknet這個exe文件,如果需要移植調用,則需要用到libdarknet.so這個動態鏈接庫,這個動態鏈接庫中只包含了src文件夾中定義的框架基礎函數,沒有包含examples中的高層函數,所以調用過程中需要自己去定義檢測函數

  • 檢測
    運行如下代碼

 

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

 

  • 1

 

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

 

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

 

  • 1
  • 2

 

由‘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")) 

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

其中test表示檢測,train表示訓練,valid表示驗證,recall表示測試其召回率,demo為調用攝像頭的實時檢測

 

命令最后的三個參數表示運行需要的文件,.data文件記錄了模型檢測的類別,類名文件等,如下:

 

classes= 1
train  = /media/seven/yolov3/data/plate2/train.list
#valid = data/coco_val_5k.list
names = data/plate/plate.names
backup = /media/seven/yolov3/data/plate2/models
#eval=coco

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

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

 

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

 

運行以上命令,會在終端得到如下提示:

 

Enter Image Path: 

 

  • 1

 

直接在終端輸入圖像的路徑,就可以對該圖像進行檢測,並在darknet的根目錄生成名為predictions.png的檢測結果,如圖:
在這里插入圖片描述

 

  • 分類
    分類和檢測類似,調用命令如下:

 

./darknet classifier predict classify.data classify.cfg classify.weights

 

  • 1

 

與檢測同理,./darknet運行darknet.exe,並調用example中的darknet.c文件,通過classfier調用classifier.c中的run_classifier函數:

 

else if (0 == strcmp(argv[1], "classifier")){
        run_classifier(argc, argv);

 

  • 1
  • 2

 

並通過predict進而調用predict_classifier函數:

 

 if(0==strcmp(argv[2], "predict")) predict_classifier(data, cfg, weights, filename, top);
 else if(0==strcmp(argv[2], "fout")) file_output_classifier(data, cfg, weights, filename);
 else if(0==strcmp(argv[2], "try")) try_classifier(data, cfg, weights, filename, atoi(layer_s));
 else if(0==strcmp(argv[2], "train")) train_classifier(data, cfg, weights, gpus, ngpus, clear);
 else if(0==strcmp(argv[2], "demo")) demo_classifier(data, cfg, weights, cam_index, filename);
 ...

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

而classify.data,classify.cfg,classify.weights分別表示分類對應的.data文件,模型定義cfg文件和模型權重.weights文件。

 

  • 訓練

 

  1. 檢測模型的訓練:
    (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 = ["plate"]#類別改為自己需要檢測的所有類別
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')   #訪問boundbox標簽的數據並進行處理,都按yolo自帶的代碼來,沒有改動
        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')

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

 

上面的代碼需要自行設置xml_path和txt_save_path
從上面的代碼可以看到,對於object的位置x_min,x_max,y_min,y_max,先求得其中心點坐標center_x,center_y以及位置框的長寬width_rect,height_rect,再將這四個值分別除以長寬以將數據歸一化,如果不是voc格式的數據可以按照這樣的思路進行類似處理
如果是voc格式的數據可以參照我之前的博客進行一步一步的處理darknet用自己的數據進行訓練
按照上面的流程,每張圖像都生成了對應的txt文件來保存其歸一化后的位置信息,如下圖對應生成的txt如下:
在這里插入圖片描述

 

0 0.250925925926 0.576388888889 0.1 0.0263888888889
0 0.485185185185 0.578125 0.0685185185185 0.0201388888889

 

  • 1
  • 2

 

圖中共有車牌兩個,每行保存一個車牌的信息,第一個0表示檢測object的label,因為我只有一類,所以都是0
后面的四位即為歸一化后的中心點坐標和位置框的長和寬
最后將圖像和對應txt的文件名統一,並拷貝到同一個文件夾(a.jpg對應的txt為a.txt),如圖:

 

在這里插入圖片描述
注意,txt和對應jpg文件的名稱除了最后.jpg,.txt的后綴不一樣,其他的必須完全一樣,且需要保存在同一文件夾,訓練過程中會直接將a.jpg的名稱替換為a.txt來尋找該圖像對應的gt。對應的gt文件也不一定必須是txt格式,如果不是txt格式可以去源碼中將這部分代碼進行修改,將.jpg替換為你需要的格式后綴

 

(2).data文件准備
前面已經貼過.data的圖,訓練的時候必須的項目有“class”,“train”,“backup”。“names”最好也設置上,方便以后調用。
“class”表示你要檢測的類別個數,如檢測類別為20則class=20
“backup”表示訓練過程中的緩存和保存的模型。訓練過程中,會在該路徑下生成一個后綴為.backup的文件,該文件每100個step將模型更新一遍,以防止訓練忽然終端而沒有保存模型。並且,訓練保存的模型也會存在該路徑下。默認情況下,每10000step還是多少(記不太清了,我自己修改過)會保存一個模型,命名為yolov3_迭代次數.weights,最終訓練完成還會保存一個yolov3_final.weights。這些模型都會保存在backup路徑下
“names”為保存檢測object名稱的路徑,names=plate.names
“train”為你訓練集的list路徑,如train=data/trainlist.txt,trainlist.txt中保存了所有訓練集圖像的路徑,如下圖
在這里插入圖片描述
可以通過如下命令直接生成該文件:

 

find image_path -name \*.jpg > trainlist.txt

 

  • 1

 

image_path為你數據集的路徑

 

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

 

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

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

修改為

 

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

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

 

其中batch表示batchsize,而subdivisions是為了解決想要大batchsize而顯存又不夠的情況,每次代碼只讀取batchsize/subdivisions 個圖像,如圖中設置為64/16=4,但是會將16次的結果也就是64張圖的結果,作為一個batch來統一處理
(調用的時候再將testing部分解除注釋,並將train部分注釋)

 

然后,根據自己檢測的類別,將每個[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

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

 

[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

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

 

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

 

(4)weights文件准備
如果你使用的是作者提供的cfg模型結構,如yolov3,那么可以到其官網去下載預訓練模型來初始化模型參數,這樣可以加快收斂。當然,你也可以不使用預訓練模型進行訓練

 

(5)開始訓練
如果使用預訓練模型則使用如下命令

 

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

 

  • 1

 

否則,使用

 

./darknet detectortrain data/detect.data data/yolov3.cfg

 

  • 1

 

命令類似與之前檢測的調用命令,只是將test變為了train

 

  1. 分類模型的訓練
    (1)數據准備
    和檢測不一樣,分類的gt只需要一個label即可,不再需要位置框的信息,所以不再需要單獨的txt文件來保存gt,而是直接將label在圖像名稱上進行體現。所以需要對圖像名稱進行重命名,命名規則為:
    (圖片序號)_(標簽).(圖片格式),如1_numzero.jpg
    需要注意的是:
    1.label不區分大小寫,即 numzero和NumZero是一樣的效果
    2.label之間不能有包含關系,如ji和jin,不能出現這樣的形式,可改為ji1和jin

 

(2).data文件准備
和檢測類似:

 

classes=65
train  = data/char/train.list
labels = data/char/labels.txt
backup = backup/
top=2

 

  • 1
  • 2
  • 3
  • 4
  • 5

 

其中top不是在訓練中使用,而是在分類調用時使用,表示輸出Top個最高的可能值

 

(3).cfg文件准備
可以從cfg文件夾中選擇,也可以自行定義

 

(4).weights文件
同上面的檢測

 

(5)開始訓練
使用命令:

 

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

 


免責聲明!

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



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