📄 cvhaar.cpp
字号:
/*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 "_cv.h"
#include <stdio.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 CvHidHaarTreeNode
{
CvHidHaarFeature feature;
float threshold;
int left;
int right;
}
CvHidHaarTreeNode;
typedef struct CvHidHaarClassifier
{
int count;
//CvHaarFeature* orig_feature;
CvHidHaarTreeNode* node;
float* alpha;
}
CvHidHaarClassifier;
typedef struct CvHidHaarStageClassifier
{
int count;
float threshold;
CvHidHaarClassifier* classifier;
int two_rects;
struct CvHidHaarStageClassifier* next;
struct CvHidHaarStageClassifier* child;
struct CvHidHaarStageClassifier* parent;
}
CvHidHaarStageClassifier;
struct CvHidHaarClassifierCascade
{
int count;
int is_stump_based;
int has_tilted_features;
int is_tree;
double inv_window_area;
CvMat sum, sqsum, tilted;
CvHidHaarStageClassifier* stage_classifier;
sqsumtype *pq0, *pq1, *pq2, *pq3;
sumtype *p0, *p1, *p2, *p3;
void** ipp_stages;
};
/* IPP functions for object detection */
icvHaarClassifierInitAlloc_32f_t icvHaarClassifierInitAlloc_32f_p = 0;
icvHaarClassifierFree_32f_t icvHaarClassifierFree_32f_p = 0;
icvApplyHaarClassifier_32s32f_C1R_t icvApplyHaarClassifier_32s32f_C1R_p = 0;
icvRectStdDev_32s32f_C1R_t icvRectStdDev_32s32f_C1R_p = 0;
const int icv_object_win_border = 1;
const float icv_stage_threshold_bias = 0.0001f;
static CvHaarClassifierCascade*
icvCreateHaarClassifierCascade( int stage_count )
{
CvHaarClassifierCascade* cascade = 0;
CV_FUNCNAME( "icvCreateHaarClassifierCascade" );
__BEGIN__;
int block_size = sizeof(*cascade) + stage_count*sizeof(*cascade->stage_classifier);
if( stage_count <= 0 )
CV_ERROR( CV_StsOutOfRange, "Number of stages should be positive" );
CV_CALL( cascade = (CvHaarClassifierCascade*)cvAlloc( block_size ));
memset( cascade, 0, block_size );
cascade->stage_classifier = (CvHaarStageClassifier*)(cascade + 1);
cascade->flags = CV_HAAR_MAGIC_VAL;
cascade->count = stage_count;
__END__;
return cascade;
}
static void
icvReleaseHidHaarClassifierCascade( CvHidHaarClassifierCascade** _cascade )
{
if( _cascade && *_cascade )
{
CvHidHaarClassifierCascade* cascade = *_cascade;
if( cascade->ipp_stages && icvHaarClassifierFree_32f_p )
{
int i;
for( i = 0; i < cascade->count; i++ )
{
if( cascade->ipp_stages[i] )
icvHaarClassifierFree_32f_p( cascade->ipp_stages[i] );
}
}
cvFree( &cascade->ipp_stages );
cvFree( _cascade );
}
}
/* create more efficient internal representation of haar classifier cascade */
static CvHidHaarClassifierCascade*
icvCreateHidHaarClassifierCascade( CvHaarClassifierCascade* cascade )
{
CvRect* ipp_features = 0;
float *ipp_weights = 0, *ipp_thresholds = 0, *ipp_val1 = 0, *ipp_val2 = 0;
int* ipp_counts = 0;
CvHidHaarClassifierCascade* out = 0;
CV_FUNCNAME( "icvCreateHidHaarClassifierCascade" );
__BEGIN__;
int i, j, k, l;
int datasize;
int total_classifiers = 0;
int total_nodes = 0;
char errorstr[100];
CvHidHaarClassifier* haar_classifier_ptr;
CvHidHaarTreeNode* haar_node_ptr;
CvSize orig_window_size;
int has_tilted_features = 0;
int max_count = 0;
if( !CV_IS_HAAR_CLASSIFIER(cascade) )
CV_ERROR( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" );
if( cascade->hid_cascade )
CV_ERROR( CV_StsError, "hid_cascade has been already created" );
if( !cascade->stage_classifier )
CV_ERROR( CV_StsNullPtr, "" );
if( cascade->count <= 0 )
CV_ERROR( CV_StsOutOfRange, "Negative number of cascade stages" );
orig_window_size = cascade->orig_window_size;
/* 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* stage_classifier = cascade->stage_classifier + i;
if( !stage_classifier->classifier ||
stage_classifier->count <= 0 )
{
sprintf( errorstr, "header of the stage classifier #%d is invalid "
"(has null pointers or non-positive classfier count)", i );
CV_ERROR( CV_StsError, errorstr );
}
max_count = MAX( max_count, stage_classifier->count );
total_classifiers += stage_classifier->count;
for( j = 0; j < stage_classifier->count; j++ )
{
CvHaarClassifier* classifier = stage_classifier->classifier + j;
total_nodes += classifier->count;
for( l = 0; l < classifier->count; l++ )
{
for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ )
{
if( classifier->haar_feature[l].rect[k].r.width )
{
CvRect r = classifier->haar_feature[l].rect[k].r;
int tilted = classifier->haar_feature[l].tilted;
has_tilted_features |= tilted != 0;
if( r.width < 0 || r.height < 0 || r.y < 0 ||
r.x + r.width > orig_window_size.width
||
(!tilted &&
(r.x < 0 || r.y + r.height > orig_window_size.height))
||
(tilted && (r.x - r.height < 0 ||
r.y + r.width + r.height > orig_window_size.height)))
{
sprintf( errorstr, "rectangle #%d of the classifier #%d of "
"the stage classifier #%d is not inside "
"the reference (original) cascade window", k, j, i );
CV_ERROR( CV_StsNullPtr, errorstr );
}
}
}
}
}
}
// this is an upper boundary for the whole hidden cascade size
datasize = sizeof(CvHidHaarClassifierCascade) +
sizeof(CvHidHaarStageClassifier)*cascade->count +
sizeof(CvHidHaarClassifier) * total_classifiers +
sizeof(CvHidHaarTreeNode) * total_nodes +
sizeof(void*)*(total_nodes + total_classifiers);
CV_CALL( out = (CvHidHaarClassifierCascade*)cvAlloc( datasize ));
memset( out, 0, sizeof(*out) );
/* init header */
out->count = cascade->count;
out->stage_classifier = (CvHidHaarStageClassifier*)(out + 1);
haar_classifier_ptr = (CvHidHaarClassifier*)(out->stage_classifier + cascade->count);
haar_node_ptr = (CvHidHaarTreeNode*)(haar_classifier_ptr + total_classifiers);
out->is_stump_based = 1;
out->has_tilted_features = has_tilted_features;
out->is_tree = 0;
/* initialize internal representation */
for( i = 0; i < cascade->count; i++ )
{
CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i;
CvHidHaarStageClassifier* hid_stage_classifier = out->stage_classifier + i;
hid_stage_classifier->count = stage_classifier->count;
hid_stage_classifier->threshold = stage_classifier->threshold - icv_stage_threshold_bias;
hid_stage_classifier->classifier = haar_classifier_ptr;
hid_stage_classifier->two_rects = 1;
haar_classifier_ptr += stage_classifier->count;
hid_stage_classifier->parent = (stage_classifier->parent == -1)
? NULL : out->stage_classifier + stage_classifier->parent;
hid_stage_classifier->next = (stage_classifier->next == -1)
? NULL : out->stage_classifier + stage_classifier->next;
hid_stage_classifier->child = (stage_classifier->child == -1)
? NULL : out->stage_classifier + stage_classifier->child;
out->is_tree |= hid_stage_classifier->next != NULL;
for( j = 0; j < stage_classifier->count; j++ )
{
CvHaarClassifier* classifier = stage_classifier->classifier + j;
CvHidHaarClassifier* hid_classifier = hid_stage_classifier->classifier + j;
int node_count = classifier->count;
float* alpha_ptr = (float*)(haar_node_ptr + node_count);
hid_classifier->count = node_count;
hid_classifier->node = haar_node_ptr;
hid_classifier->alpha = alpha_ptr;
for( l = 0; l < node_count; l++ )
{
CvHidHaarTreeNode* node = hid_classifier->node + l;
CvHaarFeature* feature = classifier->haar_feature + l;
memset( node, -1, sizeof(*node) );
node->threshold = classifier->threshold[l];
node->left = classifier->left[l];
node->right = classifier->right[l];
if( fabs(feature->rect[2].weight) < DBL_EPSILON ||
feature->rect[2].r.width == 0 ||
feature->rect[2].r.height == 0 )
memset( &(node->feature.rect[2]), 0, sizeof(node->feature.rect[2]) );
else
hid_stage_classifier->two_rects = 0;
}
memcpy( alpha_ptr, classifier->alpha, (node_count+1)*sizeof(alpha_ptr[0]));
haar_node_ptr =
(CvHidHaarTreeNode*)cvAlignPtr(alpha_ptr+node_count+1, sizeof(void*));
out->is_stump_based &= node_count == 1;
}
}
//
// NOTE: Currently, OpenMP is implemented and IPP modes are incompatible.
//
#ifndef _OPENMP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -