darknet-yolov3 识别自定义数据集

训练环境为 ubuntu18.04,使用 CPU 训练 yolov3 模型,本文介绍了如何使用 darknet 识别想要的物品,包括修改配置文件、训练、测试过程。如果想要将 darknet 部署到树莓派等平台上,则需要做一些修改,因为 yolov3 的网络参数较大,识别比较费时,建议使用 yolov3-tiny 模型,使用过程类似,详情参考这篇文章使用GPU训练yolov3-tiny模型

一、下载编译 darknet

从 github 拉取 darknet

git clone https://github.com/pjreddie/darknet
cd darknet

根据主机情况修改配置文件 Makefile ,如果使用 CPU 训练,则文件内容如下:

GPU=0     #如果使用GPU设置为1,CPU设置为0
CUDNN=0   #如果使用CUDNN设置为1,否则为0
OPENCV=0  #如果调用摄像头,还需要设置OPENCV为1,否则为0
OPENMP=0  #如果使用OPENMP设置为1,否则为0
DEBUG=0   #如果使用DEBUG设置为1,否则为0

编译

make

在 darknet 目录下下载 yolov3 的权重文件

wget https://pjreddie.com/media/files/yolov3.weights

使用预训练模型权重文件 yolov3.weights 进行测试,看 darknet 是否能识别

./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg

或者

./darknet detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights data/dog.jpg

二、数据集准备

2.1 标注数据集

下载标注工具(labeling)

用 labeling 为自己的数据集打上标签,采用 PascalVOC 格式,标签的文件格式为 xml 文件。

2.2 创建数据集文件夹

在 darknet 目录下创建 myData 文件夹,目录结构如下,作用是存储数据片图像及标签

myData
├── JPEGImages    #存放图像
├── Annotations   #存放图像对应的xml文件
├── ImageSets
    └── Main      # 存放训练/验证图像的文件名(格式如 000001,不带文件后缀名)

命令如下:

mkdir myData
cd myData
mkdir JPEGImages
mkdir Annotations
mkdir -p ImageSets/Main

将自己的数据集图片拷贝到 JPEGImages 目录下。将数据集标签文件(即用 labeling 生成的 xml 文件)拷贝到Annotations目录下。

2.3 生成训练所需文件

生成训练、验证、测试集花名册和可用的标签文件,以供训练使用。

在 myData 目录下创建test.py

cd darknet/myData
touch test.py

将下面代码拷贝进去,test.py 的内容:

import 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,将会在 myData/ImageSets/Main 目录下生成四个文件:train.txt,val.txt,test.txt和trainval.txt,这四个文件是训练、测试所使用的图片分配。

python test.py

通过 mylabel.py 脚本将 xml 文件转换成 darknet 支持的格式。

在darknet文件夹下创建 mylabel.py 文件

cd darknet
touch mylabel.py

将以下内容拷贝进去,注意要修改类别

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
 
sets=[('myData', 'train')]  
 
classes = ["person", "foot", "face"] # 改成自己的类别
 
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))  
    out_file = open('myData/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)
        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/'):  
        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()

运行该脚本,会在 myData 目录下生成 labels 文件夹和一个 txt 文件(myData_train.txt),myData_train.txt 的内容是数据集图片的绝对路径,labels 里面是 txt 格式的标签文件(xml 转)

labels 文件夹中的 txt 文件内容解释

在这里插入图片描述

三、修改训练配置文件

训练所需的配置文件主要在 darknet/cfg 中,这里用到 voc.data 和 yolov3-voc.cfg 这两个配置文件

以防万一,复制这两个文件,并分别重命名为 my_data.data 和 my_yolov3.cfg,命令如下

cp cfg/voc.data cfg/my_data.data
cp cfg/yolov3-voc.cfg cfg/my_yolov3.cfg

3.1 修改 my_data.data 配置文件

修改 my_data.data 的内容如下,注意修改路径

classes= 3    ##改为自己的分类个数
##下面都改为自己的绝对路径
train  = /home/XXX/darknet/myData/myData_train.txt   #训练图片的绝对路径
names = /home/XXX/darknet/myData/myData.names    #稍后需要创建这个文件
backup = /home/XXX/darknet/myData/weights   #保存训练的权重文件的文件夹

3.2 修改 my_yolov3.cfg 配置文件

使用 vi 编辑器,输入 /yolo,总共会搜出3个含有yolo的地方。

vi cfg/my_yolov3.cfg

每个地方都必须要改2处(filters 和 classes)

classes 的值改为要识别的种类数目

filters 的值改为 3*(5+种类数目)

如要识别的种类有 3 种,则
filters = 24
classes = 3

可选修改:random = 1:原来是1,如果显存较小则改为0 (random 决定是否要多尺度输出)

在这里插入图片描述

可修改训练轮数 max_batches ,下图是文件开头内容:
在这里插入图片描述

各项参数含义:

[net]
# Testing            ### 测试模式,测试的时候把 Training 下面的 batch 和 subdivisions 注释掉,取消 Testing 下的 batch 和 subdivisions 的注释                                       
# batch=1
# subdivisions=1
# Training           ### 训练模式,每次前向的图片数目 = batch/subdivisions 
batch=64			 ### 每batch个样本更新一次参数
subdivisions=16      ### 如果内存不够大,将batch分割为subdivisions个子batch,每个子batch的大小为batch/subdivisions
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    ### 学习率变动步长 

max_batches参数根据总类别修改,为类别数x2000,steps参数修改为max_batches的80%和90%,大致如此

3.3 创建 myData.names 文件

在 myData文件夹下新建 myData.names 文件,内容为识别类型的名字,每个名字一行

people
foot
car

四、训练模型

4.1 下载预训练模型

在 darknet 目录下运行如下命令下载预训练模型

wget https://pjreddie.com/media/files/darknet53.conv.74

4.2 开始训练

在 darknet 目录下,用之前修改好的配置文件进行训练

./darknet detector train cfg/my_data.data cfg/my_yolov3.cfg darknet53.conv.74

从停止处重新训练

./darknet detector train cfg/my_data.data cfg/my_yolov3.cfg darknet53.conv.74  myData/weights/my_yolov3.backup 

说明:myData/weights/my_yolov3.backup 是每一轮迭代后所权重文件缓存

五、测试

训练完成后,修改 my_yolov3.cfg 文件开头,使用 Testing ,注释掉 Training , 使用数据集图片和指定的权重文件进行测试,命令如下

./darknet detector test cfg/my_data.data cfg/my_yolov3.cfg myData/weights/my_yolov3_9000.weights myData/JPEGImages/1.jpg

参考文章:darknet-yolov3训练自己数据集

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值