1.yolo9000训练时,loss分为两种,遇到分类数据时只传递分类损失,不传bbox损失。遇到检测数据时,传递全部损失。
2.检测数据预处理过程跟yolov2一样
3.分类数据预处理过程跟检测数据类似,label的类别不变,只是bbox的框坐标全部设置为0
一.分类数据预处理(Imagenet)
准备9000类label文件9k.labels和imagenet_9k_list.txt
# coding=utf-8
# 使用说明
#将该文件放在/home/research/disk1/imagenet/ILSVRC2015/目录下
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
def get_dirs(path):
dirs_train = []
dirs_2015 = os.listdir('Data/CLS-LOC/train/')
dir38 = open(path+'9k.labels')
for line in dir38:
temp = line[:-1]
if temp in dirs_2015:
dirs_train.append(temp)
else:
continue
dir38.close()
'''
for dir_2015 in dirs_2015:
dirs_train.append(dir_2015)
'''
return dirs_train
def get_classes_and_index(path):
D = {}
f_name = open(path+'imagenet_9k_list.txt')
for line in f_name:
line_name = line.strip('\n').split(',')
#print(line_name)
temp_name = line_name[1]
temp_label = line_name[0]
D[temp_name] = temp_label
f_name.close()
return D
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_dir):
#print(image_dir)
objdir = os.listdir('Data/CLS-LOC/train/'+image_dir)
obj_num = 0
for idir in objdir:
#print(idir)
obj_num+=1
if obj_num == 1:
if not os.path.exists('labels/CLS-LOC/train/%s' %(image_dir)):
os.makedirs('labels/CLS-LOC/train/%s' %(image_dir))
out_file = open('labels/CLS-LOC/train/%s/%s.txt' % (image_dir,idir.split('.')[0]),'w')
cls_id = classes[image_dir]
out_file.write(str(cls_id) +' 0.0 0.0 0.0 0.0'+'\n')
if obj_num > 0:
list_file.write('%s/JPEGImages/CLS-LOC/train/%s/%s\n' % (wd, image_dir, idir))
def IsSubString(SubStrList, Str):
flag = True
for substr in SubStrList:
if not (substr in Str):
flag = False
return flag
def GetFileList(FindPath, FlagStr=[]):
import os
FileList = []
FileNames = os.listdir(FindPath)
if (len(FileNames) > 0):
for fn in FileNames:
if (len(FlagStr) > 0):
#if (IsSubString(FlagStr, fn)):
FileList.append(fn[:-4])
else:
FileList.append(fn)
if (len(FileList) > 0):
FileList.sort()
return FileList
classes = get_classes_and_index('/home/research/disk2/wangshun/yolo9000/darknet/data/')
#print(classes)
dirs = get_dirs('/home/research/disk2/wangshun/yolo9000/darknet/data/')
#print(dirs)
print(len(dirs))
wd = getcwd()
if not os.path.exists('filelist/'):
os.mkdir('filelist')
list_file = open('filelist/%s_9k.txt' % ('imagenet_label'),'w')
for image_dir in dirs:
if not os.path.exists('Data/CLS-LOC/train/' + image_dir):
print("Data/CLS-LOC/train/%s dir not exist" % image_dir)
continue
else:
'''
image_ids = GetFileList('Annotations/CLS-LOC/train/' + image_dir, ['xml'])
for i in image_ids:
#print(i)
'''
convert_annotation(image_dir)
list_file.close()
二.检测数据预处理(coco)
先准备coco_list.txt文件
# coding=utf-8
# 使用说明
# 需要先安装coco tools
# git clone https://github.com/pdollar/coco.git
# cd coco/PythonAPI
# make install
import os
from pycocotools.coco import COCO
def convert(size, box):
dw = 1./size[0]
dh = 1./size[1]
x = box[0] + box[2]/2.0
y = box[1] + box[3]/2.0
w = box[2]
h = box[3]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
def get_classes_and_index(path):
D = {}
f = open(path)
for line in f:
temp = line.rstrip().split(',', 2)
#print("temp[0]:"+temp[0]+"\n")
#print("temp[1]:" + temp[1]+"\n")
D[temp[1]] = temp[0]
return D
classes = ['human face','dog','cat']
dataDir = '/home/research/disk2/wangshun/yolo9000/darknet/coco'
dataType = 'train2014'
#dataTypeval='val2014'
annFile = '%s/annotations/instances_%s.json' % (dataDir, dataType)
#annFileval = '%s/annotations/instances_%s.json' % (dataDir, dataTypeval)
classes = get_classes_and_index('/home/research/disk2/wangshun/yolo9000/darknet/data/coco_9k_list.txt')
coco = COCO(annFile)
list_file = open('%s/filelist/coco_%s.txt' % (dataDir,dataType), 'w')
#list_file_val = open('%s/filelist/val2014/%s.txt' % (dataDir,dataTypeval), 'w')
imgIds = coco.getImgIds()
catIds = coco.getCatIds()
for imgId in imgIds:
objCount = 0
#print('imgId :%s'%imgId)
Img = coco.loadImgs(imgId)[0]
#print('Img :%s' % Img)
filename = Img['file_name']
width = Img['width']
height = Img['height']
#print('filename :%s, width :%s ,height :%s' % (filename,width,height))
annIds = coco.getAnnIds(imgIds=imgId, catIds=catIds, iscrowd=None)
#print('annIds :%s' % annIds)
if not os.path.exists('%s/labels/train2014/' %(dataDir)):
os.makedirs('labels/train2014/')
out_file = open('%s/labels/train2014/%s.txt' % (dataDir, filename[:-4]), 'w')
for annId in annIds:
anns = coco.loadAnns(annId)[0]
catId = anns['category_id']
cat = coco.loadCats(catId)[0]['name']
#print 'anns :%s' % anns
#print 'catId :%s , cat :%s' % (catId,cat)
#if cat in classes:
if cat in classes:
objCount = objCount + 1
#cls_id = classes[cat]
cls_id = classes.index(cat)
box = anns['bbox']
size = [width,height]
bb=convert(size, box)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
list_file.write('%s/images/%s/%s\n' % (dataDir, dataType, filename))
out_file.close()
#if objCount > 0:
list_file.close()
将coco_train2014.txt和imagenet_label_9k.txt放在同一个文件下
cat imagenet_label_9k.txt coco_train2014.txt > yolo9k_train.txt
三.修改darknet前向传播层代码
修改darknet/src/region_layer.c中的forward_region_layer
注释掉
四.修改yolo9000.cfg
注释掉最后的map
修改yolo9000.data文件
五.训练
./darknet detector train cfg/yolo9000.data cfg/yolo9000.cfg 预训练网络 -gpus 0
当算法遇到分类数据时只有Class和No Obj计算值,其他为-nan。因为count为0