1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*M/////////////////////////////////////////////////////////////////////////////////////// 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// By downloading, copying, installing or using the software you agree to this license. 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// If you do not agree to this license, do not download, install, 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// copy or use the software. 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Intel License Agreement 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// For Open Source Computer Vision Library 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (C) 2000, Intel Corporation, all rights reserved. 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Third party copyrights are property of their respective owners. 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Redistribution and use in source and binary forms, with or without modification, 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// are permitted provided that the following conditions are met: 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * Redistribution's of source code must retain the above copyright notice, 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// this list of conditions and the following disclaimer. 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * Redistribution's in binary form must reproduce the above copyright notice, 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// this list of conditions and the following disclaimer in the documentation 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// and/or other materials provided with the distribution. 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * The name of Intel Corporation may not be used to endorse or promote products 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// derived from this software without specific prior written permission. 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// This software is provided by the copyright holders and contributors "as is" and 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// any express or implied warranties, including, but not limited to, the implied 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// warranties of merchantability and fitness for a particular purpose are disclaimed. 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// In no event shall the Intel Corporation or contributors be liable for any direct, 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// indirect, incidental, special, exemplary, or consequential damages 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// (including, but not limited to, procurement of substitute goods or services; 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// loss of use, data, or profits; or business interruption) however caused 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// and on any theory of liability, whether in contract, strict liability, 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// or tort (including negligence or otherwise) arising in any way out of 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// the use of this software, even if advised of the possibility of such damage. 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//M*/ 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Haar features calculation */ 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "precomp.hpp" 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/imgproc/imgproc_c.h" 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/objdetect/objdetect_c.h" 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <stdio.h> 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if CV_SSE2 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# if 1 /*!CV_SSE4_1 && !CV_SSE4_2*/ 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# define _mm_blendv_pd(a, b, m) _mm_xor_pd(a, _mm_and_pd(_mm_xor_pd(b, a), m)) 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# define _mm_blendv_ps(a, b, m) _mm_xor_ps(a, _mm_and_ps(_mm_xor_ps(b, a), m)) 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# endif 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if 0 /*CV_AVX*/ 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# define CV_HAAR_USE_AVX 1 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# if defined _MSC_VER 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# pragma warning( disable : 4752 ) 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# endif 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# if CV_SSE2 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# define CV_HAAR_USE_SSE 1 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# endif 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* these settings affect the quality of detection: change with care */ 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define CV_ADJUST_FEATURES 1 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define CV_ADJUST_WEIGHTS 0 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef int sumtype; 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef double sqsumtype; 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct CvHidHaarFeature 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sumtype *p0, *p1, *p2, *p3; 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float weight; 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rect[CV_HAAR_FEATURE_MAX]; 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} CvHidHaarFeature; 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct CvHidHaarTreeNode 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarFeature feature; 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float threshold; 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int left; 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int right; 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} CvHidHaarTreeNode; 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct CvHidHaarClassifier 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int count; 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler //CvHaarFeature* orig_feature; 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node; 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float* alpha; 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} CvHidHaarClassifier; 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct CvHidHaarStageClassifier 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int count; 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float threshold; 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* classifier; 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int two_rects; 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct CvHidHaarStageClassifier* next; 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct CvHidHaarStageClassifier* child; 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct CvHidHaarStageClassifier* parent; 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} CvHidHaarStageClassifier; 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct CvHidHaarClassifierCascade 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int count; 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int isStumpBased; 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int has_tilted_features; 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int is_tree; 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double inv_window_area; 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvMat sum, sqsum, tilted; 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarStageClassifier* stage_classifier; 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sqsumtype *pq0, *pq1, *pq2, *pq3; 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sumtype *p0, *p1, *p2, *p3; 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void** ipp_stages; 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} CvHidHaarClassifierCascade; 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerconst int icv_object_win_border = 1; 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerconst float icv_stage_threshold_bias = 0.0001f; 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic CvHaarClassifierCascade* 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslericvCreateHaarClassifierCascade( int stage_count ) 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifierCascade* cascade = 0; 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int block_size = sizeof(*cascade) + stage_count*sizeof(*cascade->stage_classifier); 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( stage_count <= 0 ) 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsOutOfRange, "Number of stages should be positive" ); 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade = (CvHaarClassifierCascade*)cvAlloc( block_size ); 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler memset( cascade, 0, block_size ); 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier = (CvHaarStageClassifier*)(cascade + 1); 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->flags = CV_HAAR_MAGIC_VAL; 150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->count = stage_count; 151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cascade; 153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void 156793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslericvReleaseHidHaarClassifierCascade( CvHidHaarClassifierCascade** _cascade ) 157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( _cascade && *_cascade ) 159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_IPP 161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifierCascade* cascade = *_cascade; 162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( CV_IPP_CHECK_COND && cascade->ipp_stages ) 163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i; 165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < cascade->count; i++ ) 166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->ipp_stages[i] ) 168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ippiHaarClassifierFree_32f( (IppiHaarClassifier_32f*)cascade->ipp_stages[i] ); 169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &cascade->ipp_stages ); 172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( _cascade ); 174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* create more efficient internal representation of haar classifier cascade */ 178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic CvHidHaarClassifierCascade* 179793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslericvCreateHidHaarClassifierCascade( CvHaarClassifierCascade* cascade ) 180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect* ipp_features = 0; 182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float *ipp_weights = 0, *ipp_thresholds = 0, *ipp_val1 = 0, *ipp_val2 = 0; 183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int* ipp_counts = 0; 184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifierCascade* out = 0; 186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i, j, k, l; 188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int datasize; 189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int total_classifiers = 0; 190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int total_nodes = 0; 191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler char errorstr[1000]; 192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* haar_classifier_ptr; 193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* haar_node_ptr; 194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSize orig_window_size; 195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int has_tilted_features = 0; 196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int max_count = 0; 197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_IS_HAAR_CLASSIFIER(cascade) ) 199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); 200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->hid_cascade ) 202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, "hid_cascade has been already created" ); 203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !cascade->stage_classifier ) 205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsNullPtr, "" ); 206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->count <= 0 ) 208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsOutOfRange, "Negative number of cascade stages" ); 209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler orig_window_size = cascade->orig_window_size; 211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* check input structure correctness and calculate total memory size needed for 213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler internal representation of the classifier cascade */ 214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < cascade->count; i++ ) 215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !stage_classifier->classifier || 219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_classifier->count <= 0 ) 220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( errorstr, "header of the stage classifier #%d is invalid " 222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(has null pointers or non-positive classfier count)", i ); 223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, errorstr ); 224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler max_count = MAX( max_count, stage_classifier->count ); 227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler total_classifiers += stage_classifier->count; 228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < stage_classifier->count; j++ ) 230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifier* classifier = stage_classifier->classifier + j; 232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler total_nodes += classifier->count; 234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = 0; l < classifier->count; l++ ) 235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) 237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( classifier->haar_feature[l].rect[k].r.width ) 239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect r = classifier->haar_feature[l].rect[k].r; 241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int tilted = classifier->haar_feature[l].tilted; 242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler has_tilted_features |= tilted != 0; 243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( r.width < 0 || r.height < 0 || r.y < 0 || 244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r.x + r.width > orig_window_size.width 245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || 246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (!tilted && 247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (r.x < 0 || r.y + r.height > orig_window_size.height)) 248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || 249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (tilted && (r.x - r.height < 0 || 250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r.y + r.width + r.height > orig_window_size.height))) 251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( errorstr, "rectangle #%d of the classifier #%d of " 253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "the stage classifier #%d is not inside " 254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "the reference (original) cascade window", k, j, i ); 255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsNullPtr, errorstr ); 256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // this is an upper boundary for the whole hidden cascade size 264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler datasize = sizeof(CvHidHaarClassifierCascade) + 265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof(CvHidHaarStageClassifier)*cascade->count + 266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof(CvHidHaarClassifier) * total_classifiers + 267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof(CvHidHaarTreeNode) * total_nodes + 268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof(void*)*(total_nodes + total_classifiers); 269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out = (CvHidHaarClassifierCascade*)cvAlloc( datasize ); 271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler memset( out, 0, sizeof(*out) ); 272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* init header */ 274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out->count = cascade->count; 275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out->stage_classifier = (CvHidHaarStageClassifier*)(out + 1); 276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler haar_classifier_ptr = (CvHidHaarClassifier*)(out->stage_classifier + cascade->count); 277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler haar_node_ptr = (CvHidHaarTreeNode*)(haar_classifier_ptr + total_classifiers); 278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out->isStumpBased = 1; 280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out->has_tilted_features = has_tilted_features; 281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out->is_tree = 0; 282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* initialize internal representation */ 284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < cascade->count; i++ ) 285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarStageClassifier* hid_stage_classifier = out->stage_classifier + i; 288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_stage_classifier->count = stage_classifier->count; 290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_stage_classifier->threshold = stage_classifier->threshold - icv_stage_threshold_bias; 291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_stage_classifier->classifier = haar_classifier_ptr; 292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_stage_classifier->two_rects = 1; 293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler haar_classifier_ptr += stage_classifier->count; 294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_stage_classifier->parent = (stage_classifier->parent == -1) 296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ? NULL : out->stage_classifier + stage_classifier->parent; 297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_stage_classifier->next = (stage_classifier->next == -1) 298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ? NULL : out->stage_classifier + stage_classifier->next; 299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_stage_classifier->child = (stage_classifier->child == -1) 300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ? NULL : out->stage_classifier + stage_classifier->child; 301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out->is_tree |= hid_stage_classifier->next != NULL; 303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < stage_classifier->count; j++ ) 305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifier* classifier = stage_classifier->classifier + j; 307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* hid_classifier = hid_stage_classifier->classifier + j; 308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int node_count = classifier->count; 309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float* alpha_ptr = (float*)(haar_node_ptr + node_count); 310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_classifier->count = node_count; 312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_classifier->node = haar_node_ptr; 313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_classifier->alpha = alpha_ptr; 314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = 0; l < node_count; l++ ) 316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = hid_classifier->node + l; 318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarFeature* feature = classifier->haar_feature + l; 319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler memset( node, -1, sizeof(*node) ); 320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler node->threshold = classifier->threshold[l]; 321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler node->left = classifier->left[l]; 322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler node->right = classifier->right[l]; 323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( fabs(feature->rect[2].weight) < DBL_EPSILON || 325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler feature->rect[2].r.width == 0 || 326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler feature->rect[2].r.height == 0 ) 327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler memset( &(node->feature.rect[2]), 0, sizeof(node->feature.rect[2]) ); 328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hid_stage_classifier->two_rects = 0; 330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler memcpy( alpha_ptr, classifier->alpha, (node_count+1)*sizeof(alpha_ptr[0])); 333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler haar_node_ptr = 334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (CvHidHaarTreeNode*)cvAlignPtr(alpha_ptr+node_count+1, sizeof(void*)); 335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out->isStumpBased &= node_count == 1; 337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_IPP 341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int can_use_ipp = CV_IPP_CHECK_COND && (!out->has_tilted_features && !out->is_tree && out->isStumpBased); 342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( can_use_ipp ) 344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int ipp_datasize = cascade->count*sizeof(out->ipp_stages[0]); 346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float ipp_weight_scale=(float)(1./((orig_window_size.width-icv_object_win_border*2)* 347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (orig_window_size.height-icv_object_win_border*2))); 348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler out->ipp_stages = (void**)cvAlloc( ipp_datasize ); 350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler memset( out->ipp_stages, 0, ipp_datasize ); 351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_features = (CvRect*)cvAlloc( max_count*3*sizeof(ipp_features[0]) ); 353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_weights = (float*)cvAlloc( max_count*3*sizeof(ipp_weights[0]) ); 354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_thresholds = (float*)cvAlloc( max_count*sizeof(ipp_thresholds[0]) ); 355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_val1 = (float*)cvAlloc( max_count*sizeof(ipp_val1[0]) ); 356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_val2 = (float*)cvAlloc( max_count*sizeof(ipp_val2[0]) ); 357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_counts = (int*)cvAlloc( max_count*sizeof(ipp_counts[0]) ); 358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < cascade->count; i++ ) 360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0, k = 0; j < stage_classifier->count; j++ ) 363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifier* classifier = stage_classifier->classifier + j; 365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int rect_count = 2 + (classifier->haar_feature->rect[2].r.width != 0); 366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_thresholds[j] = classifier->threshold[0]; 368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_val1[j] = classifier->alpha[0]; 369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_val2[j] = classifier->alpha[1]; 370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_counts[j] = rect_count; 371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = 0; l < rect_count; l++, k++ ) 373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_features[k] = classifier->haar_feature->rect[l].r; 375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler //ipp_features[k].y = orig_window_size.height - ipp_features[k].y - ipp_features[k].height; 376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_weights[k] = classifier->haar_feature->rect[l].weight*ipp_weight_scale; 377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( ippiHaarClassifierInitAlloc_32f( (IppiHaarClassifier_32f**)&out->ipp_stages[i], 381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (const IppiRect*)ipp_features, ipp_weights, ipp_thresholds, 382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ipp_val1, ipp_val2, ipp_counts, stage_classifier->count ) < 0 ) 383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( i < cascade->count ) 387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < i; j++ ) 389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( out->ipp_stages[i] ) 390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ippiHaarClassifierFree_32f( (IppiHaarClassifier_32f*)out->ipp_stages[i] ); 391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &out->ipp_stages ); 392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler*/ 396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->hid_cascade = out; 397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler assert( (char*)haar_node_ptr - (char*)out <= datasize ); 398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &ipp_features ); 400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &ipp_weights ); 401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &ipp_thresholds ); 402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &ipp_val1 ); 403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &ipp_val2 ); 404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &ipp_counts ); 405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return out; 407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define sum_elem_ptr(sum,row,col) \ 411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ((sumtype*)CV_MAT_ELEM_PTR_FAST((sum),(row),(col),sizeof(sumtype))) 412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define sqsum_elem_ptr(sqsum,row,col) \ 414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ((sqsumtype*)CV_MAT_ELEM_PTR_FAST((sqsum),(row),(col),sizeof(sqsumtype))) 415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define calc_sum(rect,offset) \ 417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ((rect).p0[offset] - (rect).p1[offset] - (rect).p2[offset] + (rect).p3[offset]) 418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define calc_sumf(rect,offset) \ 420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_cast<float>((rect).p0[offset] - (rect).p1[offset] - (rect).p2[offset] + (rect).p3[offset]) 421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 423793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCV_IMPL void 424793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslercvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* _cascade, 425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const CvArr* _sum, 426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const CvArr* _sqsum, 427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const CvArr* _tilted_sum, 428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double scale ) 429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvMat sum_stub, *sum = (CvMat*)_sum; 431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvMat sqsum_stub, *sqsum = (CvMat*)_sqsum; 432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvMat tilted_stub, *tilted = (CvMat*)_tilted_sum; 433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifierCascade* cascade; 434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int coi0 = 0, coi1 = 0; 435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i; 436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect equRect; 437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double weight_scale; 438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) 440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); 441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( scale <= 0 ) 443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsOutOfRange, "Scale must be positive" ); 444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum = cvGetMat( sum, &sum_stub, &coi0 ); 446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sqsum = cvGetMat( sqsum, &sqsum_stub, &coi1 ); 447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( coi0 || coi1 ) 449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_BadCOI, "COI is not supported" ); 450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_ARE_SIZES_EQ( sum, sqsum )) 452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsUnmatchedSizes, "All integral images must have the same size" ); 453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( CV_MAT_TYPE(sqsum->type) != CV_64FC1 || 455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_MAT_TYPE(sum->type) != CV_32SC1 ) 456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsUnsupportedFormat, 457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" ); 458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !_cascade->hid_cascade ) 460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler icvCreateHidHaarClassifierCascade(_cascade); 461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade = _cascade->hid_cascade; 463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->has_tilted_features ) 465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tilted = cvGetMat( tilted, &tilted_stub, &coi1 ); 467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( CV_MAT_TYPE(tilted->type) != CV_32SC1 ) 469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsUnsupportedFormat, 470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" ); 471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( sum->step != tilted->step ) 473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsUnmatchedSizes, 474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "Sum and tilted_sum must have the same stride (step, widthStep)" ); 475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_ARE_SIZES_EQ( sum, tilted )) 477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsUnmatchedSizes, "All integral images must have the same size" ); 478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->tilted = *tilted; 479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _cascade->scale = scale; 482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _cascade->real_window_size.width = cvRound( _cascade->orig_window_size.width * scale ); 483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _cascade->real_window_size.height = cvRound( _cascade->orig_window_size.height * scale ); 484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->sum = *sum; 486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->sqsum = *sqsum; 487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.x = equRect.y = cvRound(scale); 489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.width = cvRound((_cascade->orig_window_size.width-2)*scale); 490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.height = cvRound((_cascade->orig_window_size.height-2)*scale); 491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler weight_scale = 1./(equRect.width*equRect.height); 492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->inv_window_area = weight_scale; 493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->p0 = sum_elem_ptr(*sum, equRect.y, equRect.x); 495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->p1 = sum_elem_ptr(*sum, equRect.y, equRect.x + equRect.width ); 496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->p2 = sum_elem_ptr(*sum, equRect.y + equRect.height, equRect.x ); 497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->p3 = sum_elem_ptr(*sum, equRect.y + equRect.height, 498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.x + equRect.width ); 499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->pq0 = sqsum_elem_ptr(*sqsum, equRect.y, equRect.x); 501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->pq1 = sqsum_elem_ptr(*sqsum, equRect.y, equRect.x + equRect.width ); 502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->pq2 = sqsum_elem_ptr(*sqsum, equRect.y + equRect.height, equRect.x ); 503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->pq3 = sqsum_elem_ptr(*sqsum, equRect.y + equRect.height, 504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.x + equRect.width ); 505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* init pointers in haar features according to real window size and 507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler given image pointers */ 508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < _cascade->count; i++ ) 509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int j, k, l; 511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = 0; l < cascade->stage_classifier[i].classifier[j].count; l++ ) 514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarFeature* feature = 516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler &_cascade->stage_classifier[i].classifier[j].haar_feature[l]; 517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* CvHidHaarClassifier* classifier = 518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].classifier + j; */ 519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarFeature* hidfeature = 520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler &cascade->stage_classifier[i].classifier[j].node[l].feature; 521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double sum0 = 0, area0 = 0; 522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect r[3]; 523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int base_w = -1, base_h = -1; 525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int new_base_w = 0, new_base_h = 0; 526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int kx, ky; 527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int flagx = 0, flagy = 0; 528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int x0 = 0, y0 = 0; 529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int nr; 530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* align blocks */ 532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) 533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !hidfeature->rect[k].p0 ) 535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r[k] = feature->rect[k].r; 537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].width-1) ); 538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].x - r[0].x-1) ); 539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].height-1) ); 540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].y - r[0].y-1) ); 541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nr = k; 544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler base_w += 1; 546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler base_h += 1; 547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler kx = r[0].width / base_w; 548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ky = r[0].height / base_h; 549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( kx <= 0 ) 551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler flagx = 1; 553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler new_base_w = cvRound( r[0].width * scale ) / kx; 554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler x0 = cvRound( r[0].x * scale ); 555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( ky <= 0 ) 558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler flagy = 1; 560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler new_base_h = cvRound( r[0].height * scale ) / ky; 561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y0 = cvRound( r[0].y * scale ); 562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( k = 0; k < nr; k++ ) 565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect tr; 567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double correction_ratio; 568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( flagx ) 570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.x = (r[k].x - r[0].x) * new_base_w / base_w + x0; 572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.width = r[k].width * new_base_w / base_w; 573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.x = cvRound( r[k].x * scale ); 577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.width = cvRound( r[k].width * scale ); 578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( flagy ) 581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.y = (r[k].y - r[0].y) * new_base_h / base_h + y0; 583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.height = r[k].height * new_base_h / base_h; 584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.y = cvRound( r[k].y * scale ); 588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.height = cvRound( r[k].height * scale ); 589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if CV_ADJUST_WEIGHTS 592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // RAINER START 594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const float orig_feature_size = (float)(feature->rect[k].r.width)*feature->rect[k].r.height; 595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const float orig_norm_size = (float)(_cascade->orig_window_size.width)*(_cascade->orig_window_size.height); 596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const float feature_size = float(tr.width*tr.height); 597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler //const float normSize = float(equRect.width*equRect.height); 598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float target_ratio = orig_feature_size / orig_norm_size; 599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler //float isRatio = featureSize / normSize; 600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler //correctionRatio = targetRatio / isRatio / normSize; 601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler correction_ratio = target_ratio / feature_size; 602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // RAINER END 603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler correction_ratio = weight_scale * (!feature->tilted ? 1 : 0.5); 606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !feature->tilted ) 609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].p0 = sum_elem_ptr(*sum, tr.y, tr.x); 611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].p1 = sum_elem_ptr(*sum, tr.y, tr.x + tr.width); 612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].p2 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x); 613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].p3 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x + tr.width); 614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].p2 = sum_elem_ptr(*tilted, tr.y + tr.width, tr.x + tr.width); 618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].p3 = sum_elem_ptr(*tilted, tr.y + tr.width + tr.height, 619793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tr.x + tr.width - tr.height); 620793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].p0 = sum_elem_ptr(*tilted, tr.y, tr.x); 621793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].p1 = sum_elem_ptr(*tilted, tr.y + tr.height, tr.x - tr.height); 622793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 623793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 624793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[k].weight = (float)(feature->rect[k].weight * correction_ratio); 625793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 626793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( k == 0 ) 627793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler area0 = tr.width * tr.height; 628793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 629793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum0 += hidfeature->rect[k].weight * tr.width * tr.height; 630793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 631793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 632793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler hidfeature->rect[0].weight = (float)(-sum0/area0); 633793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } /* l */ 634793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } /* j */ 635793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 636793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 637793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 638793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 639793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// AVX version icvEvalHidHaarClassifier. Process 8 CvHidHaarClassifiers per call. Check AVX support before invocation!! 640793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef CV_HAAR_USE_AVX 641793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCV_INLINE 642793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerdouble icvEvalHidHaarClassifierAVX( CvHidHaarClassifier* classifier, 643793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double variance_norm_factor, size_t p_offset ) 644793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 645793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int CV_DECL_ALIGNED(32) idxV[8] = {0,0,0,0,0,0,0,0}; 646793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler uchar flags[8] = {0,0,0,0,0,0,0,0}; 647793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* nodes[8]; 648793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double res = 0; 649793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler uchar exitConditionFlag = 0; 650793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for(;;) 651793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 652793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float CV_DECL_ALIGNED(32) tmp[8] = {0,0,0,0,0,0,0,0}; 653793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0] = (classifier+0)->node + idxV[0]; 654793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1] = (classifier+1)->node + idxV[1]; 655793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2] = (classifier+2)->node + idxV[2]; 656793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3] = (classifier+3)->node + idxV[3]; 657793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4] = (classifier+4)->node + idxV[4]; 658793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5] = (classifier+5)->node + idxV[5]; 659793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6] = (classifier+6)->node + idxV[6]; 660793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[7] = (classifier+7)->node + idxV[7]; 661793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 662793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 t = _mm256_set1_ps(static_cast<float>(variance_norm_factor)); 663793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 664793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold, 665793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->threshold, 666793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->threshold, 667793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->threshold, 668793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->threshold, 669793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->threshold, 670793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->threshold, 671793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->threshold)); 672793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 673793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[0], p_offset), 674793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[6]->feature.rect[0], p_offset), 675793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[5]->feature.rect[0], p_offset), 676793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[4]->feature.rect[0], p_offset), 677793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[3]->feature.rect[0], p_offset), 678793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[2]->feature.rect[0], p_offset), 679793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[1]->feature.rect[0], p_offset), 680793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[0]->feature.rect[0], p_offset)); 681793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 682793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, 683793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->feature.rect[0].weight, 684793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->feature.rect[0].weight, 685793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->feature.rect[0].weight, 686793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->feature.rect[0].weight, 687793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->feature.rect[0].weight, 688793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->feature.rect[0].weight, 689793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->feature.rect[0].weight); 690793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 691793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 sum = _mm256_mul_ps(offset, weight); 692793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 693793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[1], p_offset), 694793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[6]->feature.rect[1], p_offset), 695793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[5]->feature.rect[1], p_offset), 696793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[4]->feature.rect[1], p_offset), 697793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[3]->feature.rect[1], p_offset), 698793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[2]->feature.rect[1], p_offset), 699793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[1]->feature.rect[1], p_offset), 700793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[0]->feature.rect[1], p_offset)); 701793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 702793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, 703793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->feature.rect[1].weight, 704793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->feature.rect[1].weight, 705793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->feature.rect[1].weight, 706793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->feature.rect[1].weight, 707793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->feature.rect[1].weight, 708793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->feature.rect[1].weight, 709793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->feature.rect[1].weight); 710793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 711793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum = _mm256_add_ps(sum, _mm256_mul_ps(offset, weight)); 712793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 713793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[0]->feature.rect[2].p0 ) 714793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[0] = calc_sumf(nodes[0]->feature.rect[2], p_offset) * nodes[0]->feature.rect[2].weight; 715793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[1]->feature.rect[2].p0 ) 716793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[1] = calc_sumf(nodes[1]->feature.rect[2], p_offset) * nodes[1]->feature.rect[2].weight; 717793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[2]->feature.rect[2].p0 ) 718793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[2] = calc_sumf(nodes[2]->feature.rect[2], p_offset) * nodes[2]->feature.rect[2].weight; 719793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[3]->feature.rect[2].p0 ) 720793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[3] = calc_sumf(nodes[3]->feature.rect[2], p_offset) * nodes[3]->feature.rect[2].weight; 721793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[4]->feature.rect[2].p0 ) 722793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[4] = calc_sumf(nodes[4]->feature.rect[2], p_offset) * nodes[4]->feature.rect[2].weight; 723793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[5]->feature.rect[2].p0 ) 724793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[5] = calc_sumf(nodes[5]->feature.rect[2], p_offset) * nodes[5]->feature.rect[2].weight; 725793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[6]->feature.rect[2].p0 ) 726793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[6] = calc_sumf(nodes[6]->feature.rect[2], p_offset) * nodes[6]->feature.rect[2].weight; 727793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[7]->feature.rect[2].p0 ) 728793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[7] = calc_sumf(nodes[7]->feature.rect[2], p_offset) * nodes[7]->feature.rect[2].weight; 729793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 730793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum = _mm256_add_ps(sum,_mm256_load_ps(tmp)); 731793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 732793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 left = _mm256_set_ps(static_cast<float>(nodes[7]->left), static_cast<float>(nodes[6]->left), 733793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_cast<float>(nodes[5]->left), static_cast<float>(nodes[4]->left), 734793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_cast<float>(nodes[3]->left), static_cast<float>(nodes[2]->left), 735793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_cast<float>(nodes[1]->left), static_cast<float>(nodes[0]->left)); 736793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 right = _mm256_set_ps(static_cast<float>(nodes[7]->right),static_cast<float>(nodes[6]->right), 737793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_cast<float>(nodes[5]->right),static_cast<float>(nodes[4]->right), 738793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_cast<float>(nodes[3]->right),static_cast<float>(nodes[2]->right), 739793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_cast<float>(nodes[1]->right),static_cast<float>(nodes[0]->right)); 740793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 741793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _mm256_store_si256((__m256i*)idxV, _mm256_cvttps_epi32(_mm256_blendv_ps(right, left, _mm256_cmp_ps(sum, t, _CMP_LT_OQ)))); 742793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 743793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for(int i = 0; i < 8; i++) 744793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 745793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(idxV[i]<=0) 746793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 747793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(!flags[i]) 748793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 749793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler exitConditionFlag++; 750793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler flags[i] = 1; 751793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler res += (classifier+i)->alpha[-idxV[i]]; 752793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 753793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler idxV[i]=0; 754793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 755793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 756793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(exitConditionFlag == 8) 757793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return res; 758793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 759793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 760793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif //CV_HAAR_USE_AVX 761793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 762793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCV_INLINE 763793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerdouble icvEvalHidHaarClassifier( CvHidHaarClassifier* classifier, 764793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double variance_norm_factor, 765793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size_t p_offset ) 766793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 767793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int idx = 0; 768793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /*#if CV_HAAR_USE_SSE && !CV_HAAR_USE_AVX 769793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(cv::checkHardwareSupport(CV_CPU_SSE2))//based on old SSE variant. Works slow 770793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 771793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double CV_DECL_ALIGNED(16) temp[2]; 772793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d zero = _mm_setzero_pd(); 773793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler do 774793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 775793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = classifier->node + idx; 776793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d t = _mm_set1_pd((node->threshold)*variance_norm_factor); 777793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d left = _mm_set1_pd(node->left); 778793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d right = _mm_set1_pd(node->right); 779793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 780793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double _sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 781793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 782793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( node->feature.rect[2].p0 ) 783793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 784793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 785793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d sum = _mm_set1_pd(_sum); 786793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler t = _mm_cmplt_sd(sum, t); 787793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum = _mm_blendv_pd(right, left, t); 788793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 789793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _mm_store_pd(temp, sum); 790793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler idx = (int)temp[0]; 791793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 792793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while(idx > 0 ); 793793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 794793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 795793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 796793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #endif*/ 797793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 798793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler do 799793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 800793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = classifier->node + idx; 801793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double t = node->threshold * variance_norm_factor; 802793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 803793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 804793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 805793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 806793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( node->feature.rect[2].p0 ) 807793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 808793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 809793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler idx = sum < t ? node->left : node->right; 810793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 811793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while( idx > 0 ); 812793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 813793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return classifier->alpha[-idx]; 814793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 815793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 816793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 817793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 818793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int 819793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslercvRunHaarClassifierCascadeSum( const CvHaarClassifierCascade* _cascade, 820793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvPoint pt, double& stage_sum, int start_stage ) 821793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 822793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef CV_HAAR_USE_AVX 823793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool haveAVX = false; 824793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(cv::checkHardwareSupport(CV_CPU_AVX)) 825793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(__xgetbv()&0x6)// Check if the OS will save the YMM registers 826793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler haveAVX = true; 827793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 828793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# ifdef CV_HAAR_USE_SSE 829793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool haveSSE2 = cv::checkHardwareSupport(CV_CPU_SSE2); 830793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler# endif 831793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 832793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 833793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int p_offset, pq_offset; 834793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i, j; 835793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double mean, variance_norm_factor; 836793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifierCascade* cascade; 837793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 838793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) 839793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid cascade pointer" ); 840793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 841793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade = _cascade->hid_cascade; 842793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !cascade ) 843793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsNullPtr, "Hidden cascade has not been created.\n" 844793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "Use cvSetImagesForHaarClassifierCascade" ); 845793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 846793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( pt.x < 0 || pt.y < 0 || 847793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pt.x + _cascade->real_window_size.width >= cascade->sum.width || 848793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pt.y + _cascade->real_window_size.height >= cascade->sum.height ) 849793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return -1; 850793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 851793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x; 852793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x; 853793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area; 854793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler variance_norm_factor = cascade->pq0[pq_offset] - cascade->pq1[pq_offset] - 855793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->pq2[pq_offset] + cascade->pq3[pq_offset]; 856793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler variance_norm_factor = variance_norm_factor*cascade->inv_window_area - mean*mean; 857793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( variance_norm_factor >= 0. ) 858793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler variance_norm_factor = std::sqrt(variance_norm_factor); 859793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 860793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler variance_norm_factor = 1.; 861793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 862793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->is_tree ) 863793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 864793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarStageClassifier* ptr = cascade->stage_classifier; 865793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler assert( start_stage == 0 ); 866793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 867793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while( ptr ) 868793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 869793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum = 0.0; 870793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler j = 0; 871793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 872793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef CV_HAAR_USE_AVX 873793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(haveAVX) 874793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 875793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ; j <= ptr->count - 8; j += 8 ) 876793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 877793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += icvEvalHidHaarClassifierAVX( 878793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ptr->classifier + j, 879793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler variance_norm_factor, p_offset ); 880793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 881793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 882793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 883793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ; j < ptr->count; j++ ) 884793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 885793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += icvEvalHidHaarClassifier( ptr->classifier + j, variance_norm_factor, p_offset ); 886793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 887793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 888793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( stage_sum >= ptr->threshold ) 889793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 890793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ptr = ptr->child; 891793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 892793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 893793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 894793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while( ptr && ptr->next == NULL ) ptr = ptr->parent; 895793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( ptr == NULL ) 896793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 0; 897793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ptr = ptr->next; 898793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 899793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 900793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 901793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else if( cascade->isStumpBased ) 902793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 903793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef CV_HAAR_USE_AVX 904793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(haveAVX) 905793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 906793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* classifiers[8]; 907793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* nodes[8]; 908793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = start_stage; i < cascade->count; i++ ) 909793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 910793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum = 0.0; 911793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler j = 0; 912793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float CV_DECL_ALIGNED(32) buf[8]; 913793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->stage_classifier[i].two_rects ) 914793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 915793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ; j <= cascade->stage_classifier[i].count - 8; j += 8 ) 916793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 917793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[0] = cascade->stage_classifier[i].classifier + j; 918793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0] = classifiers[0]->node; 919793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[1] = cascade->stage_classifier[i].classifier + j + 1; 920793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1] = classifiers[1]->node; 921793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[2] = cascade->stage_classifier[i].classifier + j + 2; 922793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2] = classifiers[2]->node; 923793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[3] = cascade->stage_classifier[i].classifier + j + 3; 924793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3] = classifiers[3]->node; 925793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[4] = cascade->stage_classifier[i].classifier + j + 4; 926793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4] = classifiers[4]->node; 927793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[5] = cascade->stage_classifier[i].classifier + j + 5; 928793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5] = classifiers[5]->node; 929793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[6] = cascade->stage_classifier[i].classifier + j + 6; 930793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6] = classifiers[6]->node; 931793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[7] = cascade->stage_classifier[i].classifier + j + 7; 932793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[7] = classifiers[7]->node; 933793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 934793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 t = _mm256_set1_ps(static_cast<float>(variance_norm_factor)); 935793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold, 936793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->threshold, 937793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->threshold, 938793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->threshold, 939793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->threshold, 940793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->threshold, 941793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->threshold, 942793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->threshold)); 943793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 944793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[0], p_offset), 945793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[6]->feature.rect[0], p_offset), 946793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[5]->feature.rect[0], p_offset), 947793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[4]->feature.rect[0], p_offset), 948793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[3]->feature.rect[0], p_offset), 949793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[2]->feature.rect[0], p_offset), 950793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[1]->feature.rect[0], p_offset), 951793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[0]->feature.rect[0], p_offset)); 952793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 953793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, 954793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->feature.rect[0].weight, 955793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->feature.rect[0].weight, 956793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->feature.rect[0].weight, 957793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->feature.rect[0].weight, 958793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->feature.rect[0].weight, 959793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->feature.rect[0].weight, 960793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->feature.rect[0].weight); 961793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 962793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 sum = _mm256_mul_ps(offset, weight); 963793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 964793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[1], p_offset), 965793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[6]->feature.rect[1], p_offset), 966793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[5]->feature.rect[1], p_offset), 967793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[4]->feature.rect[1], p_offset), 968793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[3]->feature.rect[1], p_offset), 969793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[2]->feature.rect[1], p_offset), 970793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[1]->feature.rect[1], p_offset), 971793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[0]->feature.rect[1], p_offset)); 972793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 973793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, 974793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->feature.rect[1].weight, 975793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->feature.rect[1].weight, 976793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->feature.rect[1].weight, 977793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->feature.rect[1].weight, 978793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->feature.rect[1].weight, 979793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->feature.rect[1].weight, 980793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->feature.rect[1].weight); 981793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 982793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum = _mm256_add_ps(sum, _mm256_mul_ps(offset,weight)); 983793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 984793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 alpha0 = _mm256_set_ps(classifiers[7]->alpha[0], 985793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[6]->alpha[0], 986793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[5]->alpha[0], 987793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[4]->alpha[0], 988793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[3]->alpha[0], 989793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[2]->alpha[0], 990793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[1]->alpha[0], 991793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[0]->alpha[0]); 992793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 alpha1 = _mm256_set_ps(classifiers[7]->alpha[1], 993793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[6]->alpha[1], 994793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[5]->alpha[1], 995793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[4]->alpha[1], 996793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[3]->alpha[1], 997793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[2]->alpha[1], 998793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[1]->alpha[1], 999793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[0]->alpha[1]); 1000793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1001793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _mm256_store_ps(buf, _mm256_blendv_ps(alpha0, alpha1, _mm256_cmp_ps(t, sum, _CMP_LE_OQ))); 1002793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += (buf[0]+buf[1]+buf[2]+buf[3]+buf[4]+buf[5]+buf[6]+buf[7]); 1003793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1004793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1005793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ; j < cascade->stage_classifier[i].count; j++ ) 1006793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1007793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 1008793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = classifier->node; 1009793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1010793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double t = node->threshold*variance_norm_factor; 1011793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 1012793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 1013793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += classifier->alpha[sum >= t]; 1014793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1015793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1016793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1017793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1018793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ; j <= (cascade->stage_classifier[i].count)-8; j+=8 ) 1019793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1020793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float CV_DECL_ALIGNED(32) tmp[8] = {0,0,0,0,0,0,0,0}; 1021793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1022793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[0] = cascade->stage_classifier[i].classifier + j; 1023793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0] = classifiers[0]->node; 1024793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[1] = cascade->stage_classifier[i].classifier + j + 1; 1025793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1] = classifiers[1]->node; 1026793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[2] = cascade->stage_classifier[i].classifier + j + 2; 1027793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2] = classifiers[2]->node; 1028793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[3] = cascade->stage_classifier[i].classifier + j + 3; 1029793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3] = classifiers[3]->node; 1030793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[4] = cascade->stage_classifier[i].classifier + j + 4; 1031793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4] = classifiers[4]->node; 1032793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[5] = cascade->stage_classifier[i].classifier + j + 5; 1033793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5] = classifiers[5]->node; 1034793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[6] = cascade->stage_classifier[i].classifier + j + 6; 1035793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6] = classifiers[6]->node; 1036793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[7] = cascade->stage_classifier[i].classifier + j + 7; 1037793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[7] = classifiers[7]->node; 1038793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1039793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 t = _mm256_set1_ps(static_cast<float>(variance_norm_factor)); 1040793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1041793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler t = _mm256_mul_ps(t, _mm256_set_ps(nodes[7]->threshold, 1042793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->threshold, 1043793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->threshold, 1044793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->threshold, 1045793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->threshold, 1046793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->threshold, 1047793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->threshold, 1048793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->threshold)); 1049793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1050793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[0], p_offset), 1051793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[6]->feature.rect[0], p_offset), 1052793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[5]->feature.rect[0], p_offset), 1053793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[4]->feature.rect[0], p_offset), 1054793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[3]->feature.rect[0], p_offset), 1055793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[2]->feature.rect[0], p_offset), 1056793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[1]->feature.rect[0], p_offset), 1057793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[0]->feature.rect[0], p_offset)); 1058793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1059793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 weight = _mm256_set_ps(nodes[7]->feature.rect[0].weight, 1060793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->feature.rect[0].weight, 1061793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->feature.rect[0].weight, 1062793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->feature.rect[0].weight, 1063793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->feature.rect[0].weight, 1064793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->feature.rect[0].weight, 1065793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->feature.rect[0].weight, 1066793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->feature.rect[0].weight); 1067793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1068793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 sum = _mm256_mul_ps(offset, weight); 1069793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1070793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler offset = _mm256_set_ps(calc_sumf(nodes[7]->feature.rect[1], p_offset), 1071793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[6]->feature.rect[1], p_offset), 1072793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[5]->feature.rect[1], p_offset), 1073793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[4]->feature.rect[1], p_offset), 1074793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[3]->feature.rect[1], p_offset), 1075793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[2]->feature.rect[1], p_offset), 1076793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[1]->feature.rect[1], p_offset), 1077793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sumf(nodes[0]->feature.rect[1], p_offset)); 1078793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1079793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler weight = _mm256_set_ps(nodes[7]->feature.rect[1].weight, 1080793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[6]->feature.rect[1].weight, 1081793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[5]->feature.rect[1].weight, 1082793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[4]->feature.rect[1].weight, 1083793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[3]->feature.rect[1].weight, 1084793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[2]->feature.rect[1].weight, 1085793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[1]->feature.rect[1].weight, 1086793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler nodes[0]->feature.rect[1].weight); 1087793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1088793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum = _mm256_add_ps(sum, _mm256_mul_ps(offset, weight)); 1089793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1090793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[0]->feature.rect[2].p0 ) 1091793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[0] = calc_sumf(nodes[0]->feature.rect[2],p_offset) * nodes[0]->feature.rect[2].weight; 1092793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[1]->feature.rect[2].p0 ) 1093793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[1] = calc_sumf(nodes[1]->feature.rect[2],p_offset) * nodes[1]->feature.rect[2].weight; 1094793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[2]->feature.rect[2].p0 ) 1095793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[2] = calc_sumf(nodes[2]->feature.rect[2],p_offset) * nodes[2]->feature.rect[2].weight; 1096793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[3]->feature.rect[2].p0 ) 1097793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[3] = calc_sumf(nodes[3]->feature.rect[2],p_offset) * nodes[3]->feature.rect[2].weight; 1098793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[4]->feature.rect[2].p0 ) 1099793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[4] = calc_sumf(nodes[4]->feature.rect[2],p_offset) * nodes[4]->feature.rect[2].weight; 1100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[5]->feature.rect[2].p0 ) 1101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[5] = calc_sumf(nodes[5]->feature.rect[2],p_offset) * nodes[5]->feature.rect[2].weight; 1102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[6]->feature.rect[2].p0 ) 1103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[6] = calc_sumf(nodes[6]->feature.rect[2],p_offset) * nodes[6]->feature.rect[2].weight; 1104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( nodes[7]->feature.rect[2].p0 ) 1105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tmp[7] = calc_sumf(nodes[7]->feature.rect[2],p_offset) * nodes[7]->feature.rect[2].weight; 1106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum = _mm256_add_ps(sum, _mm256_load_ps(tmp)); 1108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 alpha0 = _mm256_set_ps(classifiers[7]->alpha[0], 1110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[6]->alpha[0], 1111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[5]->alpha[0], 1112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[4]->alpha[0], 1113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[3]->alpha[0], 1114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[2]->alpha[0], 1115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[1]->alpha[0], 1116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[0]->alpha[0]); 1117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 alpha1 = _mm256_set_ps(classifiers[7]->alpha[1], 1118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[6]->alpha[1], 1119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[5]->alpha[1], 1120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[4]->alpha[1], 1121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[3]->alpha[1], 1122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[2]->alpha[1], 1123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[1]->alpha[1], 1124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifiers[0]->alpha[1]); 1125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m256 outBuf = _mm256_blendv_ps(alpha0, alpha1, _mm256_cmp_ps(t, sum, _CMP_LE_OQ )); 1127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outBuf = _mm256_hadd_ps(outBuf, outBuf); 1128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outBuf = _mm256_hadd_ps(outBuf, outBuf); 1129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _mm256_store_ps(buf, outBuf); 1130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += (buf[0] + buf[4]); 1131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ; j < cascade->stage_classifier[i].count; j++ ) 1134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 1136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = classifier->node; 1137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double t = node->threshold*variance_norm_factor; 1139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 1140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 1141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( node->feature.rect[2].p0 ) 1142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 1143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += classifier->alpha[sum >= t]; 1144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( stage_sum < cascade->stage_classifier[i].threshold ) 1147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return -i; 1148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#elif defined CV_HAAR_USE_SSE //old SSE optimization 1152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(haveSSE2) 1153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = start_stage; i < cascade->count; i++ ) 1155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d vstage_sum = _mm_setzero_pd(); 1157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->stage_classifier[i].two_rects ) 1158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 1160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 1162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = classifier->node; 1163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // ayasin - NHM perf optim. Avoid use of costly flaky jcc 1165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d t = _mm_set_sd(node->threshold*variance_norm_factor); 1166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d a = _mm_set_sd(classifier->alpha[0]); 1167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d b = _mm_set_sd(classifier->alpha[1]); 1168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d sum = _mm_set_sd(calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight + 1169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight); 1170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler t = _mm_cmpgt_sd(t, sum); 1171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vstage_sum = _mm_add_sd(vstage_sum, _mm_blendv_pd(b, a, t)); 1172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 1177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 1179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = classifier->node; 1180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // ayasin - NHM perf optim. Avoid use of costly flaky jcc 1181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d t = _mm_set_sd(node->threshold*variance_norm_factor); 1182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d a = _mm_set_sd(classifier->alpha[0]); 1183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d b = _mm_set_sd(classifier->alpha[1]); 1184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double _sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 1185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 1186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( node->feature.rect[2].p0 ) 1187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 1188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d sum = _mm_set_sd(_sum); 1189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler t = _mm_cmpgt_sd(t, sum); 1191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vstage_sum = _mm_add_sd(vstage_sum, _mm_blendv_pd(b, a, t)); 1192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __m128d i_threshold = _mm_set1_pd(cascade->stage_classifier[i].threshold); 1195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( _mm_comilt_sd(vstage_sum, i_threshold) ) 1196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return -i; 1197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif // AVX or SSE 1201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = start_stage; i < cascade->count; i++ ) 1203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum = 0.0; 1205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->stage_classifier[i].two_rects ) 1206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 1208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 1210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = classifier->node; 1211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double t = node->threshold*variance_norm_factor; 1212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 1213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 1214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += classifier->alpha[sum >= t]; 1215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 1220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 1222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHidHaarTreeNode* node = classifier->node; 1223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double t = node->threshold*variance_norm_factor; 1224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 1225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 1226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( node->feature.rect[2].p0 ) 1227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 1228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += classifier->alpha[sum >= t]; 1229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( stage_sum < cascade->stage_classifier[i].threshold ) 1232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return -i; 1233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = start_stage; i < cascade->count; i++ ) 1239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum = 0.0; 1241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int k = 0; 1242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef CV_HAAR_USE_AVX 1244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(haveAVX) 1245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ; k < cascade->stage_classifier[i].count - 8; k += 8 ) 1247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += icvEvalHidHaarClassifierAVX( 1249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].classifier + k, 1250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler variance_norm_factor, p_offset ); 1251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 1254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for(; k < cascade->stage_classifier[i].count; k++ ) 1255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_sum += icvEvalHidHaarClassifier( 1258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].classifier + k, 1259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler variance_norm_factor, p_offset ); 1260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( stage_sum < cascade->stage_classifier[i].threshold ) 1263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return -i; 1264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return 1; 1267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 1268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1270793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCV_IMPL int 1271793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslercvRunHaarClassifierCascade( const CvHaarClassifierCascade* _cascade, 1272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvPoint pt, int start_stage ) 1273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 1274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double stage_sum; 1275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cvRunHaarClassifierCascadeSum(_cascade, pt, stage_sum, start_stage); 1276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 1277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernamespace cv 1279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 1280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerclass HaarDetectObjects_ScaleImage_Invoker : public ParallelLoopBody 1282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 1283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerpublic: 1284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler HaarDetectObjects_ScaleImage_Invoker( const CvHaarClassifierCascade* _cascade, 1285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int _stripSize, double _factor, 1286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const Mat& _sum1, const Mat& _sqsum1, Mat* _norm1, 1287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mat* _mask1, Rect _equRect, std::vector<Rect>& _vec, 1288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<int>& _levels, std::vector<double>& _weights, 1289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool _outputLevels, Mutex *_mtx ) 1290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade = _cascade; 1292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stripSize = _stripSize; 1293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler factor = _factor; 1294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum1 = _sum1; 1295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sqsum1 = _sqsum1; 1296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler norm1 = _norm1; 1297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mask1 = _mask1; 1298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect = _equRect; 1299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vec = &_vec; 1300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rejectLevels = _outputLevels ? &_levels : 0; 1301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler levelWeights = _outputLevels ? &_weights : 0; 1302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx = _mtx; 1303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void operator()( const Range& range ) const 1306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Size winSize0 = cascade->orig_window_size; 1308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Size winSize(cvRound(winSize0.width*factor), cvRound(winSize0.height*factor)); 1309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int y1 = range.start*stripSize, y2 = std::min(range.end*stripSize, sum1.rows - 1 - winSize0.height); 1310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (y2 <= y1 || sum1.cols <= 1 + winSize0.width) 1312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return; 1313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Size ssz(sum1.cols - 1 - winSize0.width, y2 - y1); 1315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int x, y, ystep = factor > 2 ? 1 : 2; 1316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_IPP 1318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(CV_IPP_CHECK_COND && cascade->hid_cascade->ipp_stages ) 1319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler IppiRect iequRect = {equRect.x, equRect.y, equRect.width, equRect.height}; 1321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ippiRectStdDev_32f_C1R(sum1.ptr<float>(y1), (int)sum1.step, 1322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sqsum1.ptr<double>(y1), (int)sqsum1.step, 1323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler norm1->ptr<float>(y1), (int)norm1->step, 1324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ippiSize(ssz.width, ssz.height), iequRect ); 1325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int positive = (ssz.width/ystep)*((ssz.height + ystep-1)/ystep); 1327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( ystep == 1 ) 1329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*mask1) = Scalar::all(1); 1330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( y = y1; y < y2; y++ ) 1332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler uchar* mask1row = mask1->ptr(y); 1334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler memset( mask1row, 0, ssz.width ); 1335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( y % ystep == 0 ) 1337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( x = 0; x < ssz.width; x += ystep ) 1338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mask1row[x] = (uchar)1; 1339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( int j = 0; j < cascade->count; j++ ) 1342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( ippiApplyHaarClassifier_32f_C1R( 1344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum1.ptr<float>(y1), (int)sum1.step, 1345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler norm1->ptr<float>(y1), (int)norm1->step, 1346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mask1->ptr<uchar>(y1), (int)mask1->step, 1347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ippiSize(ssz.width, ssz.height), &positive, 1348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->hid_cascade->stage_classifier[j].threshold, 1349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (IppiHaarClassifier_32f*)cascade->hid_cascade->ipp_stages[j]) < 0 ) 1350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler positive = 0; 1351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( positive <= 0 ) 1352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 1353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); 1355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( positive > 0 ) 1357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( y = y1; y < y2; y += ystep ) 1358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler uchar* mask1row = mask1->ptr(y); 1360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( x = 0; x < ssz.width; x += ystep ) 1361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( mask1row[x] != 0 ) 1362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx->lock(); 1364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vec->push_back(Rect(cvRound(x*factor), cvRound(y*factor), 1365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler winSize.width, winSize.height)); 1366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx->unlock(); 1367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( --positive == 0 ) 1368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 1369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( positive == 0 ) 1371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 1372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif // IPP 1376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( y = y1; y < y2; y += ystep ) 1377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( x = 0; x < ssz.width; x += ystep ) 1378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double gypWeight; 1380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int result = cvRunHaarClassifierCascadeSum( cascade, cvPoint(x,y), gypWeight, 0 ); 1381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( rejectLevels ) 1382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( result == 1 ) 1384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler result = -1*cascade->count; 1385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->count + result < 4 ) 1386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx->lock(); 1388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vec->push_back(Rect(cvRound(x*factor), cvRound(y*factor), 1389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler winSize.width, winSize.height)); 1390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rejectLevels->push_back(-result); 1391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler levelWeights->push_back(gypWeight); 1392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx->unlock(); 1393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( result > 0 ) 1398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx->lock(); 1400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vec->push_back(Rect(cvRound(x*factor), cvRound(y*factor), 1401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler winSize.width, winSize.height)); 1402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx->unlock(); 1403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const CvHaarClassifierCascade* cascade; 1409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int stripSize; 1410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double factor; 1411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mat sum1, sqsum1, *norm1, *mask1; 1412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Rect equRect; 1413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<Rect>* vec; 1414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<int>* rejectLevels; 1415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<double>* levelWeights; 1416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mutex* mtx; 1417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; 1418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerclass HaarDetectObjects_ScaleCascade_Invoker : public ParallelLoopBody 1421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 1422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerpublic: 1423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler HaarDetectObjects_ScaleCascade_Invoker( const CvHaarClassifierCascade* _cascade, 1424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Size _winsize, const Range& _xrange, double _ystep, 1425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size_t _sumstep, const int** _p, const int** _pq, 1426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<Rect>& _vec, Mutex* _mtx ) 1427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade = _cascade; 1429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler winsize = _winsize; 1430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler xrange = _xrange; 1431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ystep = _ystep; 1432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sumstep = _sumstep; 1433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler p = _p; pq = _pq; 1434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vec = &_vec; 1435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx = _mtx; 1436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void operator()( const Range& range ) const 1439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int iy, startY = range.start, endY = range.end; 1441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const int *p0 = p[0], *p1 = p[1], *p2 = p[2], *p3 = p[3]; 1442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const int *pq0 = pq[0], *pq1 = pq[1], *pq2 = pq[2], *pq3 = pq[3]; 1443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool doCannyPruning = p0 != 0; 1444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int sstep = (int)(sumstep/sizeof(p0[0])); 1445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( iy = startY; iy < endY; iy++ ) 1447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int ix, y = cvRound(iy*ystep), ixstep = 1; 1449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ix = xrange.start; ix < xrange.end; ix += ixstep ) 1450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int x = cvRound(ix*ystep); // it should really be ystep, not ixstep 1452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( doCannyPruning ) 1454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int offset = y*sstep + x; 1456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int s = p0[offset] - p1[offset] - p2[offset] + p3[offset]; 1457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int sq = pq0[offset] - pq1[offset] - pq2[offset] + pq3[offset]; 1458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( s < 100 || sq < 20 ) 1459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ixstep = 2; 1461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler continue; 1462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int result = cvRunHaarClassifierCascade( cascade, cvPoint(x, y), 0 ); 1466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( result > 0 ) 1467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx->lock(); 1469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler vec->push_back(Rect(x, y, winsize.width, winsize.height)); 1470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mtx->unlock(); 1471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ixstep = result != 0 ? 1 : 2; 1473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const CvHaarClassifierCascade* cascade; 1478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double ystep; 1479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size_t sumstep; 1480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Size winsize; 1481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Range xrange; 1482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const int** p; 1483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const int** pq; 1484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<Rect>* vec; 1485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Mutex* mtx; 1486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; 1487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 1490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1492793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCvSeq* 1493793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslercvHaarDetectObjectsForROC( const CvArr* _img, 1494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifierCascade* cascade, CvMemStorage* storage, 1495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<int>& rejectLevels, std::vector<double>& levelWeights, 1496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double scaleFactor, int minNeighbors, int flags, 1497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSize minSize, CvSize maxSize, bool outputRejectLevels ) 1498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 1499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const double GROUP_EPS = 0.2; 1500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvMat stub, *img = (CvMat*)_img; 1501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Ptr<CvMat> temp, sum, tilted, sqsum, normImg, sumcanny, imgSmall; 1502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSeq* result_seq = 0; 1503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Ptr<CvMemStorage> temp_storage; 1504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<cv::Rect> allCandidates; 1506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<cv::Rect> rectList; 1507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<int> rweights; 1508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double factor; 1509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int coi; 1510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool doCannyPruning = (flags & CV_HAAR_DO_CANNY_PRUNING) != 0; 1511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool findBiggestObject = (flags & CV_HAAR_FIND_BIGGEST_OBJECT) != 0; 1512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool roughSearch = (flags & CV_HAAR_DO_ROUGH_SEARCH) != 0; 1513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Mutex mtx; 1514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_IS_HAAR_CLASSIFIER(cascade) ) 1516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier cascade" ); 1517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !storage ) 1519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsNullPtr, "Null storage pointer" ); 1520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler img = cvGetMat( img, &stub, &coi ); 1522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( coi ) 1523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_BadCOI, "COI is not supported" ); 1524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( CV_MAT_DEPTH(img->type) != CV_8U ) 1526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsUnsupportedFormat, "Only 8-bit images are supported" ); 1527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( scaleFactor <= 1 ) 1529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsOutOfRange, "scale factor must be > 1" ); 1530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( findBiggestObject ) 1532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler flags &= ~CV_HAAR_SCALE_IMAGE; 1533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( maxSize.height == 0 || maxSize.width == 0 ) 1535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler maxSize.height = img->rows; 1537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler maxSize.width = img->cols; 1538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler temp.reset(cvCreateMat( img->rows, img->cols, CV_8UC1 )); 1541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 )); 1542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sqsum.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_64FC1 )); 1543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !cascade->hid_cascade ) 1545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler icvCreateHidHaarClassifierCascade(cascade); 1546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( cascade->hid_cascade->has_tilted_features ) 1548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tilted.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 )); 1549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), storage ); 1551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( CV_MAT_CN(img->type) > 1 ) 1553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvCvtColor( img, temp, CV_BGR2GRAY ); 1555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler img = temp; 1556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( findBiggestObject ) 1559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler flags &= ~(CV_HAAR_SCALE_IMAGE|CV_HAAR_DO_CANNY_PRUNING); 1560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( flags & CV_HAAR_SCALE_IMAGE ) 1562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSize winSize0 = cascade->orig_window_size; 1564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_IPP 1565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int use_ipp = CV_IPP_CHECK_COND && (cascade->hid_cascade->ipp_stages != 0); 1566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( use_ipp ) 1568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler normImg.reset(cvCreateMat( img->rows, img->cols, CV_32FC1)); 1569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 1570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler imgSmall.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_8UC1 )); 1571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( factor = 1; ; factor *= scaleFactor ) 1573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSize winSize(cvRound(winSize0.width*factor), 1575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvRound(winSize0.height*factor)); 1576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSize sz(cvRound( img->cols/factor ), cvRound( img->rows/factor )); 1577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSize sz1(sz.width - winSize0.width + 1, sz.height - winSize0.height + 1); 1578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect equRect(icv_object_win_border, icv_object_win_border, 1580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler winSize0.width - icv_object_win_border*2, 1581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler winSize0.height - icv_object_win_border*2); 1582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvMat img1, sum1, sqsum1, norm1, tilted1, mask1; 1584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvMat* _tilted = 0; 1585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( sz1.width <= 0 || sz1.height <= 0 ) 1587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 1588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( winSize.width > maxSize.width || winSize.height > maxSize.height ) 1589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 1590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( winSize.width < minSize.width || winSize.height < minSize.height ) 1591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler continue; 1592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler img1 = cvMat( sz.height, sz.width, CV_8UC1, imgSmall->data.ptr ); 1594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sum1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, sum->data.ptr ); 1595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sqsum1 = cvMat( sz.height+1, sz.width+1, CV_64FC1, sqsum->data.ptr ); 1596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( tilted ) 1597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tilted1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, tilted->data.ptr ); 1599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _tilted = &tilted1; 1600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler norm1 = cvMat( sz1.height, sz1.width, CV_32FC1, normImg ? normImg->data.ptr : 0 ); 1602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler mask1 = cvMat( sz1.height, sz1.width, CV_8UC1, temp->data.ptr ); 1603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvResize( img, &img1, CV_INTER_LINEAR ); 1605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvIntegral( &img1, &sum1, &sqsum1, _tilted ); 1606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int ystep = factor > 2 ? 1 : 2; 1608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const int LOCS_PER_THREAD = 1000; 1609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int stripCount = ((sz1.width/ystep)*(sz1.height + ystep-1)/ystep + LOCS_PER_THREAD/2)/LOCS_PER_THREAD; 1610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stripCount = std::min(std::max(stripCount, 1), 100); 1611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef HAVE_IPP 1613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( use_ipp ) 1614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Mat fsum(sum1.rows, sum1.cols, CV_32F, sum1.data.ptr, sum1.step); 1616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::cvarrToMat(&sum1).convertTo(fsum, CV_32F, 1, -(1<<24)); 1617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1619793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 1620793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvSetImagesForHaarClassifierCascade( cascade, &sum1, &sqsum1, _tilted, 1. ); 1621793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1622793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Mat _norm1 = cv::cvarrToMat(&norm1), _mask1 = cv::cvarrToMat(&mask1); 1623793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::parallel_for_(cv::Range(0, stripCount), 1624793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::HaarDetectObjects_ScaleImage_Invoker(cascade, 1625793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (((sz1.height + stripCount - 1)/stripCount + ystep-1)/ystep)*ystep, 1626793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler factor, cv::cvarrToMat(&sum1), cv::cvarrToMat(&sqsum1), &_norm1, &_mask1, 1627793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Rect(equRect), allCandidates, rejectLevels, levelWeights, outputRejectLevels, &mtx)); 1628793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1629793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1630793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1631793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1632793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int n_factors = 0; 1633793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Rect scanROI; 1634793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1635793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvIntegral( img, sum, sqsum, tilted ); 1636793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1637793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( doCannyPruning ) 1638793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1639793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sumcanny.reset(cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 )); 1640793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvCanny( img, temp, 0, 50, 3 ); 1641793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvIntegral( temp, sumcanny ); 1642793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1643793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1644793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( n_factors = 0, factor = 1; 1645793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler factor*cascade->orig_window_size.width < img->cols - 10 && 1646793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler factor*cascade->orig_window_size.height < img->rows - 10; 1647793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler n_factors++, factor *= scaleFactor ) 1648793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ; 1649793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1650793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( findBiggestObject ) 1651793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1652793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler scaleFactor = 1./scaleFactor; 1653793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler factor *= scaleFactor; 1654793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1655793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1656793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler factor = 1; 1657793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1658793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( ; n_factors-- > 0; factor *= scaleFactor ) 1659793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1660793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const double ystep = std::max( 2., factor ); 1661793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSize winSize(cvRound( cascade->orig_window_size.width * factor ), 1662793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvRound( cascade->orig_window_size.height * factor )); 1663793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect equRect; 1664793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int *p[4] = {0,0,0,0}; 1665793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int *pq[4] = {0,0,0,0}; 1666793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int startX = 0, startY = 0; 1667793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int endX = cvRound((img->cols - winSize.width) / ystep); 1668793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int endY = cvRound((img->rows - winSize.height) / ystep); 1669793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1670793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( winSize.width < minSize.width || winSize.height < minSize.height ) 1671793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1672793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( findBiggestObject ) 1673793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 1674793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler continue; 1675793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1676793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1677793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if ( winSize.width > maxSize.width || winSize.height > maxSize.height ) 1678793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1679793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !findBiggestObject ) 1680793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 1681793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler continue; 1682793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1683793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1684793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvSetImagesForHaarClassifierCascade( cascade, sum, sqsum, tilted, factor ); 1685793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvZero( temp ); 1686793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1687793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( doCannyPruning ) 1688793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1689793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.x = cvRound(winSize.width*0.15); 1690793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.y = cvRound(winSize.height*0.15); 1691793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.width = cvRound(winSize.width*0.7); 1692793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler equRect.height = cvRound(winSize.height*0.7); 1693793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1694793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler p[0] = (int*)(sumcanny->data.ptr + equRect.y*sumcanny->step) + equRect.x; 1695793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler p[1] = (int*)(sumcanny->data.ptr + equRect.y*sumcanny->step) 1696793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler + equRect.x + equRect.width; 1697793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler p[2] = (int*)(sumcanny->data.ptr + (equRect.y + equRect.height)*sumcanny->step) + equRect.x; 1698793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler p[3] = (int*)(sumcanny->data.ptr + (equRect.y + equRect.height)*sumcanny->step) 1699793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler + equRect.x + equRect.width; 1700793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1701793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pq[0] = (int*)(sum->data.ptr + equRect.y*sum->step) + equRect.x; 1702793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pq[1] = (int*)(sum->data.ptr + equRect.y*sum->step) 1703793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler + equRect.x + equRect.width; 1704793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pq[2] = (int*)(sum->data.ptr + (equRect.y + equRect.height)*sum->step) + equRect.x; 1705793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pq[3] = (int*)(sum->data.ptr + (equRect.y + equRect.height)*sum->step) 1706793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler + equRect.x + equRect.width; 1707793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1708793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1709793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( scanROI.area() > 0 ) 1710793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1711793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler //adjust start_height and stop_height 1712793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler startY = cvRound(scanROI.y / ystep); 1713793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler endY = cvRound((scanROI.y + scanROI.height - winSize.height) / ystep); 1714793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1715793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler startX = cvRound(scanROI.x / ystep); 1716793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler endX = cvRound((scanROI.x + scanROI.width - winSize.width) / ystep); 1717793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1718793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1719793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::parallel_for_(cv::Range(startY, endY), 1720793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::HaarDetectObjects_ScaleCascade_Invoker(cascade, winSize, cv::Range(startX, endX), 1721793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ystep, sum->step, (const int**)p, 1722793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (const int**)pq, allCandidates, &mtx )); 1723793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1724793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( findBiggestObject && !allCandidates.empty() && scanROI.area() == 0 ) 1725793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1726793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rectList.resize(allCandidates.size()); 1727793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::copy(allCandidates.begin(), allCandidates.end(), rectList.begin()); 1728793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1729793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler groupRectangles(rectList, std::max(minNeighbors, 1), GROUP_EPS); 1730793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1731793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !rectList.empty() ) 1732793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1733793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size_t i, sz = rectList.size(); 1734793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Rect maxRect; 1735793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1736793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < sz; i++ ) 1737793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1738793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( rectList[i].area() > maxRect.area() ) 1739793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler maxRect = rectList[i]; 1740793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1741793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1742793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler allCandidates.push_back(maxRect); 1743793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1744793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler scanROI = maxRect; 1745793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int dx = cvRound(maxRect.width*GROUP_EPS); 1746793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int dy = cvRound(maxRect.height*GROUP_EPS); 1747793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler scanROI.x = std::max(scanROI.x - dx, 0); 1748793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler scanROI.y = std::max(scanROI.y - dy, 0); 1749793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler scanROI.width = std::min(scanROI.width + dx*2, img->cols-1-scanROI.x); 1750793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler scanROI.height = std::min(scanROI.height + dy*2, img->rows-1-scanROI.y); 1751793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1752793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double minScale = roughSearch ? 0.6 : 0.4; 1753793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler minSize.width = cvRound(maxRect.width*minScale); 1754793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler minSize.height = cvRound(maxRect.height*minScale); 1755793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1756793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1757793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1758793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1759793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1760793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rectList.resize(allCandidates.size()); 1761793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if(!allCandidates.empty()) 1762793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::copy(allCandidates.begin(), allCandidates.end(), rectList.begin()); 1763793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1764793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( minNeighbors != 0 || findBiggestObject ) 1765793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1766793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( outputRejectLevels ) 1767793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1768793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler groupRectangles(rectList, rejectLevels, levelWeights, minNeighbors, GROUP_EPS ); 1769793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1770793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1771793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1772793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler groupRectangles(rectList, rweights, std::max(minNeighbors, 1), GROUP_EPS); 1773793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1774793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1775793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1776793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rweights.resize(rectList.size(),0); 1777793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1778793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( findBiggestObject && rectList.size() ) 1779793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1780793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvAvgComp result_comp = {CvRect(),0}; 1781793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1782793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( size_t i = 0; i < rectList.size(); i++ ) 1783793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1784793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cv::Rect r = rectList[i]; 1785793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( r.area() > cv::Rect(result_comp.rect).area() ) 1786793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1787793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler result_comp.rect = r; 1788793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler result_comp.neighbors = rweights[i]; 1789793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1790793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1791793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvSeqPush( result_seq, &result_comp ); 1792793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1793793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 1794793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1795793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( size_t i = 0; i < rectList.size(); i++ ) 1796793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1797793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvAvgComp c; 1798793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler c.rect = rectList[i]; 1799793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler c.neighbors = !rweights.empty() ? rweights[i] : 0; 1800793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvSeqPush( result_seq, &c ); 1801793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1802793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1803793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1804793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return result_seq; 1805793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 1806793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1807793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCV_IMPL CvSeq* 1808793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslercvHaarDetectObjects( const CvArr* _img, 1809793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifierCascade* cascade, CvMemStorage* storage, 1810793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler double scaleFactor, 1811793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int minNeighbors, int flags, CvSize minSize, CvSize maxSize ) 1812793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 1813793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<int> fakeLevels; 1814793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::vector<double> fakeWeights; 1815793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cvHaarDetectObjectsForROC( _img, cascade, storage, fakeLevels, fakeWeights, 1816793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler scaleFactor, minNeighbors, flags, minSize, maxSize, false ); 1817793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1818793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 1819793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1820793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1821793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic CvHaarClassifierCascade* 1822793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslericvLoadCascadeCART( const char** input_cascade, int n, CvSize orig_window_size ) 1823793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 1824793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i; 1825793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifierCascade* cascade = icvCreateHaarClassifierCascade(n); 1826793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->orig_window_size = orig_window_size; 1827793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1828793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < n; i++ ) 1829793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1830793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int j, count, l; 1831793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler float threshold = 0; 1832793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const char* stage = input_cascade[i]; 1833793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int dl = 0; 1834793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1835793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* tree links */ 1836793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int parent = -1; 1837793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int next = -1; 1838793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1839793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sscanf( stage, "%d%n", &count, &dl ); 1840793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1841793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1842793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler assert( count > 0 ); 1843793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].count = count; 1844793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].classifier = 1845793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (CvHaarClassifier*)cvAlloc( count*sizeof(cascade->stage_classifier[i].classifier[0])); 1846793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1847793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < count; j++ ) 1848793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1849793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 1850793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int k, rects = 0; 1851793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler char str[100]; 1852793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1853793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sscanf( stage, "%d%n", &classifier->count, &dl ); 1854793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1855793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1856793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature = (CvHaarFeature*) cvAlloc( 1857793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->count * ( sizeof( *classifier->haar_feature ) + 1858793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->threshold ) + 1859793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->left ) + 1860793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->right ) ) + 1861793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (classifier->count + 1) * sizeof( *classifier->alpha ) ); 1862793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->threshold = (float*) (classifier->haar_feature+classifier->count); 1863793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->left = (int*) (classifier->threshold + classifier->count); 1864793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->right = (int*) (classifier->left + classifier->count); 1865793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->alpha = (float*) (classifier->right + classifier->count); 1866793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1867793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = 0; l < classifier->count; l++ ) 1868793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1869793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sscanf( stage, "%d%n", &rects, &dl ); 1870793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1871793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1872793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler assert( rects >= 2 && rects <= CV_HAAR_FEATURE_MAX ); 1873793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1874793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( k = 0; k < rects; k++ ) 1875793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1876793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect r; 1877793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int band = 0; 1878793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sscanf( stage, "%d%d%d%d%d%f%n", 1879793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler &r.x, &r.y, &r.width, &r.height, &band, 1880793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler &(classifier->haar_feature[l].rect[k].weight), &dl ); 1881793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1882793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature[l].rect[k].r = r; 1883793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1884793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sscanf( stage, "%s%n", str, &dl ); 1885793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1886793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1887793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature[l].tilted = strncmp( str, "tilted", 6 ) == 0; 1888793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1889793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( k = rects; k < CV_HAAR_FEATURE_MAX; k++ ) 1890793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1891793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler memset( classifier->haar_feature[l].rect + k, 0, 1892793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof(classifier->haar_feature[l].rect[k]) ); 1893793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1894793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1895793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sscanf( stage, "%f%d%d%n", &(classifier->threshold[l]), 1896793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler &(classifier->left[l]), 1897793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler &(classifier->right[l]), &dl ); 1898793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1899793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1900793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = 0; l <= classifier->count; l++ ) 1901793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1902793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sscanf( stage, "%f%n", &(classifier->alpha[l]), &dl ); 1903793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1904793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1905793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1906793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1907793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sscanf( stage, "%f%n", &threshold, &dl ); 1908793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1909793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1910793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].threshold = threshold; 1911793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1912793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* load tree links */ 1913793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( sscanf( stage, "%d%d%n", &parent, &next, &dl ) != 2 ) 1914793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1915793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler parent = i - 1; 1916793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler next = -1; 1917793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1918793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage += dl; 1919793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1920793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].parent = parent; 1921793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].next = next; 1922793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].child = -1; 1923793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1924793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( parent != -1 && cascade->stage_classifier[parent].child == -1 ) 1925793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1926793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[parent].child = i; 1927793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1928793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1929793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1930793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cascade; 1931793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 1932793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1933793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifndef _MAX_PATH 1934793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define _MAX_PATH 1024 1935793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 1936793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1937793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCV_IMPL CvHaarClassifierCascade* 1938793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslercvLoadHaarClassifierCascade( const char* directory, CvSize orig_window_size ) 1939793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 1940793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !directory ) 1941793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsNullPtr, "Null path is passed" ); 1942793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1943793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler char name[_MAX_PATH]; 1944793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1945793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int n = (int)strlen(directory)-1; 1946793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const char* slash = directory[n] == '\\' || directory[n] == '/' ? "" : "/"; 1947793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int size = 0; 1948793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1949793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* try to read the classifier from directory */ 1950793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( n = 0; ; n++ ) 1951793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1952793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( name, "%s%s%d/AdaBoostCARTHaarClassifier.txt", directory, slash, n ); 1953793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler FILE* f = fopen( name, "rb" ); 1954793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !f ) 1955793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 1956793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fseek( f, 0, SEEK_END ); 1957793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size += ftell( f ) + 1; 1958793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fclose(f); 1959793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1960793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1961793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( n == 0 && slash[0] ) 1962793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return (CvHaarClassifierCascade*)cvLoad( directory ); 1963793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1964793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( n == 0 ) 1965793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsBadArg, "Invalid path" ); 1966793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1967793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size += (n+1)*sizeof(char*); 1968793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const char** input_cascade = (const char**)cvAlloc( size ); 1969793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1970793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !input_cascade ) 1971793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsNoMem, "Could not allocate memory for input_cascade" ); 1972793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1973793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler char* ptr = (char*)(input_cascade + n + 1); 1974793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1975793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( int i = 0; i < n; i++ ) 1976793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 1977793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( name, "%s/%d/AdaBoostCARTHaarClassifier.txt", directory, i ); 1978793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler FILE* f = fopen( name, "rb" ); 1979793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !f ) 1980793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, "" ); 1981793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fseek( f, 0, SEEK_END ); 1982793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size = (int)ftell( f ); 1983793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fseek( f, 0, SEEK_SET ); 1984793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler size_t elements_read = fread( ptr, 1, size, f ); 1985793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Assert(elements_read == (size_t)(size)); 1986793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fclose(f); 1987793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_cascade[i] = ptr; 1988793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ptr += size; 1989793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *ptr++ = '\0'; 1990793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 1991793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1992793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_cascade[n] = 0; 1993793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1994793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifierCascade* cascade = icvLoadCascadeCART( input_cascade, n, orig_window_size ); 1995793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1996793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( input_cascade ) 1997793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &input_cascade ); 1998793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 1999793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cascade; 2000793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 2001793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2002793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2003793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCV_IMPL void 2004793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslercvReleaseHaarClassifierCascade( CvHaarClassifierCascade** _cascade ) 2005793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 2006793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( _cascade && *_cascade ) 2007793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2008793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i, j; 2009793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifierCascade* cascade = *_cascade; 2010793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2011793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < cascade->count; i++ ) 2012793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2013793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 2014793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &cascade->stage_classifier[i].classifier[j].haar_feature ); 2015793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( &cascade->stage_classifier[i].classifier ); 2016793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2017793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler icvReleaseHidHaarClassifierCascade( &cascade->hid_cascade ); 2018793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvFree( _cascade ); 2019793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2020793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 2021793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2022793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2023793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/****************************************************************************************\ 2024793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler* Persistence functions * 2025793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler\****************************************************************************************/ 2026793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2027793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* field names */ 2028793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2029793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_SIZE_NAME "size" 2030793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_STAGES_NAME "stages" 2031793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_TREES_NAME "trees" 2032793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_FEATURE_NAME "feature" 2033793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_RECTS_NAME "rects" 2034793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_TILTED_NAME "tilted" 2035793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_THRESHOLD_NAME "threshold" 2036793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_LEFT_NODE_NAME "left_node" 2037793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_LEFT_VAL_NAME "left_val" 2038793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_RIGHT_NODE_NAME "right_node" 2039793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_RIGHT_VAL_NAME "right_val" 2040793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_STAGE_THRESHOLD_NAME "stage_threshold" 2041793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_PARENT_NAME "parent" 2042793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ICV_HAAR_NEXT_NAME "next" 2043793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2044793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic int 2045793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslericvIsHaarClassifier( const void* struct_ptr ) 2046793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 2047793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return CV_IS_HAAR_CLASSIFIER( struct_ptr ); 2048793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 2049793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2050793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void* 2051793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslericvReadHaarClassifier( CvFileStorage* fs, CvFileNode* node ) 2052793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 2053793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifierCascade* cascade = NULL; 2054793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2055793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler char buf[256]; 2056793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* seq_fn = NULL; /* sequence */ 2057793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* fn = NULL; 2058793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* stages_fn = NULL; 2059793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSeqReader stages_reader; 2060793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int n; 2061793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i, j, k, l; 2062793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int parent, next; 2063793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2064793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stages_fn = cvGetFileNodeByName( fs, node, ICV_HAAR_STAGES_NAME ); 2065793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !stages_fn || !CV_NODE_IS_SEQ( stages_fn->tag) ) 2066793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, "Invalid stages node" ); 2067793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2068793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler n = stages_fn->data.seq->total; 2069793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade = icvCreateHaarClassifierCascade(n); 2070793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2071793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* read size */ 2072793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler seq_fn = cvGetFileNodeByName( fs, node, ICV_HAAR_SIZE_NAME ); 2073793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !seq_fn || !CV_NODE_IS_SEQ( seq_fn->tag ) || seq_fn->data.seq->total != 2 ) 2074793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, "size node is not a valid sequence." ); 2075793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = (CvFileNode*) cvGetSeqElem( seq_fn->data.seq, 0 ); 2076793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 ) 2077793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, "Invalid size node: width must be positive integer" ); 2078793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->orig_window_size.width = fn->data.i; 2079793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = (CvFileNode*) cvGetSeqElem( seq_fn->data.seq, 1 ); 2080793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 ) 2081793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, "Invalid size node: height must be positive integer" ); 2082793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->orig_window_size.height = fn->data.i; 2083793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2084793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartReadSeq( stages_fn->data.seq, &stages_reader ); 2085793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < n; ++i ) 2086793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2087793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* stage_fn; 2088793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* trees_fn; 2089793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSeqReader trees_reader; 2090793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2091793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler stage_fn = (CvFileNode*) stages_reader.ptr; 2092793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_MAP( stage_fn->tag ) ) 2093793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2094793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Invalid stage %d", i ); 2095793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2096793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2097793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2098793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler trees_fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_TREES_NAME ); 2099793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !trees_fn || !CV_NODE_IS_SEQ( trees_fn->tag ) 2100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || trees_fn->data.seq->total <= 0 ) 2101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Trees node is not a valid sequence. (stage %d)", i ); 2103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].classifier = 2107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (CvHaarClassifier*) cvAlloc( trees_fn->data.seq->total 2108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * sizeof( cascade->stage_classifier[i].classifier[0] ) ); 2109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < trees_fn->data.seq->total; ++j ) 2110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].classifier[j].haar_feature = NULL; 2112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].count = trees_fn->data.seq->total; 2114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartReadSeq( trees_fn->data.seq, &trees_reader ); 2116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < trees_fn->data.seq->total; ++j ) 2117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* tree_fn; 2119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSeqReader tree_reader; 2120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifier* classifier; 2121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int last_idx; 2122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier = &cascade->stage_classifier[i].classifier[j]; 2124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tree_fn = (CvFileNode*) trees_reader.ptr; 2125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_SEQ( tree_fn->tag ) || tree_fn->data.seq->total <= 0 ) 2126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Tree node is not a valid sequence." 2128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler " (stage %d, tree %d)", i, j ); 2129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->count = tree_fn->data.seq->total; 2133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature = (CvHaarFeature*) cvAlloc( 2134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->count * ( sizeof( *classifier->haar_feature ) + 2135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->threshold ) + 2136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->left ) + 2137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->right ) ) + 2138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (classifier->count + 1) * sizeof( *classifier->alpha ) ); 2139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->threshold = (float*) (classifier->haar_feature+classifier->count); 2140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->left = (int*) (classifier->threshold + classifier->count); 2141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->right = (int*) (classifier->left + classifier->count); 2142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->alpha = (float*) (classifier->right + classifier->count); 2143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartReadSeq( tree_fn->data.seq, &tree_reader ); 2145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( k = 0, last_idx = 0; k < tree_fn->data.seq->total; ++k ) 2146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* node_fn; 2148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* feature_fn; 2149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* rects_fn; 2150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvSeqReader rects_reader; 2151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler node_fn = (CvFileNode*) tree_reader.ptr; 2153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_MAP( node_fn->tag ) ) 2154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Tree node %d is not a valid map. (stage %d, tree %d)", 2156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler k, i, j ); 2157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler feature_fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_FEATURE_NAME ); 2160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !feature_fn || !CV_NODE_IS_MAP( feature_fn->tag ) ) 2161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Feature node is not a valid map. " 2163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rects_fn = cvGetFileNodeByName( fs, feature_fn, ICV_HAAR_RECTS_NAME ); 2167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !rects_fn || !CV_NODE_IS_SEQ( rects_fn->tag ) 2168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || rects_fn->data.seq->total < 1 2169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || rects_fn->data.seq->total > CV_HAAR_FEATURE_MAX ) 2170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Rects node is not a valid sequence. " 2172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartReadSeq( rects_fn->data.seq, &rects_reader ); 2176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = 0; l < rects_fn->data.seq->total; ++l ) 2177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvFileNode* rect_fn; 2179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvRect r; 2180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rect_fn = (CvFileNode*) rects_reader.ptr; 2182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_SEQ( rect_fn->tag ) || rect_fn->data.seq->total != 5 ) 2183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Rect %d is not a valid sequence. " 2185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", l, i, j, k ); 2186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 0 ); 2190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i < 0 ) 2191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "x coordinate must be non-negative integer. " 2193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 2194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r.x = fn->data.i; 2197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 1 ); 2198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i < 0 ) 2199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "y coordinate must be non-negative integer. " 2201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 2202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r.y = fn->data.i; 2205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 2 ); 2206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 2207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || r.x + fn->data.i > cascade->orig_window_size.width ) 2208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "width must be positive integer and " 2210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(x + width) must not exceed window width. " 2211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 2212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r.width = fn->data.i; 2215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 3 ); 2216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 2217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || r.y + fn->data.i > cascade->orig_window_size.height ) 2218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "height must be positive integer and " 2220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(y + height) must not exceed window height. " 2221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 2222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r.height = fn->data.i; 2225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 4 ); 2226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_REAL( fn->tag ) ) 2227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "weight must be real number. " 2229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 2230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature[k].rect[l].weight = (float) fn->data.f; 2234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature[k].rect[l].r = r; 2235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_NEXT_SEQ_ELEM( sizeof( *rect_fn ), rects_reader ); 2237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } /* for each rect */ 2238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = rects_fn->data.seq->total; l < CV_HAAR_FEATURE_MAX; ++l ) 2239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature[k].rect[l].weight = 0; 2241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature[k].rect[l].r = cvRect( 0, 0, 0, 0 ); 2242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, feature_fn, ICV_HAAR_TILTED_NAME); 2245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !fn || !CV_NODE_IS_INT( fn->tag ) ) 2246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "tilted must be 0 or 1. " 2248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature[k].tilted = ( fn->data.i != 0 ); 2252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_THRESHOLD_NAME); 2253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !fn || !CV_NODE_IS_REAL( fn->tag ) ) 2254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "threshold must be real number. " 2256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->threshold[k] = (float) fn->data.f; 2260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_LEFT_NODE_NAME); 2261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( fn ) 2262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= k 2264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || fn->data.i >= tree_fn->data.seq->total ) 2265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "left node must be valid node number. " 2267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* left node */ 2271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->left[k] = fn->data.i; 2272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 2274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_LEFT_VAL_NAME ); 2276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !fn ) 2277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "left node or left value must be specified. " 2279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_REAL( fn->tag ) ) 2283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "left value must be real number. " 2285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* left value */ 2289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( last_idx >= classifier->count + 1 ) 2290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Tree structure is broken: too many values. " 2292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->left[k] = -last_idx; 2296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->alpha[last_idx++] = (float) fn->data.f; 2297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, node_fn,ICV_HAAR_RIGHT_NODE_NAME); 2299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( fn ) 2300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= k 2302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || fn->data.i >= tree_fn->data.seq->total ) 2303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "right node must be valid node number. " 2305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* right node */ 2309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->right[k] = fn->data.i; 2310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 2312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_RIGHT_VAL_NAME ); 2314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !fn ) 2315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "right node or right value must be specified. " 2317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !CV_NODE_IS_REAL( fn->tag ) ) 2321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "right value must be real number. " 2323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* right value */ 2327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( last_idx >= classifier->count + 1 ) 2328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Tree structure is broken: too many values. " 2330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d, node %d)", i, j, k ); 2331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->right[k] = -last_idx; 2334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->alpha[last_idx++] = (float) fn->data.f; 2335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_NEXT_SEQ_ELEM( sizeof( *node_fn ), tree_reader ); 2338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } /* for each node */ 2339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( last_idx != classifier->count + 1 ) 2340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "Tree structure is broken: too few values. " 2342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler "(stage %d, tree %d)", i, j ); 2343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_NEXT_SEQ_ELEM( sizeof( *tree_fn ), trees_reader ); 2347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } /* for each tree */ 2348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_STAGE_THRESHOLD_NAME); 2350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !fn || !CV_NODE_IS_REAL( fn->tag ) ) 2351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "stage threshold must be real number. (stage %d)", i ); 2353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].threshold = (float) fn->data.f; 2356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler parent = i - 1; 2358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler next = -1; 2359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_PARENT_NAME ); 2361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !fn || !CV_NODE_IS_INT( fn->tag ) 2362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || fn->data.i < -1 || fn->data.i >= cascade->count ) 2363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "parent must be integer number. (stage %d)", i ); 2365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler parent = fn->data.i; 2368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_NEXT_NAME ); 2369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( !fn || !CV_NODE_IS_INT( fn->tag ) 2370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler || fn->data.i < -1 || fn->data.i >= cascade->count ) 2371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "next must be integer number. (stage %d)", i ); 2373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_Error( CV_StsError, buf ); 2374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler next = fn->data.i; 2376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].parent = parent; 2378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].next = next; 2379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].child = -1; 2380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( parent != -1 && cascade->stage_classifier[parent].child == -1 ) 2382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[parent].child = i; 2384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CV_NEXT_SEQ_ELEM( sizeof( *stage_fn ), stages_reader ); 2387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } /* for each stage */ 2388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cascade; 2390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 2391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void 2393793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslericvWriteHaarClassifier( CvFileStorage* fs, const char* name, const void* struct_ptr, 2394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvAttrList attributes ) 2395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 2396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i, j, k, l; 2397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler char buf[256]; 2398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const CvHaarClassifierCascade* cascade = (const CvHaarClassifierCascade*) struct_ptr; 2399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* TODO: parameters check */ 2401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_HAAR, attributes ); 2403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, ICV_HAAR_SIZE_NAME, CV_NODE_SEQ | CV_NODE_FLOW ); 2405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, NULL, cascade->orig_window_size.width ); 2406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, NULL, cascade->orig_window_size.height ); 2407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* size */ 2408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, ICV_HAAR_STAGES_NAME, CV_NODE_SEQ ); 2410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < cascade->count; ++i ) 2411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, NULL, CV_NODE_MAP ); 2413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "stage %d", i ); 2414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteComment( fs, buf, 1 ); 2415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, ICV_HAAR_TREES_NAME, CV_NODE_SEQ ); 2417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; ++j ) 2419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifier* tree = &cascade->stage_classifier[i].classifier[j]; 2421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, NULL, CV_NODE_SEQ ); 2423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "tree %d", j ); 2424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteComment( fs, buf, 1 ); 2425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( k = 0; k < tree->count; ++k ) 2427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarFeature* feature = &tree->haar_feature[k]; 2429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, NULL, CV_NODE_MAP ); 2431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( k ) 2432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "node %d", k ); 2434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 2436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sprintf( buf, "root node" ); 2438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteComment( fs, buf, 1 ); 2440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, ICV_HAAR_FEATURE_NAME, CV_NODE_MAP ); 2442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, ICV_HAAR_RECTS_NAME, CV_NODE_SEQ ); 2444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( l = 0; l < CV_HAAR_FEATURE_MAX && feature->rect[l].r.width != 0; ++l ) 2445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvStartWriteStruct( fs, NULL, CV_NODE_SEQ | CV_NODE_FLOW ); 2447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, NULL, feature->rect[l].r.x ); 2448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, NULL, feature->rect[l].r.y ); 2449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, NULL, feature->rect[l].r.width ); 2450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, NULL, feature->rect[l].r.height ); 2451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteReal( fs, NULL, feature->rect[l].weight ); 2452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* rect */ 2453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* rects */ 2455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, ICV_HAAR_TILTED_NAME, feature->tilted ); 2456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* feature */ 2457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteReal( fs, ICV_HAAR_THRESHOLD_NAME, tree->threshold[k]); 2459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( tree->left[k] > 0 ) 2461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, ICV_HAAR_LEFT_NODE_NAME, tree->left[k] ); 2463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 2465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteReal( fs, ICV_HAAR_LEFT_VAL_NAME, 2467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tree->alpha[-tree->left[k]] ); 2468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if( tree->right[k] > 0 ) 2471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, ICV_HAAR_RIGHT_NODE_NAME, tree->right[k] ); 2473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 2475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteReal( fs, ICV_HAAR_RIGHT_VAL_NAME, 2477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler tree->alpha[-tree->right[k]] ); 2478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* split */ 2481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* tree */ 2484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* trees */ 2487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteReal( fs, ICV_HAAR_STAGE_THRESHOLD_NAME, cascade->stage_classifier[i].threshold); 2489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, ICV_HAAR_PARENT_NAME, cascade->stage_classifier[i].parent ); 2490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvWriteInt( fs, ICV_HAAR_NEXT_NAME, cascade->stage_classifier[i].next ); 2491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* stage */ 2493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } /* for each stage */ 2494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* stages */ 2496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cvEndWriteStruct( fs ); /* root */ 2497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 2498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void* 2500793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslericvCloneHaarClassifier( const void* struct_ptr ) 2501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 2502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifierCascade* cascade = NULL; 2503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i, j, k, n; 2505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const CvHaarClassifierCascade* cascade_src = 2506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (const CvHaarClassifierCascade*) struct_ptr; 2507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler n = cascade_src->count; 2509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade = icvCreateHaarClassifierCascade(n); 2510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->orig_window_size = cascade_src->orig_window_size; 2511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( i = 0; i < n; ++i ) 2513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].parent = cascade_src->stage_classifier[i].parent; 2515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].next = cascade_src->stage_classifier[i].next; 2516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].child = cascade_src->stage_classifier[i].child; 2517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].threshold = cascade_src->stage_classifier[i].threshold; 2518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].count = 0; 2520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].classifier = 2521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (CvHaarClassifier*) cvAlloc( cascade_src->stage_classifier[i].count 2522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * sizeof( cascade->stage_classifier[i].classifier[0] ) ); 2523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].count = cascade_src->stage_classifier[i].count; 2525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; ++j ) 2527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cascade->stage_classifier[i].classifier[j].haar_feature = NULL; 2528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( j = 0; j < cascade->stage_classifier[i].count; ++j ) 2530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler const CvHaarClassifier* classifier_src = 2532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler &cascade_src->stage_classifier[i].classifier[j]; 2533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CvHaarClassifier* classifier = 2534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler &cascade->stage_classifier[i].classifier[j]; 2535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->count = classifier_src->count; 2537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature = (CvHaarFeature*) cvAlloc( 2538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->count * ( sizeof( *classifier->haar_feature ) + 2539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->threshold ) + 2540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->left ) + 2541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler sizeof( *classifier->right ) ) + 2542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (classifier->count + 1) * sizeof( *classifier->alpha ) ); 2543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->threshold = (float*) (classifier->haar_feature+classifier->count); 2544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->left = (int*) (classifier->threshold + classifier->count); 2545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->right = (int*) (classifier->left + classifier->count); 2546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->alpha = (float*) (classifier->right + classifier->count); 2547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for( k = 0; k < classifier->count; ++k ) 2548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 2549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->haar_feature[k] = classifier_src->haar_feature[k]; 2550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->threshold[k] = classifier_src->threshold[k]; 2551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->left[k] = classifier_src->left[k]; 2552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->right[k] = classifier_src->right[k]; 2553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->alpha[k] = classifier_src->alpha[k]; 2554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier->alpha[classifier->count] = 2556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler classifier_src->alpha[classifier->count]; 2557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 2559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return cascade; 2561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 2562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2564793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerCvType haar_type( CV_TYPE_NAME_HAAR, icvIsHaarClassifier, 2565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (CvReleaseFunc)cvReleaseHaarClassifierCascade, 2566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler icvReadHaarClassifier, icvWriteHaarClassifier, 2567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler icvCloneHaarClassifier ); 2568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 2569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* End of file. */ 2570