您的位置:首页 > 运维架构

OpenCV的人脸检测:cvRunHaarClassifierCascade函数解析

2013-07-22 14:51 513 查看


转自:http://www.cnblogs.com/freecloudinsky/archive/2013/05/20/3088890.html


OpenCV的人脸检测:cvRunHaarClassifierCascade函数解析

2013-05-20 16:55 by freecloudinsky, 24 阅读, 0 评论, 收藏编辑


cvRunHaarClassifierCascade的:转载:http://2000liuzhenxing.blog.163.com/blog/static/51677475200981952828662/


最近学习OpenCV的人脸检测,有cvHaarDetectObjects,此函数中又有两个函数很重要,一个cvRunHaarClassifierCascade,另一个cvSetImagesForHaarClassifierCascade。这两个函数很重要,上网看到了,就把它转过来了,希望对大家有帮助。

//此函数是一个匹配函数,根据不同的分类器(tree、stump)进行不同的匹配,返回整形值

CV_IMPL int
cvRunHaarClassifierCascade( CvHaarClassifierCascade* _cascade,
                            CvPoint pt, int start_stage )
{
    int result = -1;
    CV_FUNCNAME(”cvRunHaarClassifierCascade”);


    __BEGIN__;


    int p_offset, pq_offset;
    int i, j;
    double mean, variance_norm_factor;
    CvHidHaarClassifierCascade* cascade;


    if( !CV_IS_HAAR_CLASSIFIER(_cascade) )
        CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, “Invalid cascade pointer” );


    cascade = _cascade->hid_cascade;
    if( !cascade )
        CV_ERROR( CV_StsNullPtr, “Hidden cascade has not been created.\n”
            “Use cvSetImagesForHaarClassifierCascade” );


    if( pt.x < 0 || pt.y < 0 ||
        pt.x + _cascade->real_window_size.width >= cascade->sum.width-2 ||
        pt.y + _cascade->real_window_size.height >= cascade->sum.height-2 )                   //超边退出
        EXIT;


    p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x;
    pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x;
    mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area;
    variance_norm_factor = cascade->pq0[pq_offset] – cascade->pq1[pq_offset] -                //左上+右下-右上-左下
                           cascade->pq2[pq_offset] + cascade->pq3[pq_offset];
    variance_norm_factor = variance_norm_factor*cascade->inv_window_area – mean*mean;      //求方差(varance) =Ex2-(Ex)2
    if( variance_norm_factor >= 0. )
        variance_norm_factor = sqrt(variance_norm_factor);
    else
        variance_norm_factor = 1.;


    if( cascade->is_tree )           //是树形的分类器,就按照层来匹配.
    {
        CvHidHaarStageClassifier* ptr;
        assert( start_stage == 0 );                      //start_stage==0继续


        result = 1;
        ptr = cascade->stage_classifier;


        while( ptr )
        {
            double stage_sum = 0;


            for( j = 0; j < ptr->count; j++ )
            {
                stage_sum += icvEvalHidHaarClassifier( ptr->classifier + j,     //层判断
                    variance_norm_factor, p_offset );
            }


            if( stage_sum >= ptr->threshold )
            {
                ptr = ptr->child;               //层判断通过,到下一层.
            }
            else
            {
                while( ptr && ptr->next == NULL ) ptr = ptr->parent;              //未通过,且当前子分类器没有同层分类器,没有返回上层
                if( ptr == NULL )              //如果刚才已经是最顶层了.
                {
                    result = 0;                  //返回0,退出.
                    EXIT;
                }
                ptr = ptr->next;               //指向下一个分类器.
            }
        }
    }
    else if( cascade->is_stump_based )              //如果是stump类的分类器
    {
        for( i = start_stage; i < cascade->count; i++ )
        {
            double stage_sum = 0;


            if( cascade->stage_classifier[i].two_rects )
            {
                for( j = 0; j < cascade->stage_classifier[i].count; j++ )
                {
                    CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
                    CvHidHaarTreeNode* node = classifier->node;
                    double sum, t = node->threshold*variance_norm_factor, a, b;


                    sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
                    sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;


                    a = classifier->alpha[0];
                    b = classifier->alpha[1];
                    stage_sum += sum < t ? a : b;
                }
            }
            else
            {
                for( j = 0; j < cascade->stage_classifier[i].count; j++ )
                {
                    CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j;
                    CvHidHaarTreeNode* node = classifier->node;
                    double sum, t = node->threshold*variance_norm_factor, a, b;


                    sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight;
                    sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight;


                    if( node->feature.rect[2].p0 )
                        sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight;


                    a = classifier->alpha[0];
                    b = classifier->alpha[1];
                    stage_sum += sum < t ? a : b;
                }
            }


            if( stage_sum < cascade->stage_classifier[i].threshold )
            {                   //没通过.则返回负的没通过的分类器数.
                result = -i;
                EXIT;
            }
        }
    }
    else                    //如果不是那两种强分类器
    {
        for( i = start_stage; i < cascade->count; i++ )
        {
            double stage_sum = 0;


            for( j = 0; j < cascade->stage_classifier[i].count; j++ )
            {
                stage_sum += icvEvalHidHaarClassifier(
                    cascade->stage_classifier[i].classifier + j,
                    variance_norm_factor, p_offset );
            }


            if( stage_sum < cascade->stage_classifier[i].threshold )
            {
                result = -i;
                EXIT;
            }
        }
    }


    result = 1;


    __END__;


    return result;     //返回结果
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: