OpenCV每日函数 Object Detection目标检测模块 (1) 用于目标检测的级联分类器

一、概述

        下面描述的目标检测器最初由 Paul Viola  提出,并由 Rainer Lienhart改进。

        保罗维奥拉和迈克尔 J. 琼斯。 使用增强级联的简单特征进行快速对象检测。 在计算机视觉和模式识别中,2001 年。CVPR 2001。2001 年 IEEE 计算机学会会议论文集,第 1 卷,第 I-511 页。 IEEE,2001 年。

        Rainer Lienhart 和 Jochen Maydt。 一组扩展的类似 haar 的特征,用于快速对象检测。 在图像处理中。 2002. 诉讼。 2002 年国际会议,第 1 卷,第 I-900 页。 IEEE,2002 年。

        首先,分类器(即使用类似 haar 的特征的增强分类器的级联)使用特定对象(即人脸或汽车)的数百个样本视图(称为正样本)进行训练,这些样本视图被缩放到相同的 大小(例如,20x20)和反例 - 相同大小的任意图像。

        训练分类器后,可以将其应用于输入图像中的感兴趣区域(与训练期间使用的大小相同)。 如果该区域可能显示对象(即人脸/汽车),则分类器输出“1”,否则输出“0”。 要在整个图像中搜索对象,可以在图像上移动搜索窗口并使用分类器检查每个位置。 分类器的设计使其可以轻松“调整大小”,以便能够找到不同大小的感兴趣对象,这比调整图像本身的大小更有效。 因此,要在图像中找到一个未知大小的对象,扫描过程应该在不同的尺度上进行多次。

        分类器名称中的“级联”一词意味着生成的分类器由几个更简单的分类器(阶段)组成,这些分类器随后应用于感兴趣的区域,直到在某个阶段候选被拒绝或所有阶段都通过。 “提升”这个词意味着级联每个阶段的分类器本身都是复杂的,它们是使用四种不同的提升技术(加权投票)中的一种由基本分类器构建的。 目前支持 Discrete Adaboost、Real Adaboost、Gentle Adaboost 和 Logitboost。 基本分类器是至少有 2 个叶子的决策树分类器。 Haar 类特征是基本分类器的输入,其计算方法如下所述。 当前算法使用以下类似 Haar 的特征:

        特定分类器中使用的特征由其形状(1a、2b 等)、感兴趣区域内的位置和尺度(这个尺度与检测阶段使用的尺度不同,尽管这两个尺度是 倍增)。 例如,在第三条线特征(2c)的情况下,响应计算为覆盖整个特征(包括中间的两条白色条纹和黑色条纹)的矩形下的图像像素之和与 黑色条纹下的图像像素总和乘以 3,以补偿区域大小的差异。 使用积分图像快速计算矩形区域上的像素值总和(见下文和积分描述)。

        在新的 C++ 接口中,除了类似 Haar 的功能外,还可以使用 LBP(本地二进制模式)功能。 .. [Viola01] Paul Viola 和 Michael J. Jones。 使用增强的简单特征级联进行快速目标检测。 IEEE CVPR,2001。

二、类参考

1、函数原型

        这里描述两个主要的函数

Ptr< BaseCascadeClassifier::MaskGenerator > 	cv::createFaceDetectionMaskGenerator ()

void cv::CascadeClassifier::detectMultiScale	(	InputArray 	image,
std::vector< Rect > & 	objects,
double 	scaleFactor = 1.1,
int 	minNeighbors = 3,
int 	flags = 0,
Size 	minSize = Size(),
Size 	maxSize = Size() 
)	

2、参数详解 

image CV_8U 类型的矩阵,包含检测到对象的图像。
objects 矩形向量,其中每个矩形包含检测到的对象,矩形可能部分位于原始图像之外。
scaleFactor 指定在每个图像比例下图像大小减小多少的参数。
minNeighbors 参数指定每个候选矩形应该有多少个邻居来保留它。
flags 与函数 cvHaarDetectObjects 中的旧级联具有相同含义的参数。 它不用于新的级联。
minSize 最小可能的对象大小。 小于该值的对象将被忽略。
maxSize 最大可能的对象大小。 大于该值的对象将被忽略。 如果 maxSize == minSize 模型在单一尺度上进行评估。

三、OpenCV源码

1、源码路径

opencv\modules\objdetect\src\cascadedetect.cpp

2、源码代码

        部分源码如下

bool CascadeClassifierImpl::load(const String& filename)
{
    oldCascade.release();
    data = Data();
    featureEvaluator.release();

    FileStorage fs(filename, FileStorage::READ);
    if( !fs.isOpened() )
        return false;

    FileNode fs_root = fs.getFirstTopLevelNode();

    if( read_(fs_root) )
        return true;

    // probably, it's the cascade in the old format;
    // let's try to convert it to the new format
    FileStorage newfs(".yml", FileStorage::WRITE+FileStorage::MEMORY);
    haar_cvt::convert(fs_root, newfs);
    std::string newfs_content = newfs.releaseAndGetString();
    newfs.open(newfs_content, FileStorage::READ+FileStorage::MEMORY);
    fs_root = newfs.getFirstTopLevelNode();

    if( read_(fs_root) )
        return true;

    return false;
}
void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
                                          std::vector<int>& rejectLevels,
                                          std::vector<double>& levelWeights,
                                          double scaleFactor, int minNeighbors,
                                          int /*flags*/, Size minObjectSize, Size maxObjectSize,
                                          bool outputRejectLevels )
{
    CV_INSTRUMENT_REGION();

    CV_Assert( scaleFactor > 1 && _image.depth() == CV_8U );

    if( empty() )
        return;

    detectMultiScaleNoGrouping( _image, objects, rejectLevels, levelWeights, scaleFactor, minObjectSize, maxObjectSize,
                                outputRejectLevels );
    const double GROUP_EPS = 0.2;
    if( outputRejectLevels )
    {
        groupRectangles( objects, rejectLevels, levelWeights, minNeighbors, GROUP_EPS );
    }
    else
    {
        groupRectangles( objects, minNeighbors, GROUP_EPS );
    }
}
void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
                                          double scaleFactor, int minNeighbors,
                                          int flags, Size minObjectSize, Size maxObjectSize)
{
    CV_INSTRUMENT_REGION();

    std::vector<int> fakeLevels;
    std::vector<double> fakeWeights;
    detectMultiScale( _image, objects, fakeLevels, fakeWeights, scaleFactor,
        minNeighbors, flags, minObjectSize, maxObjectSize );
}

void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
                                          std::vector<int>& numDetections, double scaleFactor,
                                          int minNeighbors, int /*flags*/, Size minObjectSize,
                                          Size maxObjectSize )
{
    CV_INSTRUMENT_REGION();

    Mat image = _image.getMat();
    CV_Assert( scaleFactor > 1 && image.depth() == CV_8U );

    if( empty() )
        return;

    std::vector<int> fakeLevels;
    std::vector<double> fakeWeights;

    detectMultiScaleNoGrouping( image, objects, fakeLevels, fakeWeights, scaleFactor, minObjectSize, maxObjectSize );
    const double GROUP_EPS = 0.2;
    groupRectangles( objects, numDetections, minNeighbors, GROUP_EPS );
}

四、效果图像示例

Opencv学习笔记 CascadeClassifier人脸检测_坐望云起的博客-CSDN博客_cascadeclassifierHaar Cascade算法是 OpenCV中最强大的对象检测算法之一,特别是人脸检测,由 Michael Jones 和 Paul Viola 在他们的研究论文“Rapid Object Detection using a Boosted Cascade of Simple Features”中提出,该算法在2001年,它使用一个称为级联函数的函数来检测图像中的对象,并且使用大量的负图像和正图像来训练这个级联函数,这个级联函数返回的图像是在图像中的人脸周围绘制的矩形做为输出。https://skydance.blog.csdn.net/article/details/108762374

猜你喜欢

转载自blog.csdn.net/bashendixie5/article/details/125297997
今日推荐