Introduction
As we all know,YOLO是一个one stage detector,其速度特别的快,且精度也较好。然而作者在实现YOLO时,硬核的使用C++编写了一个框架:Darknet,其除了包含Darknet、YOLO之外,还实现了一些基本的模型,如ResNet、DenseNet,RNN等,也包含了COCO、PASCAL VOC数据集的使用。更重要的是,Darknet依赖项少,可以通过编译后直接使用。
However!Darknet是C++编写的,与目前大多数框架都使用Python无法通用,虽然使用Darknet也很简单。。。
在此我将把在使用Darknet过程中遇到的一些问题记录下来。
自定义数据集
官方给出的数据集包含VOC和COCO,由于COCO数据集太庞大,目前仅测试过VOC数据集。
对于VOC数据集,其基本格式为:
![](https://img.haomeiwen.com/i3247424/151bc8de35bf2547.png)
要注意Annotaions包含每张影像的标注xml格式,JPEGImages包含了所有影像,ImageSets则记录了train、val、test的影像名称。
在使用Darknet提供的
voc_label.py
脚本时,其会在JPEGImages同级目录生成label
文件夹,并为每一张影像生成一个txt
文件,其格式为:
<object-class> <x> <y> <width> <height>
<object-class> <x> <y> <width> <height>
...
<object-class> <x> <y> <width> <height>
也就是将VOC的annotaion格式转换成Darknet的格式。
同样的在自定义数据集时,有一些问题要注意。
首先是数据目录的组织。由于Darknet支持VOC的数据格式,因此在定义数据集时,应至少包含JPEGImages
和labels
两个同级文件夹,在文件夹下,可以定义train
、val
等对应的子文件夹。如下图所示:
![](https://img.haomeiwen.com/i3247424/8cdb24eb6507bf8e.png)
在训练时,关于数据集其只需要一个配置文件如
voc.data
,格式如下:
classes= 20
train = data/2007_train.txt
valid = data/2007_val.txt
names = data/voc.names
backup = backup
也就是说其只需要train和val影像的位置,然后会自动的到与JPEGImages
同级的labels
寻找标签,如训练影像的路径为your_dataset/JPEGImages/train/demo1.jpg
,那么它会到your_dataset/labels/train/demo1.txt
寻找标签。
其次是标签的信息。在记录影像annotaion的txt里,其object-class
是一个数字,其对应表要记录在一个文件中(如voc.nems),内容大致如下:
aeroplane
bicycle
bird
boat
bottle
bus
car
cat
chair
cow
diningtable
dog
horse
motorbike
person
pottedplant
sheep
sofa
train
tvmonitor
即每行记录一个类别,依次从0
到n
。
测试图片
当模型训练完成后,需要测试图片时,官方写的是可以用命令:./darknet detect cfg/yolov3.cfg weights/yolov3.weights data/dog.jpg
来测试,然后解释到:./darknet detect
中的detect是detector test 的简写。
但是请注意!这里的简写,其实是简写了detect test cfg/coco.data
,而在测试时,我们需要用到coco.names
,里面记录了从数字与类别的对应关系。
如果我们使用的是VOC数据集,或者是其他自定义数据集,一定要使用./darknet detector test cfg/yourdata.data cfg/your_confg.cfg yourimage.jpg
这样的格式,不能将.data
文件遗漏,否则将会采用默认的coco数据集标签。
自定义BDD100K数据集
BDD100K是一个新的自动驾驶数据集,是一个数据量更大,更广泛的数据集。在此我们将使用Darknet的YOLOv3模型训练BDD100k数据的过程记录下来。
-
文件目录格式。由于Darknet十分依赖VOC数据集的格式,因此我们在定义文件目录时可以这样:
BDD100k原始数据组织格式
适应Darknet的BDD100K数据组织格式
-
将BDD100K的annotations转换成Darknet的格式。
import os
import json
classes = ["car","person"]
classes_index = {"car":0,"person":1}
#convert absolute box to relative box
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)
#convert json annotation to darknet's format txt
def convert_json(in_file_path,out_file_path):
with open(in_file_path) as f_in:
info = json.load(f_in)
objs = info['frames'][0]['objects']
for obj in objs:
if obj['category'] in classes:
class_index = classes_index[obj['category']]
bbox = convert((1280,720),[float(obj['box2d']['x1']),float(obj['box2d']['x2']),float(obj['box2d']['y1']),float(obj['box2d']['y2'])])
with open(out_file_path,'w') as f_out:
f_out.write(str(class_index)+' '+str(bbox[0])+' '+str(bbox[1])+' '+str(bbox[2])+' '+str(bbox[3])+'\n')
return True
else:
return False
base_path = os.path.join(os.getcwd(),'bdd100k')
raw_label_path = os.path.join(base_path,'raw_labels')
label_path = os.path.join(base_path,'labels')
train_label_list = os.listdir(raw_label_path+'/train')
with open(base_path+'/bdd100k_train.txt','w') as f:
for (i,label) in enumerate(train_label_list):
has_obj = convert_json(raw_label_path+'/train/'+label,label_path+'/train/'+label.split('.')[0]+'.txt')
if has_obj == True:
f.write(base_path+'/JPEGImages/'+label.split('.')[0]+'.jpg\n')
val_label_list = os.listdir(raw_label_path+'/val')
with open(base_path+'/bdd100k_val.txt','w') as f:
for (i,label) in enumerate(val_label_list):
has_obj = convert_json(raw_label_path+'/val/'+label,label_path+'/val/'+label.split('.')[0]+'.txt')
if has_obj == True:
f.write(base_path+'/JPEGImages/'+label.split('.')[0]+'.jpg\n')
- bdd100k.names文件记录训练数据集的类别,每行代表一个类别
car
person
- bdd100k.data记录训练验证数据的信息
classes= 2
train = data/bdd100k_train.txt
valid = data/bdd100k_val.txt
names = data/bdd100k/bdd100k_car_person.names
backup = backup
- 修改yolo模型。只需要在三个yolo层上,将上一个卷积层的个数改为
,将yolo层的
num_class
改为你的类别数。
![](https://img.haomeiwen.com/i3247424/c9c1a3bcd5f7f2ac.png)
- 训练。
./darknet detector train cfg/bdd100k.data cfg/yolov3-bdd100k.cfg weights/darknet53.conv.74 -gpus 1,2
- 测试。
./darknet detector test cfg/bdd100k.data cfg/yolov3-bdd100k.cfg backup/yolov3-bdd100k_final.weights data/your_test_img.jpg
网友评论