【 1. 准备数据 】
- 考虑到训练时间和资源等因素,我们使用的极少量的数据集来训练。虽然数据少,但效果很棒,而且流程健全。
- 使用到的图片数据集:
训练集
- 我们使用4张图片作为训练集数据。
其中人脸相关的标注数据,存放于XML文件中,格式如下:
<?xml version='1.0' encoding='ISO-8859-1'?>
<?xml-stylesheet type='text/xsl' href='image_metadata_stylesheet.xsl'?>
<dataset>
<name>Training faces</name>
<comment>These are images from the PASCAL VOC 2011 dataset.</comment>
<images>
<image file='2007_007763.jpg'>
<box top='90' left='194' width='37' height='37'/>
<box top='114' left='158' width='37' height='37'/>
...
<box top='86' left='294' width='37' height='37'/>
<box top='233' left='309' width='45' height='44'/>
</image>
...
</images>
</dataset>
# image file 代表图像文件名;
# box中 top、left、width和height指定了人脸区域,
# 一张图中可能包含多个人脸,所以可能有多个box。
测试集
- 我们使用5张图片作为测试集数据。
同样的,其中人脸相关的标注数据,存放于XML文件中,其格式与训练集文件格式相同。
【 2. 使用 Dlib 训练模型 】
- 在准备好训练集和测试集之后,便可以开始训练人脸检测模型。
- 大量的研究和实验表明,在物体检测的领域中,与HOG一起使用的算法中,SVM算法的效果是最好的。由于人脸检测也是物体检测的一种,所以我们的训练模型也会基HOG+SVM。
- 一个完整的训练流程:
- 设置
SVM
的参数;- 读取用于训练的xml文件
training.xml
;- 获取用于训练集中图片的
人脸区域
;- 将人脸区域转为
HOG特征
;- 将生成的HOG特征
作为SVM的输入
;- SVM训练数据
生成模型
。
1. 定义参数
人脸检测模型中包含大量可以设置的参数,所以我们首先定义参数设置函数:
options = dlib.simple_object_detector_training_options()
大部分参数,在此我们使用默认值,针对我们的训练集,我们主要设定如下几个参数。
- C: 对误差的宽容度
在SVM中,C是惩罚系数,即对误差的宽容度。
C越高,说明越不能容忍出现误差,容易过拟合;
C越小,容易欠拟合。C过大或过小,泛化能力变差。
在本例中我们将C的值设置为5。
options.C = 5
- add_left_right_image_flips:对图片做镜像处理
对用于训练的图片做镜像处理,从而将训练集扩大一倍。一般都会设置为True。
options.add_left_right_image_flips = True
- be_verbose :输出训练的过程中的相关信息
是否输出训练的过程中的相关信息。我们设置为True。
options.be_verbose = True
- num_threads:设置训练时使用的cpu的核数
设置训练时使用的cpu的核数。在这里我们设置为4。
options.num_threads = 4
2. 训练、生成模型
参数设定完成,就可以进行训练了。
训练函数封装了训练流程的第2到6步,如下:
dlib.train_simple_object_detector(training_xml_path, "detector.svm", options)
其中,training_xml_path 是训练数据标记文件路径,options 可以视为我们前一步设置各种参数的集合,最后我们将检测器输出为 detector.svm文件。
- 完整的训练代码如下:
import dlib
import os
faces_folder = "step2/data/dlib_example_faces" # 数据集路径
# 1. 定义模型训练需要的参数
options = dlib.simple_object_detector_training_options()
# 2.参数设定
options.add_left_right_image_flips = True # 对数据集图片做镜像处理
options.C = 5 # SVM的惩罚因子C为5
options.num_threads = 4 # 设置训练时使用的cpu的核数为4
options.be_verbose = True # 输出训练的过程中的相关信息
# 3. 调用训练模型函数
training_xml_path = os.path.join(faces_folder, "training.xml")# 训练集xml路径
# 4. 训练模型
dlib.train_simple_object_detector(training_xml_path, "detector.svm", options)
运行训练程序,输出如下:
objective: 1.79764
objective gap: 0.0611934
risk: 0.0123693
risk gap: 0.0122387
num planes: 111
iter: 1
...
objective: 1.78632
objective gap: 0.049733
risk: 0.0100423
risk gap: 0.0099466
num planes: 113
iter: 205
Training complete.
Trained with C: 5
Training with epsilon: 0.01
Trained using 4 threads.
Trained with sliding window 80 pixels wide by 80 pixels tall.
Upsampled images 1 time to allow detection of small boxes.
Trained on both left and right flipped versions of images.
Saved detector to file detector.svm
3. 检验模型的效果
在训练完成之后,我们可以调用我们训练好的模型并在测试集上测试我们的模型结果,
示例代码如下:
testing_xml_path = os.path.join(faces_folder, "testing.xml")
print("Testing accu\fracy: {}".format(dlib.test_simple_object_detector(testing_xml_path, "detector.svm")))
运行测试程序,输出如下:
Training accu\fracy: precision: 1, recall: 1, average precision: 1
Testing accu\fracy: precision: 1, recall: 1, average precision: 1
下图展示了在下一步中(绘制人脸区域)实际完成的模型效果,可以看出模型效果还不错。