工具:labelimg、MobaXterm
1.標注自己的數據集。用labelimg進行標注,保存后會生成與所標注圖片文件名相同的xml文件,如圖。我們標注的是井蓋和路邊欄,名稱分了NoManholeCover、ManholeCover、WarningStick共3類標簽名
2.下載yolov3項目工程。按照YoLo官網下載
- git clone https://github.com/pjreddie/darknet
- cd darknet
- make
3.修改Makefile文件(文件就在下載的darknet文件夾內)
vi Makefile #打開文件
- GPU=1#使用GPU訓練,其他的沒有用,所以沒有置為1,可根據自己的需要調整
- CUDNN=0
- OPENCV=0
- OPENMP=0
- DEBUG=0
make #保存並退出后,進行make才可生效,如果出現錯誤,自行百度。
3.准備數據集。在darknet/scripts文件夾下創建文件夾VOCdevkit(因為scripts文件夾下有voc_label.py文件,它的作用下面會說,下面創建的文件也跟它有關),根據下圖在VOCdevkit文件夾下創建文件,並放入相應的數據
- VOCdevkit
- ——VOC2007 #文件夾的年份可以自己取,但是要與你其他文件年份一致,看下一步就明白了
- ————Annotations #放入所有的xml文件
- ————ImageSets
- ——————Main #放入train.txt,val.txt文件
- ————JPEGImages #放入所有的圖片文件
- Main中的文件分別表示test.txt是測試集,train.txt是訓練集,val.txt是驗證集,trainval.txt是訓練和驗證集,反正我只建了兩個
注意:Linux環境下Annotations和IPEGImages中的文件權限一定是-rw-r--r--,不然會影響模型准確率!!!
其中Main中的txt文件是要寫文件名,比如train.txt里寫的是用來訓練的圖片的文件名(不包含后綴,只是文件名哦!!!),這個文件可以找代碼生成(下面的python代碼可以用),代碼的話看懂他的作用,特別的文件的路徑之類的,根據自己的情況修改下,就可以用
import os
import random
train_percent = 0.50
xmlfilepath = 'Annotations'
txtsavepath = 'ImageSets\Main'
total_xml = os.listdir(xmlfilepath)
num=len(total_xml)
list=range(num)
tr=int(num*train_percent)
train=random.sample(list,tr)
ftrain = open('ImageSets/Main/train.txt', 'w')
fval = open('ImageSets/Main/val.txt', 'w')
for i in list:
name=total_xml[i][:-4]+'\n'
if i in train:
ftrain.write(name)
else:
fval.write(name)
ftrain.close()
fval.close()
print ("finished")
5.修改voc_label.py,這個文件就是根據Main中txt里的文件名,生成相應的txt,里面存放的是它們的路徑
- sets=[('2007', 'train'), ('2007', 'val')] #這里要與Main中的txt文件一致
- classes = ["ManholeCover","NoManholeCover","WarningStick"] #你所標注的表簽名,第一步中已經說過
- #os.system("cat 2007_train.txt 2007_val.txt > train.txt") #文件最后一句,意思是要將生成的文件合並,所以很據需要修改,這里的年份都是一致的,簡單理解下代碼應該會懂,不要盲目修改
python voc_label.py #保存后運行
運行后會生成2007_train.txt、2007_val.txt如圖
6.下載Imagenet上預先訓練的權重,放到scripts目錄下
wget https://pjreddie.com/media/files/darknet53.conv.74
7.修改cfg/voc.data,重命名為voc-cover.data
- classes= 3#classes為訓練樣本集的類別總數,第一步中說了我分了5類標簽
- train = /darknet/scripts/2007_train.txt #train的路徑為訓練樣本集所在的路徑,上一步中生成
- valid = /darknet/scripts/2007_val.txt #valid的路徑為驗證樣本集所在的路徑,上一步中生成
- names = data/voc-cover.names #names的路徑為data/voc-cover.names文件所在的路徑
- backup = backup
8.修改data/voc.names,重命名為voc-cover.names
- NoManholeCover
- ManholeCover
- WarningStick
- #修改為自己樣本集的標簽名即第一步中標注的標簽名
9.修改cfg/yolov3-voc-cover.cfg
- [net]
- # Testing
- # batch=1 #這里的batch跟subdivisions原來不是注釋掉的,但是訓練后沒成功,有的blog上說為1的時候太小難以收斂,但是不知道下面訓練模式的 batch=64 subdivisions=8 會不會覆蓋掉,總之注釋掉后就成功了,不過這個腳本不是很明白,還來不及驗證
- # subdivisions=1
- # Training
- batch=64
- subdivisions=8
- ......
- [convolutional]
- size=1
- stride=1
- pad=1
- filters=24#---------------修改為3*(classes+5)即3*(3+5)=24
- activation=linear
- [yolo]
- mask = 6,7,8
- anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
- classes=3#---------------修改為標簽類別個數,5類
- num=9
- jitter=.3
- ignore_thresh = .5
- truth_thresh = 1
- random=0#1,如果顯存很小,將random設置為0,關閉多尺度訓練;(轉自別的blog,還不太明白)
- ......
- [convolutional]
- size=1
- stride=1
- pad=1
- filters=24#---------------修改同上
- activation=linear
- [yolo]
- mask = 3,4,5
- anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
- classes=3#---------------修改同上
- num=9
- jitter=.3
- ignore_thresh = .5
- truth_thresh = 1
- random=0
- ......
- [convolutional]
- size=1
- stride=1
- pad=1
- filters=24#---------------修改同上
- 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=3#---------------修改同上
- num=9
- jitter=.3
- ignore_thresh = .5
- truth_thresh = 1
- random=1
10.開始訓練
- ./darknet detector train cfg/voc-cover.data cfg/yolov3-voc-cover.cfg scripts/darknet53.conv.74 -gpus 0,1
- #注意文件路徑
- 訓練默認的是前1000輪每100輪保存一次模型,1000輪后每10000輪保存一次模型。可以修改examples/detector.c文件的138行。修改完重新編譯一下,在darknet目錄下執行make。
11.測試識別。訓練后會在backup文件夾下生成權重文件,利用生成的權重文件進行測試
./darknet detector test cfg/voc-cover.data cfg/yolov3-voc-cover.cfg backup/yolov3-voc_600.weights data/210.jpg
以上對於一些文件的理解也是多次失敗的收獲,可能並不全對,有誤請指正,遇到問題也可以交流。
DarkNet的Python接口:
注意使用Python測試的時候必須要有GPU和安裝好cuda驅動,因為作者提供的Python的接口只有GPU調用函數
作者給出的使用的Demo為:
```python
# Stupid python path shit.
# Instead just add darknet.py to somewhere in your python path
# OK actually that might not be a great idea, idk, work in progress
# Use at your own risk. or don't, i don't care
import sys, os
sys.path.append(os.path.join(os.getcwd(),'python/'))
import darknet as dn
import pdb
dn.set_gpu(0)
net = dn.load_net("cfg/yolo-thor.cfg", "/home/pjreddie/backup/yolo-thor_final.weights", 0)
meta = dn.load_meta("cfg/thor.data")
r = dn.detect(net, meta, "data/bedroom.jpg")
print r
# And then down here you could detect a lot more images like:
r = dn.detect(net, meta, "data/eagle.jpg")
print r
r = dn.detect(net, meta, "data/giraffe.jpg")
print r
r = dn.detect(net, meta, "data/horses.jpg")
print r
r = dn.detect(net, meta, "data/person.jpg")
print r
```
我們不難看出除了系統模塊之外,只調用了darknet.py模塊,存放在工程的python目錄里。
但darknet.py中有一些路徑是軟地址要改一下(在47行中,仿照着注釋的格式):
```python
#lib = CDLL("/home/lishukang/darknet/libdarknet.so", RTLD_GLOBAL)
lib = CDLL("libdarknet.so", RTLD_GLOBAL)
```
但這個模塊是基於Python2編寫,如果直接使用Python2運行的話還會有一些包存在路徑問題,哪我們不如將他稍微修改一下:
在154行,即最后一行中,print需要加上括號
```python
print (r)
```
這樣,我們在工程目錄下進行模塊導入就沒有任何問題了。
我們仿照着把配置文件路徑和要測試的圖片地址改好就可以了。比如我的:
```python
In [10]: dn = set_gpu(0)
...: net = dn.load_net("cfg/yolov3.cfg", "/home/lishukang/darknet/backup/yolov3_400.weights", 0)
...: meta = dn.load_meta("cfg/number.data")
...: r = dn.detect(net, meta, "zhebing/pic/20171105_636454947681503257_P.jpg")
...: print (r)
```
就可以顯示出測試圖像啦。
