目录
-
下载darknet代码并测试
-
红外车载数据集及训练文件准备
-
训练与测试
1、下载darknet代码并测试
1.1 下载代码
git clone https://github.com/pjreddie/darknet
1.2 编译代码
cd darknet
1.2.1 修改Makefile文件
1)如果使用GPU,GPU=1;否则使用CPU,CPU=0;
2)如果使用cudnn加速库,CUDNN=1;否则为0;
3)如果使用opencv,将opencv=1;否则,opencv=0;
1.2.2 在darknet下,编译代码make
1.2.3 下载初始权重
1.2.4 测试
执行相应脚本文件进行测试。
2 红外车载数据集及训练文件准备
2、红外车载数据集及训练文件准备
2.1 准备图像数据集(训练与验证)
2.2 准备txt标注文件
将xml标注文件转换成txt文件
# -*- coding: utf-8 -*- # 此代码和VOC_KITTI文件夹同目录 #我们需要生成darknet中YOLO使用的txt标签格式,原来xml中的bbox数据现在已经全部归一化,原来的Car类型变成现在的索引0,原来的Pedestrain类型变成现在的索引2 import os import glob import xml.etree.ElementTree as ET # 这里的类名为我们xml里面的类名,顺序现在不需要考虑 class_names= ['Pedestrian','Cyclist','Special_vehicle','Bus','Sedan_Car','Vehicle_others','SUV','BigTruck','Motor-Tricycle','MiniVan','Lorry'] person_class_names = ['Pedestrian','Cyclist'] #vehicle_class_names = ['Special_vehicle','Bus','Sedan_Car','Vehicle_others','SUV','BigTruck','Motor-Tricycle','MiniVan','Lorry'] # xml文件路径 xml_path = '../tp_ADAS_2021/xml/' label_path = '../tp_ADAS_2021/labels/' # 转换一个xml文件为txt def single_xml_to_txt(xml_file): tree = ET.parse(xml_file) root = tree.getroot() # filename = root.find('filename').text picture_width = int(root.find('size')[0].text) picture_height = int(root.find('size')[1].text) # 保存的txt文件路径 xml_name = xml_file.split('/')[3] #print(xml_name) txt_name = xml_name[:-4] + '.txt' # 后四位是扩展名.xml,只取前面的文件名 label_file = os.path.join(label_path, txt_name) #print(label_file) with open(label_file, 'w') as label_file: for obj in root.iter('object'): class_name = obj.find('name').text if class_name not in class_names: print('--->%s',class_name) continue # 类名对应的index #class_num = class_names.index(class_name) if class_name in person_class_names: class_num = 0 else: class_num = 1 xmlbox = obj.find('bndbox') box_x_min = float(xmlbox.find('xmin').text) # 左上角横坐标 box_y_min = float(xmlbox.find('ymin').text) # 左上角纵坐标 box_x_max = float(xmlbox.find('xmax').text) # 右下角横坐标 box_y_max = float(xmlbox.find('ymax').text) # 右下角纵坐标 # 转成相对位置和宽高 x_center = float(box_x_min + box_x_max) / (2.0 * picture_width) y_center = float(box_y_min + box_y_max) / (2.0 * picture_height) width = float(box_x_max - box_x_min) / picture_width height = float(box_y_max - box_y_min) / picture_height #print(class_num, box_x_min,box_y_min,box_x_max,box_y_max,x_center, y_center, width, height) label_file.write(str(class_num) + ' ' + str(x_center) + ' ' + str(y_center) + ' ' + str(width) + ' ' + str(height) + ' ') label_file.close() # 转换文件夹下的所有xml文件为txt def dir_xml_to_txt(xml_path): if not os.path.exists(label_path): os.makedirs(label_path) for xml_file in glob.glob(xml_path + '*.xml'): #print(xml_file) single_xml_to_txt(xml_file) dir_xml_to_txt(xml_path)
2.3 准备训练集和验证集txt文件
# -*- coding: utf-8 -*- # 此代码和data文件夹同目录 import glob import os, random, shutil import sys, getopt import string # train, test, rate = getDir(sys.argv[1:]) # if tmp <= 0.0 or tmp >= 1.0: # rate = 0.1 def moveFile(trainDir, testDir, rate): rate=float(rate) pathDir = os.listdir(trainDir) #返回指定的文件夹包含的文件或文件夹的名字的列表 filenumber=len(pathDir) print("filenumber = ", filenumber) picknumber=int(filenumber*rate) print("picknumber = ", picknumber) sample = random.sample(pathDir, picknumber) #从pathDir中随机选取picknumber个元素 for name in sample: shutil.move(os.path.join(trainDir,name), os.path.join(testDir,name)) return train_list = [] test_list = [] train_file = 'train.txt' test_file = 'test.txt' rate = 0.80 if __name__ == '__main__': rate = float(rate) #pathDir = os.listdir('labels/') pathDir = os.listdir('../tp_ADAS_2021/JPEGImages/') filenumber = len(pathDir) picknumber = int(filenumber * rate) sample = random.sample(pathDir, picknumber) for name in sample: train_list.append(name) for name in pathDir: if name not in sample: test_list.append(name) cur_dir = os.getcwd() #返回当前进程的工作目录 train_images_dir = os.path.join(cur_dir, 'JPEGImages/') with open(train_file, 'w') as train_txt: for name in train_list: jpg_name = name.strip() jpg_file = os.path.join(train_images_dir, jpg_name) train_txt.write(jpg_file + ' ') train_txt.close() with open(test_file, 'w') as test_txt: for name in test_list: jpg_name = name.strip() jpg_file = os.path.join(train_images_dir, jpg_name) test_txt.write(jpg_file + ' ') test_txt.close() print(filenumber,picknumber,filenumber-picknumber)
2.4 编辑 adas.names
一行一个名字
2.5 编辑 adas.data文件
classes :训练集类别总数
train:训练集路径
valid:验证集路径
names: adas.names 文件
backup: 备份文件夹,训练后的权重信息或者断点保存信息在此文件夹下。
(记得创建目录 backup)
2.6 修改yolov3.cfg
修改yolo层类别数和yolo层上一层卷积数。
总共会搜出3个含有yolo的地方。
每个地方都必须要改2处, filters:3*(5+len(classes));
其中:classes: len(classes) =11,这里以我的工程为例
filters = 48
classes = 11
超参数解释:
[net] # Testing ### 测试模式 # batch=1 # subdivisions=1 # Training ### 训练模式,每次前向的图片数目 = batch/subdivisions batch=64 subdivisions=16 width=416 ### 网络的输入宽、高、通道数 height=416 channels=3 momentum=0.9 ### 动量 decay=0.0005 ### 权重衰减 angle=0 saturation = 1.5 ### 饱和度 exposure = 1.5 ### 曝光度 hue=.1 ### 色调 learning_rate=0.001 ### 学习率 burn_in=1000 ### 学习率控制的参数 max_batches = 50200 ### 迭代次数 policy=steps ### 学习率策略 steps=40000,45000 ### 学习率变动步长
2.7 下载预训练权重
wget https://pjreddie.com/media/files/darknet53.conv.74
3 训练与测试
./darknet detector train cfg/my_data.data cfg/my_yolov3.cfg darknet53.conv.74
或者指定gpu训练,默认使用gpu0
./darknet detector train cfg/my_data.data cfg/my_yolov3.cfg darknet53.conv.74 -gups 0,1,2,3
从停止处重新训练
./darknet detector train cfg/my_data.data cfg/my_yolov3.cfg darknet53.conv.74 myData/weights/my_yolov3.backup -gpus 0,1,2,3
测试
./darknet detect cfg/my_yolov3.cfg weights/my_yolov3.weights 1.jpg