基于imagenet和coco,voc联合数据的yolo9000训练

1.yolo9000训练时,loss分为两种,遇到分类数据时只传递分类损失,不传bbox损失。遇到检测数据时,传递全部损失。

2.检测数据预处理过程跟yolov2一样

3.分类数据预处理过程跟检测数据类似,label的类别不变,只是bbox的框坐标全部设置为0


一.分类数据预处理(Imagenet)

准备9000类label文件9k.labels和imagenet_9k_list.txt

基于imagenet和coco,voc联合数据的yolo9000训练_第1张图片

基于imagenet和coco,voc联合数据的yolo9000训练_第2张图片

# 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()

制作好label标签文件并生成filelist/imagenet_label_9k.txt

二.检测数据预处理(coco)

先准备coco_list.txt文件

基于imagenet和coco,voc联合数据的yolo9000训练_第3张图片

# 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()

生成filelist/coco_train2014.txt

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

注释掉

//if(l.output[obj_index] < .3) l.delta[obj_index] = l.object_scale * (.3 - l.output[obj_index]);
//else l.delta[obj_index] = 0;
//l.delta[obj_index] = 0;

四.修改yolo9000.cfg

注释掉最后的map

基于imagenet和coco,voc联合数据的yolo9000训练_第4张图片

修改yolo9000.data文件

基于imagenet和coco,voc联合数据的yolo9000训练_第5张图片

五.训练

./darknet detector train cfg/yolo9000.data cfg/yolo9000.cfg 预训练网络 -gpus 0

注意:最好将检测数据和分类数据进行平衡为1:1以下,论文中是1:4。结果发现分类效果很好,但是回归bbox效果较差。我在做实验时将比例设为1:0.8

当算法遇到分类数据时只有Class和No Obj计算值,其他为-nan。因为count为0

你可能感兴趣的:(yolo学习)