配置YOLOv7训练自己是数据集
随手记录一下YOLOv7的配置。环境:
window 10 专业版
Python3.8
Pytorch2.1
参考资料
1、HIT-UAV-Infrared-Thermal-Dataset
2、WongKinYiu/yolov7
3、【小白教学】如何用YOLOv7训练自己的数据集
4、目标检测中数据集格式之间的相互转换–coco、voc、yolo
5、YoloV7实战:手把手教你使用Yolov7进行物体检测(附数据集)
6、【特训营第三期】无人机高空红外检测
7、YOLOv7保姆级教程(个人踩坑无数)----训练自己的数据集
1、第一次踩坑【未解决】
1.1、数据集准备
使用开源的HIT-UAV数据集。有四种格式的数据,使用normal_xml
文件下的,这个是voc
格式的数据
1.2、配置YOLO
- 创建文件夹
datasets
,统一管理数据集 - 创建文件夹
weights
,存放模型参数
1.2.1、配置网络参数
复制文件..\yolov7-main\cfg\training\yolov7.yaml
,重命名为yolov7-HITUAV.yaml
,修改分类的种类:
1.2.2、修改数据集配置
复制文件..\yolov7-main\data\coco.yaml
,重命名为..\yolov7-main\data\HITUAV.yaml
,针对数据集进行修改:
1.2.3、配置训练参数
在官网下载预训练模型yolov7_training.pt
,放到文件夹weights
中。
在train.py
文件中,针对上面的配置,设定相关的参数:
就这样运行训练,会报错的:
需要把.yaml
文件中的中文删除掉,不能留有中文,不然会报错。
就算是这样修改了,也是跑不起来的:
2、第二次踩坑【已解决】
找到了这篇博客:YOLOv7保姆级教程(个人踩坑无数)----训练自己的数据集,作者讲的很好,解决了我很多疑问和问题,推荐看!!
网络参数用上面修改的,不用修改了。
2.1、修改数据集配置
复制文件..\yolov7-main\data\coco.yaml
,重命名为..\yolov7-main\data\HITUAV.yaml
,针对数据集进行修改:
# COCO 2017 dataset http://cocodataset.org
# download command/URL (optional)
# download: bash ./scripts/get_coco.sh
train: ./datasets/HITUAV/VOC/TrainVal_train.txt #
val: ./datasets/HITUAV/VOC/TrainVal_val.txt #
test: ./datasets/HITUAV/VOC/Test_test.txt #
# number of classes
nc: 5
# class names
names: ["Person", "Car", "Bicycle", "OtherVehicle", "DontCare"] #
2.2、配置数据集
原来的数据集文件有:
Annotations
为数据集的xml
文件,ImageStes
中再创建一个Main
文件夹,JPEGImages
为数据集的图片,接下来需要将xml
文件划分,再转为txt
文件——YOLOv7保姆级教程(个人踩坑无数)----训练自己的数据集
2.2.1、划分训练集、测试集
编写python脚本,对数据进行划分:
# 参考https://blog.csdn.net/weixin_55749226/article/details/128480595
import os
from os import listdir, getcwd
import random
# xmlfilepath = r'./datasets/HITUAV/VOC/Annotations/' # xml文件的路径
# saveBasePath = r'./datasets/HITUAV/VOC/ImageSets/' # 生成的txt文件的保存路径
wd = getcwd()
xmlfilepath = wd + '/Annotations/' # xml文件的路径
saveBasePath = wd + '/ImageSets/' # 生成的txt文件的保存路径
# xmlfilepath = r'G:/YOLOv7/yolov7-main/datasets/HITUAV/VOC/Annotations/' # xml文件的路径
# saveBasePath = r'G:/YOLOv7/yolov7-main/datasets/HITUAV/VOC/ImageSets/' # 生成的txt文件的保存路径
trainval_percent = 0.9 # 训练验证集占整个数据集的比重(划分训练集和测试验证集)
train_percent = 0.8 # 训练集占整个训练验证集的比重(划分训练集和验证集)
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)
print("train and val size", tv)
print("traub suze", tr)
ftrainval = open(os.path.join(saveBasePath, 'Main/trainval.txt'), 'w')
ftest = open(os.path.join(saveBasePath, 'Main/test.txt'), 'w')
ftrain = open(os.path.join(saveBasePath, 'Main/train.txt'), 'w')
fval = open(os.path.join(saveBasePath, '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:
ftrain.write(name)
else:
fval.write(name)
else:
ftest.write(name)
ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
运行结果:
2.2.2、生成对应的文件
创建一个voc_label.py文件:
# 参考:https://blog.csdn.net/weixin_55749226/article/details/128480595
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import shutil
sets=[('TrainVal', 'train'), ('TrainVal', 'val'), ('Test', 'test')]
# classes =["mask_weared_incorrect","with_mask","without_mask"]
classes =["Person","Car","Bicycle","OtherVehicle","DontCare"] #需要分别标注的类别
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(year, image_set, image_id):
in_file = open('Annotations/%s.xml'%( image_id))
out_file = open('labels/%s_%s/%s.txt'%(year, image_set, image_id), 'w',encoding='utf-8')
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)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
def copy_images(year,image_set, image_id):
in_file = 'JPEGImages/%s.jpg'%(image_id)
out_flie = 'images/%s_%s/%s.jpg'%(year, image_set, image_id)
shutil.copy(in_file, out_flie)
wd = getcwd()
for year, image_set in sets:
if not os.path.exists('labels/%s_%s'%(year, image_set)):
os.makedirs('labels/%s_%s'%(year, image_set))
if not os.path.exists('images/%s_%s'%(year, image_set)):
os.makedirs('images/%s_%s'%(year, image_set))
image_ids = open('ImageSets/Main/%s.txt'%( image_set)).read().strip().split()
list_file = open('%s_%s.txt'%(year, image_set), 'w')
for image_id in image_ids:
list_file.write('%s/images/%s_%s/%s.jpg\n'%(wd, year, image_set, image_id))
convert_annotation(year, image_set, image_id)
copy_images(year, image_set, image_id)
list_file.close()
运行后,文件变为了:
其中,文件images
、labels
很重要,训练的时候会默认搜索这两个文件找数据,如果没有,会报错。
其他的使用上面的设置就行。
3、训练
要注意:
batchsize需要根据显卡来配置,本人使用RTX1060 6GB,设为8才不会爆显存!
运行结果:
算是成功运行了。
下一步需要根据自己的数据进行打标,再说吧。