目录
下载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) + '\n')
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 + '\n')
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 + '\n')
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