OpenCV 4.11.0
开源计算机视觉
加载中…
搜索中…
未找到匹配项
级联分类器训练

上一教程: 级联分类器
下一教程: 条形码识别

引言

使用弱分类器的增强级联包含两个主要阶段:训练阶段和检测阶段。使用基于HAAR或LBP模型的检测阶段在目标检测教程中进行了描述。本文档概述了训练您自己的弱分类器增强级联所需的功能。本指南将逐步讲解所有不同阶段:收集训练数据、准备训练数据以及执行实际模型训练。

为了支持本教程,将使用几个官方的OpenCV应用程序:opencv_createsamplesopencv_annotationopencv_traincascadeopencv_visualisation

注意
从OpenCV 4.0开始,createsamples和traincascade已被禁用。建议使用3.4分支的这些应用程序进行级联分类器的训练。3.4和4.x版本的模型格式相同。

重要提示

  • 如果您遇到任何提到旧的opencv_haartraining工具的教程(该工具已弃用,仍在使用OpenCV 1.x接口),请忽略该教程,并坚持使用opencv_traincascade工具。此工具是较新的版本,使用C++编写,符合OpenCV 2.x和OpenCV 3.x API。opencv_traincascade支持HAAR类小波特征[285]和LBP(局部二值模式)[164]特征。与HAAR特征产生浮点精度相比,LBP特征产生整数精度,因此使用LBP进行训练和检测比使用HAAR特征快几倍。关于LBP和HAAR检测质量,它主要取决于所使用的训练数据和所选择的训练参数。可以训练一个基于LBP的分类器,其质量几乎与基于HAAR的分类器相同,且训练时间只有一小部分。
  • OpenCV 2.x和OpenCV 3.x的较新的级联分类器检测接口(cv::CascadeClassifier)支持使用旧的和新的模型格式。如果由于某种原因您仍然使用旧接口,opencv_traincascade甚至可以保存(导出)以旧格式训练的级联。至少模型训练可以在最稳定的接口中完成。
  • opencv_traincascade应用程序可以使用TBB进行多线程处理。要在多核模式下使用它,OpenCV必须启用TBB支持进行构建。

训练数据准备

为了训练弱分类器的增强级联,我们需要一组正样本(包含您想要检测的实际对象)和一组负图像(包含您不想要检测的所有内容)。负样本集必须手动准备,而正样本集是使用opencv_createsamples应用程序创建的。

负样本

负样本取自任意图像,不包含您想要检测的对象。从这些负图像中生成的样本应该列在一个特殊的负图像文件中,每行包含一个图像路径(可以是绝对路径或相对路径)。请注意,负样本和样本图像也称为背景样本或背景图像,在本文件中可互换使用。

所描述的图像大小可能不同。但是,每个图像都应该等于或大于所需的训练窗口大小(这对应于模型尺寸,大多数情况下是您对象的平均大小),因为这些图像用于将给定的负图像二次采样成几个具有此训练窗口大小的图像样本。

此类负描述文件示例

目录结构

/img
img1.jpg
img2.jpg
bg.txt

文件 bg.txt

img/img1.jpg
img/img2.jpg

您的负窗口样本集将用于告诉机器学习步骤(在本例中为增强)在尝试查找您感兴趣的对象时不应查找什么。

正样本

正样本由opencv_createsamples应用程序创建。它们由增强过程用于定义模型在尝试查找您感兴趣的对象时实际应该查找什么。该应用程序支持两种生成正样本数据集的方法。

  1. 您可以从单个正对象图像生成大量正样本。
  2. 您可以自己提供所有正样本,只使用该工具将它们剪切出来、调整大小并将其放入opencv所需的二进制格式。

虽然第一种方法对于固定对象(如非常刚性的徽标)效果不错,但对于不太刚性的对象,它往往很快就会失败。在这种情况下,我们建议使用第二种方法。网络上的许多教程甚至指出,使用opencv_createsamples应用程序,100张真实对象图像可以比1000张人工生成的正样本产生更好的模型。但是,如果您确实决定采用第一种方法,请记住一些事项

  • 请注意,在将其提供给上述应用程序之前,您需要多个正样本,因为它只应用透视变换。
  • 如果您想要一个健壮的模型,请获取涵盖对象类别中可能出现的各种变化的样本。例如,在人脸的情况下,您应该考虑不同的种族和年龄组、情绪以及可能的胡须样式。这同样适用于使用第二种方法的情况。

第一种方法采用单个对象图像(例如公司徽标),通过随机旋转对象、更改图像强度以及将图像放置在任意背景上来从给定的对象图像创建大量正样本。随机性的数量和范围可以通过opencv_createsamples应用程序的命令行参数来控制。

命令行参数

  • -vec <vec_file_name>:包含用于训练的正样本的输出文件名。
  • -img <image_file_name>:源对象图像(例如,公司徽标)。
  • -bg <background_file_name>:背景描述文件;包含用作对象的随机变形版本的背景的图像列表。
  • -num <number_of_samples>:要生成的正样本数量。
  • -bgcolor <background_color>:背景颜色(目前假设为灰度图像);背景颜色表示透明颜色。由于可能存在压缩伪像,因此可以通过-bgthresh指定颜色容差量。bgcolor-bgthresh和bgcolor+bgthresh范围内的所有像素都被解释为透明的。
  • -bgthresh <background_color_threshold>
  • -inv:如果指定,颜色将被反转。
  • -randinv:如果指定,颜色将被随机反转。
  • -maxidev <max_intensity_deviation>:前景样本中像素的最大强度偏差。
  • -maxxangle <max_x_rotation_angle>:对x轴的最大旋转角度,必须以弧度给出。
  • -maxyangle <max_y_rotation_angle>:对y轴的最大旋转角度,必须以弧度给出。
  • -maxzangle <max_z_rotation_angle>:绕z轴的最大旋转角度,必须以弧度表示。
  • -show:有用的调试选项。如果指定,则会显示每个样本。按Esc键可在不显示每个样本的情况下继续样本创建过程。
  • -w <sample_width>:输出样本的宽度(以像素为单位)。
  • -h <sample_height>:输出样本的高度(以像素为单位)。

以这种方式运行opencv_createsamples时,将使用以下过程创建样本对象实例:给定的源图像绕所有三个轴随机旋转。所选角度受-maxxangle-maxyangle-maxzangle限制。然后,将强度在[bg_color-bg_color_threshold; bg_color+bg_color_threshold]范围内的像素解释为透明像素。将白噪声添加到前景的强度中。如果指定了-inv键,则前景像素强度将被反转。如果指定了-randinv键,则算法将随机选择是否应将反转应用于此样本。最后,将获得的图像放置到背景描述文件中的任意背景上,调整为由-w-h指定的所需大小,并存储到由-vec命令行选项指定的vec文件中。

正样本也可以从先前标记图像的集合中获得,这在构建鲁棒的对象模型时是理想的方法。此集合由类似于背景描述文件的文本文件描述。此文件的每一行对应于一个图像。该行的第一个元素是文件名,后跟对象注释的数量,然后是描述对象边界矩形坐标的数字(x、y、宽度、高度)。

描述文件示例

目录结构

/img
img1.jpg
img2.jpg
info.dat

文件 info.dat

img/img1.jpg 1 140 100 45 45
img/img2.jpg 2 100 200 50 50 50 30 25 25

图像img1.jpg包含单个对象实例,其边界矩形的坐标为:(140, 100, 45, 45)。图像img2.jpg包含两个对象实例。

为了从此集合创建正样本,应指定-info参数而不是-img参数。

  • -info <collection_file_name>:标记图像集合的描述文件。

请注意,在这种情况下,诸如-bg, -bgcolor, -bgthreshold, -inv, -randinv, -maxxangle, -maxyangle, -maxzangle之类的参数将被简单地忽略,不再使用。在这种情况下,样本创建方案如下:从给定的图像中获取对象实例,方法是从原始图像中剪切提供的边界框。然后将其调整为目标样本大小(由-w-h定义),并存储在由-vec参数定义的输出vec文件中。不应用任何变形,因此唯一影响的参数是-w-h-show-num

也可以使用opencv_annotation工具手动创建-info文件。这是一个开源工具,用于在任何给定图像中直观地选择对象实例的感兴趣区域。下一小节将更详细地讨论如何使用此应用程序。

附加说明

  • opencv_createsamples实用程序可用于检查任何给定正样本文件中存储的样本。为此,只需指定-vec-w-h参数。
  • vec文件的示例位于此处opencv/data/vec_files/trainingfaces_24-24.vec。它可用于使用以下窗口大小训练人脸检测器:-w 24 -h 24

使用OpenCV集成的标注工具

从OpenCV 3.x开始,社区一直在提供和维护一个开源标注工具,用于生成-info文件。如果构建了OpenCV应用程序,则可以通过命令opencv_annotation访问该工具。

使用该工具非常简单。该工具接受几个必需参数和一些可选参数。

  • --annotations (必需):要存储注释的注释txt文件的路径,然后将其传递给-info参数[示例 - /data/annotations.txt]
  • --images (必需):包含带有对象的图像的文件夹的路径[示例 - /data/testimages/]
  • --maxWindowHeight (可选):如果输入图像的高度大于此处给定的分辨率,则使用--resizeFactor调整图像大小以方便标注。
  • --resizeFactor (可选):使用--maxWindowHeight参数时用于调整输入图像大小的系数。

请注意,可选参数只能一起使用。下面可以看到可以使用的一个命令示例。

opencv_annotation --annotations=/path/to/annotations/file.txt --images=/path/to/image/folder/

此命令将启动一个窗口,其中包含第一张图像和您的鼠标光标,该光标将用于标注。有关如何使用标注工具的视频,请点击此处。基本上,有一些按键会触发操作。左鼠标按钮用于选择对象的第一个角点,然后继续绘制直到您满意为止,并在注册第二次左鼠标按钮单击时停止。每次选择后,您都有以下选择:

  • c:确认注释,将注释变为绿色并确认已存储。
  • d:删除注释列表中的最后一个注释(方便删除错误的注释)。
  • n:继续到下一张图像。
  • ESC:这将退出注释软件。

最后,您将获得一个可用的注释文件,可以将其传递给opencv_createsamples的-info参数。

级联训练

下一步是基于预先准备的正负数据集,实际训练增强弱分类器的级联。

按用途分组的opencv_traincascade应用程序的命令行参数

  • 常用参数
    • -data <cascade_dir_name>:应存储训练好的分类器的路径。此文件夹应事先手动创建。
    • -vec <vec_file_name>:包含正样本的vec文件(由opencv_createsamples实用程序创建)。
    • -bg <background_file_name>:背景描述文件。此文件包含负样本图像。
    • -numPos <number_of_positive_samples>:每个分类器阶段训练中使用的正样本数量。
    • -numNeg <number_of_negative_samples>:每个分类器阶段训练中使用的负样本数量。
    • -numStages <number_of_stages>:要训练的级联阶段数。
    • -precalcValBufSize <precalculated_vals_buffer_size_in_Mb>:预先计算的特征值缓冲区大小(以Mb为单位)。分配的内存越多,训练过程越快,但是请记住,-precalcValBufSize-precalcIdxBufSize的总和不应超过您可用的系统内存。
    • -precalcIdxBufSize <预计算索引缓冲区大小(Mb)>:预计算特征索引的缓冲区大小(以Mb为单位)。分配的内存越大,训练过程越快,但是请记住,-precalcValBufSize-precalcIdxBufSize 的总和不应超过系统可用内存。
    • -baseFormatSave:此参数仅在使用 Haar-like 特征时有效。如果指定此参数,则级联将以旧格式保存。这仅出于向后兼容性考虑,并允许使用旧版弃用接口的用户至少可以使用新接口训练模型。
    • -numThreads <最大线程数>:训练过程中使用的最大线程数。请注意,根据您的机器和编译选项,实际使用的线程数可能较少。默认情况下,如果您使用 TBB 支持构建了 OpenCV(此优化需要 TBB 支持),则会选择最大可用线程。
    • -acceptanceRatioBreakValue <中断值>:此参数用于确定模型应该保持学习的精度以及何时停止。一个好的指导原则是,训练不要超过 10e-5,以确保模型不会在训练数据上过拟合。默认情况下,此值设置为 -1 以禁用此功能。
  • 级联参数
    • -stageType <BOOST(默认)>:阶段类型。目前仅支持提升型分类器作为阶段类型。
    • -featureType <{HAAR(默认), LBP}>:特征类型:HAAR - Haar-like 特征,LBP - 局部二值模式。
    • -w <样本宽度>:训练样本的宽度(以像素为单位)。必须与创建训练样本时使用的值(opencv_createsamples 实用程序)完全相同。
    • -h <样本高度>:训练样本的高度(以像素为单位)。必须与创建训练样本时使用的值(opencv_createsamples 实用程序)完全相同。
  • 提升型分类器参数
    • -bt <{DAB, RAB, LB, GAB(默认)}>:提升型分类器的类型:DAB - 离散 AdaBoost,RAB - 实数 AdaBoost,LB - LogitBoost,GAB - Gentle AdaBoost。
    • -minHitRate <最小命中率>:分类器每个阶段的最小期望命中率。总命中率可以估计为 (最小命中率 ^ 阶段数),[286] §4.1。
    • -maxFalseAlarmRate <最大误报率>:分类器每个阶段的最大期望误报率。总误报率可以估计为 (最大误报率 ^ 阶段数),[286] §4.1。
    • -weightTrimRate <权重修剪率>:指定是否应使用修剪以及其权重。一个不错的选择是 0.95。
    • -maxDepth <弱树的最大深度>:弱树的最大深度。一个不错的选择是 1,即树桩的情况。
    • -maxWeakCount <弱树的最大数量>:每个级联阶段的弱树的最大数量。提升型分类器(阶段)将拥有所需数量的弱树(<=maxWeakCount),以达到给定的-maxFalseAlarmRate
  • Haar-like 特征参数
    • -mode <BASIC (默认) | CORE | ALL>:选择训练中使用的 Haar 特征集类型。BASIC 只使用直立特征,而 ALL 使用完整的直立和 45 度旋转特征集。有关更多详细信息,请参见 [167]
  • 局部二值模式参数:局部二值模式没有参数。

opencv_traincascade 应用程序完成其工作后,训练好的级联将保存在 -data 文件夹中的 cascade.xml 文件中。此文件夹中的其他文件是为中断训练的情况创建的,因此您可以在训练完成后删除它们。

训练完成,您可以测试您的级联分类器了!

可视化级联分类器

有时,可视化训练好的级联可能很有用,以便查看它选择了哪些特征以及它的阶段有多复杂。为此,OpenCV 提供了一个 opencv_visualisation 应用程序。此应用程序具有以下命令

  • --image (必需):对象模型的参考图像路径。这应该是具有 [-w,-h] 维度的注释,如传递给 opencv_createsamples 和 opencv_traincascade 应用程序一样。
  • --model (必需):训练好的模型路径,该路径应位于提供给 opencv_traincascade 应用程序的 -data 参数的文件夹中。
  • --data (可选):如果提供了一个数据文件夹(需要预先手动创建),则阶段输出和特征视频将被存储。

下面可以看到一个示例命令

opencv_visualisation --image=/data/object.png --model=/data/model.xml --data=/data/result/

当前可视化工具的一些限制

  • 仅处理使用 opencv_traincascade 工具训练的级联分类器模型,其中包含树桩作为决策树[默认设置]。
  • 提供的图像需要是一个样本窗口,其原始模型尺寸与传递给--image参数的尺寸相同。

在给定的安吉丽娜·朱莉窗口上运行的 HAAR/LBP 面部模型示例,该窗口具有与级联分类器文件相同的预处理 -> 24x24 像素图像,灰度转换和直方图均衡。

为每个阶段制作一个视频,其中可视化每个特征。

每个阶段都存储为一个图像,以便将来验证特征。

这项工作是为 OpenCV 3 Blueprints 由 Steven Puttemans 创建的,但 Packt Publishing 同意将其集成到 OpenCV 中。