YOLO目标检测
Train
训练自己的数据时需要修改几个文件,也可以自己新建。
列表如下:
data/voc.names
cfg/voc.date
第一步:
下载预训练权重,放在darknet文件夹下
wget https://pjreddie.com/media/files/darknet53.conv.74
第二步:
如果你想训练其他类别的目标,可以参考着自己新建一个.names和.data文件。这里以voc训练进行讲解。当然可以参考官网的过程。这里主要以自己数据训练讲解。
.names文件中是物体的类别,voc中有20类,可以修改成自己需要的类别。
.data文件中只要是训练集和测试集的路径,以及生成的权重文件,如下:
1 classes= 20 #修改成类别
2 train = <path-to-voc>/train.txt #修改成你的训练集的路径
3 valid = <path-to-voc>test.txt #修改成你的测试集的路径
4 names = data/voc.names #修改成你的类别名称
5 backup = backup #生成权重保存的地址
第三步:
数据和标签的生成
数据:生成train.txt文件和test.txt文件
在draknet文件夹下scripts/voc_label.py文件,这个是针对voc数据集的所以我们要进行相应的修改。
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=['train', 'val', 'test']
classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]
def convert(size, box):
dw = 1./(size[0])
dh = 1./(size[1])
x = (box[0] + box[1])/2.0 - 1
y = (box[2] + box[3])/2.0 - 1
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('./Annotations/%s.xml'%(image_id))
out_file = open('labels/%s.txt'%( image_id), 'w')
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'):
difficult = obj.find('difficult').text
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')
for image_set in sets:
if not os.path.exists('labels/'):
os.makedirs('labels/')
image_ids = open('./Main/%s.txt'%(image_set)).read().strip().split()
list_file = open('%s.txt'%( image_set), 'w')
for image_id in image_ids:
list_file.write('./JPEGImages/%s.jpg\n'%(image_id))
convert_annotation(image_id)
list_file.close()
其中主要是去除了year这个变量。
在文件中的Main文件夹下主要存放三个文件tain.txt,val.txt,test.txt,他们是训练集测试集验证集的图片的文件名,可以根据自己的需要划分。程序运行完会生成labels文件夹,里边存放的是训练的label。
Annotations下是xml的标签
JPEGImages下是图片
第三步(非xml文件):
对于非xml文件的数据,主要生成训练标签和训练集和测试集路径即可。
训练集路径:为所有文件的一个路径列表,测试集路径也是如此。
标签:txt文本,以图片名字命名,内容为label x y w h(此处的都为相对坐标)
1、训练集路径列表生成(测试集类似)
import os
imagepath = './data3/' #''你的图片路径'
tt= open('train.txt','w')
for i in os.listdir(imagepath):
print(i)
line = imagepath + i +'\n'
tt.write(line)
tt.close()
2、训练集标签生成(测试集类似)
(1)如果你的格式是:filename label x y w h
读取文件,拆分,写入多个文件。
(2)如果是每个图片对应一个txt且格式为 label x y w h,只需要图片名字和txt名字一致即可,训练是将txt和图片放在一个文件夹下。
第四步:
./darknet detector train cfg/voc.data cfg/yolov3.cfg darknet53.conv.74
cfg/voc.data #数据
cfg/yolov3v3.cfg #网络结构
darknet53.conv.74 #预训练权重
如果出现全部是这种情况:
Region 94 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000004, .5R: -nan, .75R: -nan, count: 0
Region 106 Avg IOU: -nan, Class: -nan, Obj: -nan, No Obj: 0.000001, .5R: -nan, .75R: -nan, count: 0
将cfg/yolov3v3.cfg中的testing部分注释掉
[net]
# Testing
# batch=1
# subdivisions=1
# Training
batch=64
subdivisions=16