cvhaar.cpp.svn-base

来自「非结构化路识别」· SVN-BASE 代码 · 共 1,285 行 · 第 1/4 页

SVN-BASE
1,285
字号

    if( !cascade )
        CV_ERROR( CV_StsNullPtr, "" );

    if( cascade->headerSize != sizeof(*cascade))
        CV_ERROR( CV_StsNullPtr, "Invalid CvHidHaarClassifierCascade header" );

    if( pt.x < 0 || pt.y < 0 ||
        pt.x + cascade->realWindowSize.width >= cascade->sum.width-2 ||
        pt.y + cascade->realWindowSize.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->invWindowArea;
    variance_norm_factor = cascade->pq0[pq_offset] - cascade->pq1[pq_offset] -
                           cascade->pq2[pq_offset] + cascade->pq3[pq_offset];
    variance_norm_factor = 
        /*1.*/sqrt(variance_norm_factor*cascade->invWindowArea - mean*mean);

    if( cascade->is_stump_based )
    {
        for( i = start_stage; i < cascade->count; i++ )
        {
            double stage_sum = 0;

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

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

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

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

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

                    stage_sum += classifier->alpha[sum >= t];
                }
            }

            if( stage_sum < cascade->stageClassifier[i].threshold - 0.0001 )
            {
                result = -i;
                EXIT;
            }
        }
    }
    else
    {
        for( i = start_stage; i < cascade->count; i++ )
        {
            double stage_sum = 0;

            for( j = 0; j < cascade->stageClassifier[i].count; j++ )
            {
                CvHidHaarClassifier* classifier = cascade->stageClassifier[i].classifier + j;
                double sum, t;// t = classifier->threshold*variance_norm_factor;
                int idx;

                idx = 0;
                do 
                {
                    t = classifier->threshold[idx] * variance_norm_factor;

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

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

                    idx = ( sum < t ) ? classifier->left[idx] : classifier->right[idx];

                }
                while( idx > 0 );

                stage_sum += classifier->alpha[-idx];
            }

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

    result = 1;

    __END__;

    return result;
}


static int is_equal( const void* _r1, const void* _r2, void* )
{
    const CvRect* r1 = (const CvRect*)_r1;
    const CvRect* r2 = (const CvRect*)_r2;
    int distance = cvRound(r1->width*0.2);

    return r2->x <= r1->x + distance &&
           r2->x >= r1->x - distance &&
           r2->y <= r1->y + distance &&
           r2->y >= r1->y - distance &&
           r2->width <= cvRound( r1->width * 1.2 ) &&
           cvRound( r2->width * 1.2 ) >= r1->width;
}


CV_IMPL CvSeq*
cvHaarDetectObjects( const IplImage* img,
                     CvHidHaarClassifierCascade* hid_cascade,
                     CvMemStorage* storage, double scale_factor,
                     int min_neighbors, int flags )
{
    int split_stage = 2;
    CvSize size = cvGetSize( img ), sumsize = { size.width + 1, size.height + 1 };
    IplImage *temp = 0, *sum = 0, *tilted = 0, *sqsum = 0;
    IplImage *sumcanny = 0;
    CvSeq* seq = 0;
    CvSeq* seq2 = 0;
    CvSeq* idx_seq = 0;
    CvSeq* result_seq = 0;
    CvMemStorage* temp_storage = 0;
    CvAvgComp* comps = 0;
    int ncomp;
    int do_canny_pruning = flags & CV_HAAR_DO_CANNY_PRUNING;
    
    CV_FUNCNAME( "cvDetectFaces" );

    __BEGIN__;

    double factor;
    int i, npass = 2;
    int hid_cascade_count0;

    if( !CV_IS_IMAGE(img) )
        CV_ERROR( CV_StsBadArg, "Invalid source image" );

    if( !hid_cascade || hid_cascade->headerSize != sizeof(*hid_cascade))
        CV_ERROR( CV_StsBadArg, "Invalid classifier cascade" );

    if( !storage )
        CV_ERROR( CV_StsNullPtr, "Null storage pointer" );

    temp = cvCreateImage( size, 8, 1 );
    sum = cvCreateImage( sumsize, IPL_DEPTH_32S, 1 );
    sqsum = cvCreateImage( sumsize, IPL_DEPTH_64F, 1 );
    temp_storage = cvCreateChildMemStorage( storage );

    if( hid_cascade->has_tilted_features )
        tilted = cvCreateImage( sumsize, IPL_DEPTH_32S, 1 );

    seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvRect), temp_storage );
    seq2 = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), temp_storage );
    result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), storage );

    if( min_neighbors == 0 )
        seq = result_seq;

    if( img->nChannels == 3 )
    {
        cvCvtColor( img, temp, CV_BGR2GRAY );
        img = temp;
    }
    
    cvIntegral( img, sum, sqsum, tilted );
    
    if( do_canny_pruning )
    {
        sumcanny = cvCreateImage( sumsize, IPL_DEPTH_32S, 1 );
        cvCanny( img, temp, 0, 50, 3 );
        cvIntegral( temp, sumcanny );
    }
    
    hid_cascade_count0 = hid_cascade->count;

    if( split_stage >= hid_cascade_count0 || split_stage == 0 )
    {
        split_stage = hid_cascade_count0;
        npass = 1;
    }

    for( factor = 1; factor*hid_cascade->origWindowSize.width <
         MIN( size.width - 10, size.height - 10 ); factor *= scale_factor )
    {
        double const ystep = MAX( 2, factor );
        
        CvSize winSize = cvSize( cvRound( hid_cascade->origWindowSize.width * factor ),
                                 cvRound( hid_cascade->origWindowSize.height * factor ));
        CvRect equ_rect = { 0, 0, 0, 0 };
        int *p0 = 0, *p1 = 0, *p2 = 0, *p3 = 0;
        int *pq0 = 0, *pq1 = 0, *pq2 = 0, *pq3 = 0;
        int pass, stage_offset = 0;
        int stopHeight = cvRound((size.height - winSize.height - ystep) / ystep);

        cvSetImagesForHaarClassifierCascade( hid_cascade, sum, sqsum, tilted, factor );
        cvZero( temp );

        if( do_canny_pruning )
        {
            equ_rect.x = cvRound(winSize.width*0.3);
            equ_rect.y = cvRound(winSize.height*0.3);
            equ_rect.width = cvRound(winSize.width*0.7);
            equ_rect.height = cvRound(winSize.height*0.7);

            p0 = (int*)(sumcanny->imageData + equ_rect.y*sumcanny->widthStep) + equ_rect.x;
            p1 = (int*)(sumcanny->imageData + equ_rect.y*sumcanny->widthStep)
                        + equ_rect.x + equ_rect.width;
            p2 = (int*)(sumcanny->imageData + (equ_rect.y + equ_rect.height)*sumcanny->widthStep) + equ_rect.x;
            p3 = (int*)(sumcanny->imageData + (equ_rect.y + equ_rect.height)*sumcanny->widthStep)
                        + equ_rect.x + equ_rect.width;

            pq0 = (int*)(sum->imageData + equ_rect.y*sum->widthStep) + equ_rect.x;
            pq1 = (int*)(sum->imageData + equ_rect.y*sum->widthStep)
                        + equ_rect.x + equ_rect.width;
            pq2 = (int*)(sum->imageData + (equ_rect.y + equ_rect.height)*sum->widthStep) + equ_rect.x;
            pq3 = (int*)(sum->imageData + (equ_rect.y + equ_rect.height)*sum->widthStep)
                        + equ_rect.x + equ_rect.width;
        }

        hid_cascade->count = split_stage;

        for( pass = 0; pass < npass; pass++ )
        {
#ifdef _OPENMP
    #pragma omp parallel for shared(hid_cascade, stopHeight, seq, ystep, temp, size, winSize, pass, npass, sum, p0, p1, p2 ,p3, pq0, pq1, pq2, pq3, stage_offset) 
#endif // _OPENMP

            for( int yInt = 0; yInt < stopHeight; yInt++ )
            {
                int iy = cvRound(yInt*ystep);
                int xIntStep = 1;
                int xInt, stopWidth = cvRound((size.width - winSize.width - 2*ystep) / ystep);

                char* mask_row = temp->imageData + temp->widthStep * iy;

                for( xInt = 0; xInt < stopWidth; xInt += xIntStep )
                {
                    int ix = cvRound(xInt*ystep);
                    
                    if( pass == 0 )
                    {
                        int result;

                        xIntStep = 2;

                        if( do_canny_pruning )
                        {
                            int offset;
                            int s, sq;
                        
                            offset = iy*(sum->widthStep/sizeof(p0[0])) + ix;
                            s = p0[offset] - p1[offset] - p2[offset] + p3[offset];
                            sq = pq0[offset] - pq1[offset] - pq2[offset] + pq3[offset];
                            if( s < 100 || sq < 20 )
                                continue;
                        }

                        result = cvRunHaarClassifierCascade( hid_cascade, cvPoint(ix,iy),
                                                             0/*stage_offset*/ );
#ifdef _OPENMP
#pragma omp critical
#endif
                        if( result > 0 )
                        {
                            if( pass < npass - 1 )
                            {
                                mask_row[ix] = 1;
                            }
                            else
                            {
                                CvRect rect = cvRect(ix,iy,winSize.width,winSize.height);
                                cvSeqPush( seq, &rect );
                            }
                        }
                        if( result < 0 )
                            xIntStep = 1;
                    }
                    else if( mask_row[ix] )
                    {
                        int result = cvRunHaarClassifierCascade( hid_cascade, cvPoint(ix,iy),
                                                                 stage_offset );
#ifdef _OPENMP
#pragma omp critical
#endif
                        if( result > 0 )
                        {
                            if( pass == npass - 1 )
                            {
                                CvRect rect = cvRect(ix,iy,winSize.width,winSize.height);
                                cvSeqPush( seq, &rect );
                            }
                        }
                        else
                            mask_row[ix] = 0;
                    }
                }
            }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?