OpenCV3.1.0级联分类器训练与使用

时间:2022-05-07
本文章向大家介绍OpenCV3.1.0级联分类器训练与使用,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

OpenCV3.1.0级联分类器训练与使用

级联分类器第一次出现是由Viola-Jones在2001时候提出,其主要用来实现实时人脸检测,通过加载已经训练好的级联分类器数据,实现快速的级联分类器过滤,达到实时检测。这个过程可以表示如下:

其主要思想是首先通过一些简单的HAAR/LBP特征来快速过滤掉大多数非目标区域,然后通过迭代的方式不断添加特征数目从而达到高识别率,低拒绝率。在计算HAAR特征数据时候采用积分图像实现快速计算,最终实现整个过程的实时快速。在整个检测过程中训练好的级联分类器数据作用直接决定着对象检测率。

OpenCV中自带的HAAR/LBP级联检测器的数据多数都是关于人脸检测的,而在实际项目应用中,我们可能需要从不同的场景中检测某个相同对象,这种需求可以通过OpenCV中HAAR/LBP级联分类器训练工具来生成自己的级联分类器数据,然后通过程序实现自定义对象检测。而要想实现这个过程需要如下几步

一:样本数据准备

正样本

正样本要做到格式与大小一致,如果有背景的话,背景尽量统一,建议处理为黑色。正样本最少的集合在200张图片左右,然后必须有一个文本描述文件,总结起来如下图所示:

有了样本数据之后,可以通过OpenCV3.1.0中自带的工具opencv_createsamples.exe来生成正样本的.vec文件,通过命令行调用该工具即可,具体执行步骤如下:

负样本

负样本图像尽量要选取不同尺寸,不同背景的,但是里面不包含检测对象的图像,来源有两个 一是自己从网上获取,下载 二是从本地相册中选择,然后适当的裁剪 最终形成的负样本数据列表文本文件大致如下:

二:训练级联分类器

使用OpenCV3.1中自带的opencv_traincascade.exe工具输入适当的参数即可进行样本训练,在进行样本训练过程中会生成一些列的中间数据,格式均为XML,如果输入的参数适当,最终会完成样本训练得到cascade.xml文件,它就是级联分类器特征数据,通过程序加载它,然后调用OpenCV中级联分类器相关API即可实现对象分类检测。样本训练执行命令如下:

参数说明如下:

-numPos

表示每个Stage的正样本数目,必须小于总正样本数

-numNeg

表示每个Stage的负样本数目,可以大于等于总负样本数目

-featureType

表示特征类型,当前OpenCV3.x只支持HAAR与LBP

-numStages

表示多少个Stage,Stage的多少跟样本有直接关系。Stage数目过多,样本不足会导致训练无法继续进行。

-w

表示正样本的宽度,必须与创建vec文件时声明中保持一致

-h

表示正样本的高度,必须与创建vec文件时声明中保持一致

-minHitRate

表示最小命中率,用来衡量每层训练目标准确度

-maxFalseAlarmRate

最大虚警率(误检率),虚警过小可能导致特征过拟合,训练效果不好。默认是0.5

在正负样本1:1或者1:10的时候训练效果都不会太好,一般负数目应该是正样本数目的3~5倍左右。

三:常见错误分析

-Train dataset for temp stage can not be filled. Branch training terminated

出现这个错误的原因是正样本数据不够,而声明的Stage数目过多,解决这个问题一是增加样本数量,二是减小Stage数目。或者还有可能是负样本数据不足,或者样本数据的路径不正确。

-Traincascade Error: Bad argument (Can not get new positive sample. Themost possible reason is insufficient count of samples in given vec-file)

原因是训练时候-numPos 参数设置的正样本数目超过或者等于了总正样本数

四:使用训练数据的代码演示

小编采集了185个人脸图片,224个负样本图片,都来自互联网上。分别采用HAAR与LBP级联训练得到的级联分类器数据,演示效果如下:

代码如下

#include <opencv2/opencv.hpp>#include <iostream>using namespace cv;using namespace std;String face_cascade_name = "D:/vcprojects/cascadetrain/custom_face_cascade.xml";CascadeClassifier customFaceDetector;String window_name = "Capture - Face detection";int main(int argc, char** argv) {    // 加载训练数据    if (!customFaceDetector.load(face_cascade_name)) {        printf("could not load face data...n");    }    // 加载测试图片    std::vector<Rect> faces;    Mat gray_src;    Mat  src = imread("D:/testface.jpg");    // 转换为灰度图像    cvtColor(src, gray_src, COLOR_BGR2GRAY);    equalizeHist(gray_src, gray_src);    // 使用自己训练的级联检测器人脸检测    customFaceDetector.detectMultiScale(gray_src, faces, 1.3, 1, 0, Size(24, 24));    for (size_t t = 0; t < faces.size(); t++) {        rectangle(src, faces[t], Scalar(0, 0, 255), 3);    }    // 显示结果    namedWindow(window_name, CV_WINDOW_AUTOSIZE);    imshow(window_name, src);    // 按任意键退出    waitKey(0);    return 0;}