cvhaar.cpp.svn-base

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

SVN-BASE
1,285
字号
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

/* Haar features calculation */

#include "_cvaux.h"

#include <float.h>
#include <stdio.h>
#include "_cvutils.h"

/* these settings affect the quality of detection: change with care */
#define CV_ADJUST_FEATURES 1
#define CV_ADJUST_WEIGHTS  0

typedef int sumtype;
typedef double sqsumtype;

typedef struct CvHidHaarFeature
{
    struct
    {
        sumtype *p0, *p1, *p2, *p3;
        float weight;
    }
    rect[CV_HAAR_FEATURE_MAX];
}
CvHidHaarFeature;


typedef struct CvHidHaarClassifier
{
    int count;
    CvHaarFeature* origFeature;
    CvHidHaarFeature* feature;
    float* threshold;
    int* left;
    int* right;
    float* alpha;
}
CvHidHaarClassifier;


typedef struct CvHidHaarStageClassifier
{
    int  count;
    float threshold;
    CvHidHaarClassifier* classifier;
    int two_rects;
}
CvHidHaarStageClassifier;


struct CvHidHaarClassifierCascade
{
    int  headerSize;
    int  count;
    int  is_stump_based;
    int  has_tilted_features;
    CvSize origWindowSize;
    CvSize realWindowSize;
    double scale, invWindowArea;
    CvHidHaarStageClassifier* stageClassifier;
    CvMat sum;
    CvMat tiltedSum;
    CvMat sqsum;
    sqsumtype *pq0, *pq1, *pq2, *pq3;
    sumtype *p0, *p1, *p2, *p3;
};


static const char* numSuffix( int i )
{
    switch( i % 10 )
    {
    case 1: return "st";
    case 2: return "nd";
    case 3: return "rd";
    default: return "th";
    }
}


static void
updateRealWindowSize( CvHidHaarClassifierCascade* cascade, double scale )
{
    assert( cascade != 0 && cascade->headerSize == sizeof(*cascade));
    
    cascade->scale = scale;
    cascade->realWindowSize =
        cvSize( cvRound( cascade->origWindowSize.width * scale ),
                cvRound( cascade->origWindowSize.height * scale ));
}


/* create faster internal representation of haar classifier cascade */
CV_IMPL CvHidHaarClassifierCascade*
cvCreateHidHaarClassifierCascade( CvHaarClassifierCascade* cascade,
                                  const CvArr* sumImage,
                                  const CvArr* sqSumImage,
                                  const CvArr* tiltedSumImage,
                                  double scale )
{
    CvHidHaarClassifierCascade* out = 0;

    CV_FUNCNAME("cvCreateHidHaarClassifierCascade");

    __BEGIN__;

    int i, j, k, l;
    int pos;
    int datasize = sizeof(CvHidHaarClassifierCascade);
    int total = 0;
    int nodes = 0;
    int nodepos = 0;
    int alphapos = 0;
    int nodecount = 0;
    char errorstr[100];
    CvHaarFeature* haarFeature0;
    CvHidHaarFeature* hidHaarFeature0;
    float* threshold0;
    int* left0;
    int* right0;
    float* alpha0;
    CvHidHaarClassifier* classifier0;
    CvSize origWindowSize;
    int has_tilted_features = 0;

    if( !cascade || !cascade->stageClassifier )
        CV_ERROR( CV_StsNullPtr, "" );

    if( cascade->count <= 0 )
        CV_ERROR( CV_StsOutOfRange, "Negative classifier counter" );
    
    origWindowSize = cascade->origWindowSize;

    if( origWindowSize.width <= 0 || origWindowSize.height <= 0 )
        CV_ERROR( CV_StsBadSize, "Negative original window width or height" );

    if( scale <= 0 )
        CV_ERROR( CV_StsOutOfRange, "Scale must be positive" );

    /* check input structure correctness and calculate total memory size needed for
       internal representation of the classifier cascade */
    for( i = 0; i < cascade->count; i++ )
    {
        CvHaarStageClassifier* stageClassifier = cascade->stageClassifier + i;

        if( !stageClassifier->classifier ||
            stageClassifier->count <= 0 )
        {
            sprintf( errorstr, "%d-%s stage classifier header is invalid "
                     "(has null pointers or non-positive classfier count)",
                     i, numSuffix(i));
            CV_ERROR( CV_StsNullPtr, errorstr );
        }

        total += stageClassifier->count;

        for( j = 0; j < stageClassifier->count; j++ )
        {
            CvHaarClassifier* classifier = stageClassifier->classifier + j;

            nodes += classifier->count;
            for( l = 0; l < classifier->count; l++ )
            {
                for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ )
                {
                    if( classifier->haarFeature[l].rect[k].weight )
                    {
                        CvRect r = classifier->haarFeature[l].rect[k].r;
                        int tilted = classifier->haarFeature[l].tilted;
                        has_tilted_features |= tilted != 0;
                        if( r.width < 0 || r.height < 0 || r.y < 0 ||
                            r.x + r.width > origWindowSize.width
                            ||
                            (!tilted &&
                            (r.x < 0 || r.y + r.height > origWindowSize.height))
                            ||
                            (tilted && (r.x - r.height < 0 ||
                            r.y + r.width + r.height > origWindowSize.height)))
                        {
                            sprintf( errorstr, "%d-%s rectangle of %d-%s classifier of "
                                     "%d-%s stage classifier is invalid or is outside "
                                     "the original window",
                                     k, numSuffix(k), j, numSuffix(j), i, numSuffix(i) );
                            CV_ERROR( CV_StsNullPtr, errorstr );
                        }
                    }
                }
            }
        }
    }

    datasize = sizeof(CvHidHaarClassifierCascade) +
               sizeof(CvHidHaarStageClassifier)*cascade->count +
               sizeof(CvHidHaarClassifier) * total +
               ( sizeof( CvHidHaarFeature ) + sizeof( CvHaarFeature ) +
                 sizeof( float ) + 2 * sizeof( int ) ) * nodes +
               sizeof( float ) * (nodes + total);

    CV_CALL( out = (CvHidHaarClassifierCascade*)cvAlloc( datasize ));

    /* init header */
    out->headerSize = sizeof(*out);
    out->count = cascade->count;
    out->origWindowSize = cascade->origWindowSize;
    updateRealWindowSize( out, scale );
    out->sum.data.ptr = out->sqsum.data.ptr = out->tiltedSum.data.ptr = 0;
    
    out->stageClassifier = (CvHidHaarStageClassifier*)(out + 1);
    classifier0 = (CvHidHaarClassifier*)(out->stageClassifier + out->count);
    haarFeature0 = (CvHaarFeature*)(classifier0 + total);
    hidHaarFeature0 = (CvHidHaarFeature*) (haarFeature0 + nodes);
    threshold0 = (float*) (hidHaarFeature0 + nodes);
    left0 = (int*) (threshold0 + nodes);
    right0 = (int*) (left0 + nodes);
    alpha0 = (float*) (right0 + nodes);

    out->is_stump_based = 1;
    out->has_tilted_features = has_tilted_features;

    /* initialize internal representation */
    for( i = 0, pos = 0, nodepos = 0, alphapos = 0; i < cascade->count; i++ )
    {
        CvHaarStageClassifier* stageClassifier = cascade->stageClassifier + i;
        CvHidHaarStageClassifier* hidStageClassifier = out->stageClassifier + i;

        hidStageClassifier->count = stageClassifier->count;
        hidStageClassifier->threshold = stageClassifier->threshold;
        hidStageClassifier->classifier = classifier0 + pos;
        hidStageClassifier->two_rects = 1;
        pos += stageClassifier->count;

        for( j = 0; j < stageClassifier->count; j++ )
        {
            nodecount = stageClassifier->classifier[j].count;
            hidStageClassifier->classifier[j].count = nodecount;
            
            hidStageClassifier->classifier[j].origFeature = haarFeature0 + nodepos;
            hidStageClassifier->classifier[j].feature = hidHaarFeature0 + nodepos;
            hidStageClassifier->classifier[j].threshold = threshold0 + nodepos;
            hidStageClassifier->classifier[j].left = left0 + nodepos;
            hidStageClassifier->classifier[j].right = right0 + nodepos;
            hidStageClassifier->classifier[j].alpha = alpha0 + alphapos;

            nodepos += hidStageClassifier->classifier[j].count;
            alphapos += hidStageClassifier->classifier[j].count + 1;
            for( l = 0; l < nodecount; l++ )
            {
                /* original haar feature */
                hidStageClassifier->classifier[j].origFeature[l] =
                    stageClassifier->classifier[j].haarFeature[l];
                if( hidStageClassifier->classifier[j].origFeature[l].rect[2].weight == 0 ||
                    hidStageClassifier->classifier[j].origFeature[l].rect[2].r.width == 0 ||
                    hidStageClassifier->classifier[j].origFeature[l].rect[2].r.height == 0 )
                {
                    memset( &(hidStageClassifier->classifier[j].origFeature[l].rect[2]), 0,
                            sizeof(hidStageClassifier->classifier[j].origFeature[l].rect[2]) );
                }
                else
                    hidStageClassifier->two_rects = 0;

                /* threshold */
                hidStageClassifier->classifier[j].threshold[l] =
                    stageClassifier->classifier[j].threshold[l];
                /* left */
                hidStageClassifier->classifier[j].left[l] =
                    stageClassifier->classifier[j].left[l];
                /* right */
                hidStageClassifier->classifier[j].right[l] =
                    stageClassifier->classifier[j].right[l];
                /* alpha */
                hidStageClassifier->classifier[j].alpha[l] =
                    stageClassifier->classifier[j].alpha[l];
            }

            out->is_stump_based &= nodecount == 1;

            hidStageClassifier->classifier[j].alpha[nodecount] =
                stageClassifier->classifier[j].alpha[nodecount];
        }
    }

⌨️ 快捷键说明

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