YOLOv3在ubuntu20.04下训练自己的数据集(从“零”开始)
本文最后更新于:2022年2月9日 上午
YOLOv3在ubuntu20.04下训练自己的数据集
背景基础
- 实现了在win10及树莓派4B下yolov3的配置及使用
目的
- 使用Ubuntu20.04下的yolov3 v4 对自己的数据集进行训练
- 将训练好的权重文件移植到机载树莓派上实现嵌入式系统实时的目标检测
- 利用机载树莓派实时的目标检测信息,将该点位置信息发送至感知无人机进行协作,同时将检测结果发送至地面站进行反馈
方法
darknet-yolov3训练自己的数据集(超详细) - AnswerThe - 博客园 (cnblogs.com)准备工作
- Ubuntu20.04的安装(这里选择双系统安装) (1条消息) win10+ubuntu双系统配置_CUG_UESTC的博客-CSDN博客
- 下载镜像:清华大学开源软件镜像站 | Tsinghua Open Source Mirror
- 制作启动盘 (1条消息) 用UltraISO制作Ubuntu16.04 U盘启动盘_YaoyuT的博客-CSDN博客
- ubuntu20.04镜像百度网盘链接提取码:dslz
- 磁盘分配100G(102400MB)空间给ubuntu
- 遇到的坑
- 刚买的新机器装不上旧版本的(18.04和16.04)Ubuntu(电脑配置11代8核i7-1180H 16G 512GSSD RTX3050),旧的台式机试过没问题
- 128G的大U盘在制作启动盘时需要将U盘格式为FAT32,写入镜像后不能正常安装,换个小容量U盘解决
- 设置电脑BIOS,很多新机器·默认uefi启动模式,在boot里并没有这个模式切换选项,但是有一个关闭UEFI的选项,关闭后就可切换到Legacy启动,一般来说开机按F12进入到图三的界面时有UEFI:的U盘时就是正确的引导模式
- 下载镜像:清华大学开源软件镜像站 | Tsinghua Open Source Mirror
- Ubuntu20.04的安装(这里选择双系统安装) (1条消息) win10+ubuntu双系统配置_CUG_UESTC的博客-CSDN博客
环境安装
- cuda11.4+cudnn11.4 (1条消息) ubuntu16.04+cuda8.0+cudnn5.1详细安装过程_weixin_43878078的博客-CSDN博客 (1条消息) Ubuntu18.04下复现YOLOv4(YOLOv3亦可)_hesongzefairy的博客-CSDN博客
- 下载cuda,终端输入:
1
wget https://developer.download.nvidia.com/compute/cuda/11.4.1/local_installers/cuda_11.4.1_470.57.02_linux.run
- 安装:
1
sudo sh cuda\_11.4.1\_470.57.02_linux.run
- 设置环境变量:
1
sudo gedit ~/.bashrc
- 打开配置文件并在末尾加上:
1
2export PATH=/usr/local/cuda-8.0/bin${PATH:+:${PATH}}
export LD\_LIBRARY\_PATH=/usr/local/cuda-8.0/lib64${LD\_LIBRARY\_PATH:+:${LD\_LIBRARY\_PATH}}- 按如下步骤进行:
- 测试CUDA安装成了没:
1
nvcc -V
- 下载cudnn 下载官网匹配版本
- opencv4.5.0:教程中的图文对应OPENCV版本号有问题,方法都一样 (1条消息) Ubuntu20.04 配置Yolov4(gpu版,安装OpenCV,配置环境)_小菜彭-没拿过奖学金的废物的博客的博客-CSDN博客
训练数据
数据集可以用之前在Windows下标注的数据集,将之前标注好的图片和xml文件放到对应目录下。
在myData目录下创建test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31import os
import random
trainval_percent = 0.1
train_percent = 0.9
xmlfilepath = 'Annotations'
txtsavepath = 'ImageSets\Main'
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('ImageSets/Main/trainval.txt', 'w')
ftest = open('ImageSets/Main/test.txt', 'w')
ftrain = open('ImageSets/Main/train.txt', 'w')
fval = open('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()- 运行test.py生成对应的四个txt文件运行
- 用python脚本将数据集进行格式转换(YOLO 训练需要的格式),在darknet文件夹下新建一个my_lables.py文件(代码如下),运行后生成代表类别和相对位置的myData_train.txt,以及lables文件夹下的txt文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join #源代码sets=[('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')]
sets=[('myData', 'train')] # 改成自己建立的myData
classes = ["people"] # 改成自己的类别
def convert(size, box):
dw = 1./(size[0])
dh = 1./(size[1])
x = (box[0] + box[1])/2.0 - 1
y = (box[2] + box[3])/2.0 - 1
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_id):
in_file = open('myData/Annotations/%s.xml'%(image_id)) # 源代码VOCdevkit/VOC%s/Annotations/%s.xml
out_file = open('myData/labels/%s.txt'%(image_id), 'w') # 源代码VOCdevkit/VOC%s/labels/%s.txt
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')
wd = getcwd()
for year, image_set in sets:
if not os.path.exists('myData/labels/'): # 改成自己建立的myData
os.makedirs('myData/labels/')
image_ids = open('myData/ImageSets/Main/%s.txt'%(image_set)).read().strip().split()
list_file = open('myData/%s_%s.txt'%(year, image_set), 'w')
for image_id in image_ids:
list_file.write('%s/myData/JPEGImages/%s.jpg\n'%(wd, image_id))
convert_annotation(year, image_id)
list_file.close()- 运行test.py生成对应的四个txt文件运行
打开自己的cfg文件如图按照自己电脑配置修改训练批次和训练迭代次数。
据实际情况分别修改三处classes(每个[yolo]下),filters=(classes + 5)x3(每个[yolo]上的第一个[convolutional])。
修改cfg/my_data.data
新建myData.names
下载预训练权重,网上找个拷贝进去
预训练权重链接: https://pan.baidu.com/s/10HPZsmBP8mpU0HcHLgSk-Q 提取码: 76fq
开始训练:
1
./darknet detector train cfg/my\_data.data cfg/my\_yolov3.cfg darknet53.conv.74
从停止处重新训练:
1
./darknet detector train cfg/my\_data.data cfg/my\_yolov3.cfg darknet53.conv.74 -gups 0,1,2,3 myData/weights/my_yolov3.backup -gpus 0,1,2,3
结果分析
- 纵坐标平均loss(误差)接近0.0359,即变化不大时可停止训练。横坐标batch(每batch(64)个样本更新一次参数)
- 当前训练的迭代次数: 6478,总体的 Loss(损失):0.0279,平均 Loss:0.0359
- 测试效果:
1
./darknet detect cfg/my\_yolov3.cfg weights/my\_yolov3.weights 72.jpg
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!
- 按如下步骤进行:
- 打开配置文件并在末尾加上:
- cuda11.4+cudnn11.4 (1条消息) ubuntu16.04+cuda8.0+cudnn5.1详细安装过程_weixin_43878078的博客-CSDN博客 (1条消息) Ubuntu18.04下复现YOLOv4(YOLOv3亦可)_hesongzefairy的博客-CSDN博客