Yolov3+VisDrone2020训练数据集
在前期准备的时候可以对比一下我文章中的修改的地方
前期准备参考:
改动的地方:
参考1, 在linux环境下转换:
1.路径都修改成绝对路径
rename.py
1 # -*- coding: utf-8 -*- 2 """ 3 Created on Thu May 9 18:02:02 2019 4 5 @author: qnh12 6 """ 7 8 9 # -*- coding: utf-8 -*- 10 11 import os 12 13 #path = "C:\\Users\\syx\\Desktop\\train\\images" #根据自己需要修改,转化完image转化annotations 14 path = "/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/annotations" 15 16 filelist = os.listdir(path) #该文件夹下所有的文件(包括文件夹) 17 18 count=1 19 20 for file in filelist: 21 22 print(file) 23 24 for file in filelist: #遍历所有文件 25 26 Olddir=os.path.join(path,file) #原来的文件路径 27 28 if os.path.isdir(Olddir): #如果是文件夹则跳过 29 30 continue 31 32 filename=os.path.splitext(file)[0] #文件名 33 34 filetype=os.path.splitext(file)[1] #文件扩展名 35 36 Newdir=os.path.join(path,str(count).zfill(6)+filetype) #os.path.join路径拼接,并用字符串函数zfill 以0补全所需位数 37 38 os.rename(Olddir,Newdir)#重命名 39 40 count+=1
main.py
import os from PIL import Image #root_dir = "train/" root_dir = "/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/" annotations_dir = root_dir+"annotations/" image_dir = root_dir + "images/" xml_dir = root_dir+"annotations_/" #注意新建文件夹。后续改一下名字,运行完成之后annotations这个文件夹就不需要了。把annotations_命名为annotations class_name = ['ignored regions','pedestrian','people','bicycle','car','van','truck','tricycle','awning-tricycle','bus','motor','others'] for filename in os.listdir(annotations_dir): fin = open(annotations_dir+filename, 'r') image_name = filename.split('.')[0] img = Image.open(image_dir+image_name+".jpg") xml_name = xml_dir+image_name+'.xml' with open(xml_name, 'w') as fout: fout.write('<annotation>'+'\n') fout.write('\t'+'<folder>VOC2007</folder>'+'\n') fout.write('\t'+'<filename>'+image_name+'.jpg'+'</filename>'+'\n') fout.write('\t'+'<source>'+'\n') fout.write('\t\t'+'<database>'+'VisDrone2018 Database'+'</database>'+'\n') fout.write('\t\t'+'<annotation>'+'VisDrone2018'+'</annotation>'+'\n') fout.write('\t\t'+'<image>'+'flickr'+'</image>'+'\n') fout.write('\t\t'+'<flickrid>'+'Unspecified'+'</flickrid>'+'\n') fout.write('\t'+'</source>'+'\n') fout.write('\t'+'<owner>'+'\n') fout.write('\t\t'+'<flickrid>'+'Haipeng Zhang'+'</flickrid>'+'\n') fout.write('\t\t'+'<name>'+'Haipeng Zhang'+'</name>'+'\n') fout.write('\t'+'</owner>'+'\n') fout.write('\t'+'<size>'+'\n') fout.write('\t\t'+'<width>'+str(img.size[0])+'</width>'+'\n') fout.write('\t\t'+'<height>'+str(img.size[1])+'</height>'+'\n') fout.write('\t\t'+'<depth>'+'3'+'</depth>'+'\n') fout.write('\t'+'</size>'+'\n') fout.write('\t'+'<segmented>'+'0'+'</segmented>'+'\n') for line in fin.readlines(): line = line.split(',') fout.write('\t'+'<object>'+'\n') fout.write('\t\t'+'<name>'+class_name[int(line[5])]+'</name>'+'\n') fout.write('\t\t'+'<pose>'+'Unspecified'+'</pose>'+'\n') fout.write('\t\t'+'<truncated>'+line[6]+'</truncated>'+'\n') fout.write('\t\t'+'<difficult>'+str(int(line[7]))+'</difficult>'+'\n') fout.write('\t\t'+'<bndbox>'+'\n') fout.write('\t\t\t'+'<xmin>'+line[0]+'</xmin>'+'\n') fout.write('\t\t\t'+'<ymin>'+line[1]+'</ymin>'+'\n') # pay attention to this point!(0-based) fout.write('\t\t\t'+'<xmax>'+str(int(line[0])+int(line[2])-1)+'</xmax>'+'\n') fout.write('\t\t\t'+'<ymax>'+str(int(line[1])+int(line[3])-1)+'</ymax>'+'\n') fout.write('\t\t'+'</bndbox>'+'\n') fout.write('\t'+'</object>'+'\n') fin.close() fout.write('</annotation>')
trainnamelist.py
# -*- coding: utf-8 -*- """ Created on Fri May 10 10:36:36 2019 @author: qnh12 """ import os import random def _main(): trainval_percent = 0.2 train_percent = 0.9 xmlfilepath = '/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/annotations/' total_xml = os.listdir(xmlfilepath) num = len(total_xml) list = range(num) tv = int(num * trainval_percent) tr = int(tv * train_percent) trainval = random.sample(list, tv) train = random.sample(trainval, tr) ftrainval = open('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/ImageSets/Main/trainval.txt', 'w') ftest = open('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/ImageSets/Main/test.txt', 'w') ftrain = open('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/ImageSets/Main/train.txt', 'w') fval = open('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/ImageSets/Main/val.txt', 'w') for i in list: name = total_xml[i][:-4] + '\n' if i in trainval: ftrainval.write(name) if i in train: ftest.write(name) else: fval.write(name) else: ftrain.write(name) ftrainval.close() ftrain.close() fval.close() ftest.close() if __name__ == '__main__': _main()
label.py
import xml.etree.ElementTree as ET import pickle import os from os import listdir, getcwd from os.path import join sets = ['train', 'test','val'] classes = ['ignored regions','pedestrian','people','bicycle','car','van','truck','tricycle','awning-tricycle','bus','motor','others'] # each category's name 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_id): in_file = open('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/annotations/%s.xml' % (image_id)) out_file = open('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/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) if cls_id != 0 : #忽略掉0类 if cls_id != 11 : #忽略掉11类 out_file.write(str(cls_id-1) + " " + " ".join([str(a) for a in bb]) + '\n') #其他类id-1。可以根据自己需要修改代码 wd = getcwd() print(wd) for image_set in sets: if not os.path.exists('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/labels/'): os.makedirs('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/labels/') image_ids = open('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/ImageSets/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('/home/lhw/Gradute/VirDrone/VisDrone2019-DET-train/images/%s.jpg\n' % (image_id)) convert_annotation(image_id) list_file.close()
参考2:
1.更改下载源
git clone https://github.com/AlexeyAB/darknet.git cd darknet
2. 更改Makefile文件
GPU=1 CUDNN=1 OPENCV=1 #增加opencv模块,显示图片,需系统安装opencv4 OPENMP=0 DEBUG=0
3.复制cfg/yolov3-voc.cfg文件并重命名为cfg/yolov3-voc-visdrone.cfg (可不做)
yolov4需要更改cfg/yolov4.cfg,将分辨率设置为416*416,max_batches=20000(class的2000倍,class=10), steps= 16000,18000(max_batches的80%和90%)
其他与参考2更改一致
4.训练,加上日志消息,可方便后期绘图
./darknet detector train cfg/voc.data cfg/yolov3-voc-visdrone.cfg scripts/darknet53.conv.74 2>&1 | tee visualization/train_yolov3.log
暂停后(ctrl+c)继续训练(将backup中保存的模型复制到script下)
./darknet detector train cfg/voc.data cfg/yolov3-voc-visdrone.cfg scripts/yolov3-voc-visdrone_last.weights 2>&1 | tee visualization/train_yolov3.log
验证
./darknet detector map cfg/voc.data cfg/yolov3-voc-visdrone.cfg scripts/yolov3-voc-visdrone_last.weights
计算验证集ACC
./darknet detector recall cfg/voc.data cfg/yolov3-voc-visdrone.cfg scripts/yolov3-voc-visdrone_last.weights
测试
注:我这里是yolov3-voc-visdrone_last.weights文件,根据实际文件名修改
./darknet detector test cfg/voc.data cfg/yolov3-voc-visdrone.cfg backup/yolov3-voc-visdrone_last.weights test/002007.jpg
新建test文件夹,将待测试的图片放到文件夹下
错误:
1. Can't open label file. (This can be normal only if you use MSCOCO
一般是.txt文件夹中的路径错误