RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)

上期回顾:

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第1张图片

前言

这篇文档会介绍如何用 darknet 训练一个 YOLOv2 目标检测模型,看完这篇文档会发现:模型训练和预测都非常简单,最花时间的精力的往往是训练集的数据预处理。

下面先简单介绍一下以下两个问题:

1、目标分类 (Classification) 和 目标检测 (Detection) 的区别是什么?

2、 YOLODarknet分别是什么

下面这张图很清晰地说明了 目标分类

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第2张图片

一张图片作为输入,然后模型就会告诉我这张图片里有猫的概率是多少,有狗的概率是多少,但是并不会告诉我有几只猫,几只狗,也不会告诉我猫和狗在图片里的具体位置。
目标检测 则不一样:

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第3张图片

目标检测的模型输出会告诉我图片中猫和狗分别在什么位置,以及是猫和狗的概率分别是多少,所以目标检测模型提供的信息更加丰富,但是因此对模型的要求也更高了。

这里非常推荐一篇文章,本文章对目标检测的解释非常直观详细:

http://machinethink.net/blog/object-detection/

现在目标检测算法也有很多,这篇文章用到的就是非常有名的 YOLO (You only look once),就和字面意思一样, YOLO 可以一步 (one-stage) 得到结果所以非常快 (R-CNN 就需要两步 two-stage),而 Darknet 就是论文作者对自己算法的开源实现,既然是作者本人的实现,自然会有很多人愿意看一看。

Darknet 是用 C 语言实现的,在 Github 上也能找到开源的 源码,用 Darknet 既可以训练新的模型,也可以用现有的模型做预测。

接下来就会介绍如何用 Darknet 训练一个小黄人目标检测模型。

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第4张图片

目标检测模型演示

参考文献:(以下链接请复制至外部浏览器打开)

1、Darknethttps://pjreddie.com/darknet/

2、目标检测http://machinethink.net/blog/object-detection/

1 准备训练集

1.1 拍摄照片

首先当然是要拍照了,照片用什么摄像头都是可以的,不过如果采集数据用的摄像头和最后实时预测用的是一样的,效果当然会更好了,不过我这里拍照用的是 K210 上面的摄像头,上面的动画里预测是用的 USB 摄像头,效果也还可以 ?

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第5张图片

其实拍照就是拍一些里面包含你想要识别的物体的照片就好了,从各个角度、各个距离拍,这很重要!!!比如如果你想识别只有一半的小黄人,那拍的照片里就得有这样的例子才行,下面就是我拍的 300 张照片:

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第6张图片

通常做机器学习的图像识别,训练集很多时候都是 10GB+,但是我是用的 K210 摄像头拍的,每张照片就 320x240 差不多 3KB 大小,最后 300 张照片加在一起还没有 3MB,不过最后的训练结果却还挺不错的 ?

如果碰巧你也有 K210 可以参照下面的 Micropython 代码每隔 1-2s 自动拍一张照片保存到 SD 卡,用手机摄像头当然也是完全没有问题的

 1# Untitled - By: RT-Thread - 周五 7月 19 2019
 2
 3import sensor, image, time, lcd
 4from fpioa_manager import *
 5from Maix import GPIO
 6import os
 7
 8def getMax():
 9    maxnum = 0;
10    files = os.listdir('/sd')
11    for file in files:
12        name = file.split(".")
13        if(len(name)>1 and name[1] == "jpg"):
14            if(int(name[0])>maxnum):
15                maxnum = int(name[0])
16    return maxnum
17
18fm.register(board_info.LED_R, fm.fpioa.GPIO0)
19led_r=GPIO(GPIO.GPIO0,GPIO.OUT)
20
21lcd.init(freq=15000000)
22
23sensor.reset()
24sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE)
25sensor.set_framesize(sensor.QVGA)   # Set frame size to QVGA (320x240)
26sensor.skip_frames(time = 2000)     # Wait for settings take effect.
27sensor.set_hmirror(0)
28sensor.set_windowing((224,224))
29clock = time.clock()                # Create a clock object to track the FPS.
30
31i = getMax() + 1
32
33def capture():
34    global i
35    img = sensor.snapshot()
36    filename = '/sd/' + str(i) + '.jpg'
37    print(filename)
38    img.save(filename)
39    img.draw_string(2,2, ("%2.1f" %(i)), color=(0,128,0), scale=2)
40    lcd.display(img)
41    i = i + 1;
42
43print("Start from %d" % i)
44
45while True:
46    led_r.value(0)
47    time.sleep(1)
48    led_r.value(1)
49    capture()

这里千万不要把图片保存为中文名,建议像图中那样用数字按顺序标注,到这里我们应该有几百张包含我们要检测的物体的图片了。

1.2 标注图片

这一步应当是最累的了,上面只是拍好了 300 张照片,这一步就要为这些图片一一的做标注了,看起来就是这样:

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第7张图片

这里推荐用软件 LabelImg (链接:https://github.com/tzutalin/labelImg)来标注:

软件用起来还是非常简单的,打开拍摄的图片文件夹,选择要保存的文件夹,然后一张一张地标注就可以了,最后可以看到每一张图片都生成了对应的 txt 文件:

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第8张图片

如果我们打开一个 txt 文件就可以看到类似下面的内容:

10     0.671875    0.575893   0.352679    0.848214
其中每个数字代表的含义是:
1物体类别   物体中心位置 x    物体中心位置 y   物体宽度 x   物体高度y

因为我们只有一个类别,所以第一个数字始终是 0,代表是第一个类别。

到这里我们应该每一张拍摄的图片都有一个对应的 txt 文件,里面包含上面提到的内容。

1.3 划分训练集和测试集

在开始训练之前,我们还需要把上面拍到的图片分为训练集和测试集,这样我们才知道模型训练效果怎么样。
这里有个 python 脚本可以自动生成训练集和测试集,其实最终的目的就是生成两个文件,train.txt 和 test.txt,里面分别包含了训练图像,和测试图像的名字。
 1import glob, os
 2
 3# Current directory
 4current_dir = os.path.dirname(os.path.abspath(__file__))
 5
 6# Directory where the data will reside, relative to 'darknet.exe'
 7# 修改为你自己的目录
 8path_data = './train/'
 9
10# Percentage of images to be used for the test set
11percentage_test = 10;
12
13# Create and/or truncate train.txt and test.txt
14file_train = open('train.txt', 'w')
15file_test = open('test.txt', 'w')
16
17# Populate train.txt and test.txt
18counter = 1
19index_test = round(100 / percentage_test)
20for pathAndFilename in glob.iglob(os.path.join(current_dir, "*.jpg")):
21    title, ext = os.path.splitext(os.path.basename(pathAndFilename))
22
23    if counter == index_test:
24        counter = 1
25        file_test.write(path_data + title + '.jpg' + "\n")
26    else:
27        file_train.write(path_data + title + '.jpg' + "\n")
28        counter = counter + 1

最后 train.txt 和 test.txt 看起来是这样的:

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第9张图片

到这里应该有拍好的照片,每张照片对应一个 txt 标明了小黄人的位置,大小,另外还有一个 train.txt 和 test.txt 汇总了当前训练集和测试集的文件名。

1.4 参考文献

1、荔枝丹 Dan Dock (K210)

https://wiki.sipeed.com/en/maix/board/dock.html

2、训练自己的 Darknet Yolov2 模型

https://timebutt.github.io/static/how-to-train-yolov2-to-detect-custom-objects/

2 训练模型

2.1 开发环境

训练的过程就非常简单了,建议使用 GPU,请务必使用 GPU,而且请使用 Linux 开发环境,Ubuntu 自然是科研领域用的最多的 Linux 发行版了,而且在开始训练之前请安装好显卡驱动CUDA 工具链cuDNN 库

我用 i5 训练了整整 2天,才迭代了 200 步,用 NVIDIA GP104 训练一上午就迭代了 20000 步。

都安装好之后,输入 nvidia-smi 应当是可以看到 CUDA 版本的:

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第10张图片

2.2 编译 Darknet


如果到这里开发环境安装没有问题,我们就可以开始训练了,其实训练过程非常简单,首先下载源码:

git clone 	
https://github.com/pjreddie/darknet	
为了使用 GPU 训练,我们需要修改一下 Makefile:
1GPU=1
2CUDNN=1
3OPENCV=0
4OPENMP=0
5DEBUG=0
然后编译:
1make

编译好 Darknet 后就可以在源码根目录看到一个 Darknet 可执行文件了。

2.3 配置文件

下面我们在 cfg 目录下添加一个 obj.names 文件,里面定义了我们的物体类别:
1minions

当然,我们只有一个类别,接下来还需要在 cfg 目录下添加一个 obj.data 文件,里面第一行定义了我们的物体类别数,我们只有一个类别,已经我们前面生成的 train.txt,test.txt,obj.names 这 3 个文件在哪里,最后的 backup 是指训练的模型保存的位置。

1classes= 1
2train  = /home/wuhan/darknet/data/train.txt
3valid  = /home/wuhan/darknet/data/test.txt
4names = /home/wuhan/darknet/cfg/obj.names
5backup = backup/
最后因为我们训练的模型只有 1 类,但是 yolo 模型默认并不是只有 1 类,所以我们需要修改 cfg/yolov2.cfg,需要修改的部分我都标注出来了,我把这个配置文件保存成了 minionsv2.cfg:
  1[net]
  2# Testing
  3batch=16
  4subdivisions=1
  5# Training
  6# batch=64
  7# subdivisions=2
  8width=214     # 修改图像宽度
  9height=214    # 修改图像高度
 10channels=3
 11momentum=0.9
 12decay=0.0005
 13angle=0
 14saturation = 1.5
 15exposure = 1.5
 16hue=.1
 17
 18learning_rate=0.001
 19burn_in=1000
 20max_batches = 500200
 21policy=steps
 22steps=400000,450000
 23scales=.1,.1
 24
 25[convolutional]
 26batch_normalize=1
 27filters=16
 28size=3
 29stride=1
 30pad=1
 31activation=leaky
 32
 33[maxpool]
 34size=2
 35stride=2
 36
 37[convolutional]
 38batch_normalize=1
 39filters=32
 40size=3
 41stride=1
 42pad=1
 43activation=leaky
 44
 45[maxpool]
 46size=2
 47stride=2
 48
 49[convolutional]
 50batch_normalize=1
 51filters=64
 52size=3
 53stride=1
 54pad=1
 55activation=leaky
 56
 57[maxpool]
 58size=2
 59stride=2
 60
 61[convolutional]
 62batch_normalize=1
 63filters=128
 64size=3
 65stride=1
 66pad=1
 67activation=leaky
 68
 69[maxpool]
 70size=2
 71stride=2
 72
 73[convolutional]
 74batch_normalize=1
 75filters=256
 76size=3
 77stride=1
 78pad=1
 79activation=leaky
 80
 81[maxpool]
 82size=2
 83stride=2
 84
 85[convolutional]
 86batch_normalize=1
 87filters=512
 88size=3
 89stride=1
 90pad=1
 91activation=leaky
 92
 93[maxpool]
 94size=2
 95stride=1
 96
 97[convolutional]
 98batch_normalize=1
 99filters=1024
100size=3
101stride=1
102pad=1
103activation=leaky
104
105###########
106
107[convolutional]
108batch_normalize=1
109size=3
110stride=1
111pad=1
112filters=512
113activation=leaky
114
115[convolutional]
116size=1
117stride=1
118pad=1
119filters=30         # filters = (classes + 5) * 5
120activation=linear
121
122[region]
123anchors =  0.57273, 0.677385, 1.87446, 2.06253, 3.33843, 5.47434, 7.88282, 3.52778, 9.77052, 9.16828
124bias_match=1
125classes=1         # 只有 1 类
126coords=4
127num=5
128softmax=1
129jitter=.2
130rescore=0
131
132object_scale=5
133noobject_scale=1
134class_scale=1
135coord_scale=1
136
137absolute=1
138thresh = .6
139random=1

2.4 开始训练

终于可以开始训练了:

1./darknet detector train cfg/obj.data cfg/minionsv2.cfg darknet19_448.conv.23 
记得把上面的配置文件改成自己的配置文件,上面命令里提前训练好的模型可以从这里下载  darknet19_448.conv.23 (78MB): https://wuhanshare-1252843818.cos.ap-guangzhou.myqcloud.com/darknet19_448.conv.23 ,可以加快训练速度。
前面提到,训练好的模型可以在 backup 目录找到,这是我训练了 20000 步之后自动保存的模型文件:
 1minionsv2_10000.weights
 2minionsv2_100.weights
 3minionsv2_20000.weights
 4minionsv2_200.weights
 5minionsv2_300.weights
 6minionsv2_400.weights
 7minionsv2_500.weights
 8minionsv2_600.weights
 9minionsv2_700.weights
10minionsv2_800.weights
11minionsv2_900.weights
12minionsv2.backup

3 实时预测

如果我们想从摄像头实时看到检测结果,需要先重新编译 Darknet,因为访问摄像头需要 OpenCV 库支持,修改 Makefile:
1GPU=1
2CUDNN=1
3OPENCV=1
4OPENMP=0
5DEBUG=0

重新 make 得到 darknet 可执行文件,输入下面的命令就可以看到试试检测结果了。

1./darknet detector demo cfg/obj.data cfg/minionsv2.cfg /home/wuhan/darknet/backup/minionsv2_10000.weights
记得把上面的文件路径改为自己的实际文件路径。
RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第11张图片

4 总结

这里总结一下,用 Darknet 训练目标检测模型其实就这几步:
1、拍摄照片
2、用 labelimg 在照片上标注出自己想识别的物体的位置
3、把拍摄的照片划分为测试集和训练集,生成 train.txt 和 test.txt
4、编译 Darknet,配置好 CUDA,cuDNN
5、添加配置文件 cfg/obj.names 和 cfg/obj.data
6、修改 yolov2 模型为单类别 cfg/yolov2.cfg,并下载 darknet19_448.conv.23
7、用 GPU 开始训练,模型会自动保存

我们下期再见!加入智能小车交流群请加微信:RT-Thread2006

RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4)_第12张图片


END

RT-Thread线上活动

1、【RT-Thread能力认证考试12月——RCEA】经过第一次考试的验证,

能力认证官网链接:https://www.rt-thread.org/page/rac.html(在外部浏览器打开)

640?wx_fmt=png

立即报名

#题外话# 喜欢RT-Thread不要忘了在GitHub上留下你的640?wx_fmt=pngSTAR640?wx_fmt=png哦,你的star对我们来说非常重要!链接地址:https://github.com/RT-Thread/rt-thread

RT-Thread线下活动

1、中国国际工业博览会RT-Thread展台指南:

位置 上海工博会6.2号馆,近4号门 上海科学院展区内  

时间  参展日期截至2019年9月20号

2、STM32全国研讨会,RT-Thread近期参展城市预告:南京、上海、深圳、广州、顺德

你可以添加微信18917005679为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群

640?wx_fmt=jpeg

RT-Thread

长按二维码,关注我们

640?wx_fmt=png
看这里,求赞!求转发!
640?wx_fmt=gif

640?wx_fmt=gif点击阅读原文进入RT-Thread官网

你可能感兴趣的:(RT-Thread智能车目标识别系统连载教程——Darknet 训练目标检测模型(4))