cvhaar.cpp revision 6acb9a7ea3d7564944e12cbc73a857b88c1301ee
16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M/////////////////////////////////////////////////////////////////////////////////////// 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// By downloading, copying, installing or using the software you agree to this license. 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// If you do not agree to this license, do not download, install, 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// copy or use the software. 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Intel License Agreement 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// For Open Source Computer Vision Library 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved. 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners. 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification, 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met: 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * Redistribution's of source code must retain the above copyright notice, 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// this list of conditions and the following disclaimer. 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * Redistribution's in binary form must reproduce the above copyright notice, 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// this list of conditions and the following disclaimer in the documentation 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and/or other materials provided with the distribution. 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * The name of Intel Corporation may not be used to endorse or promote products 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// derived from this software without specific prior written permission. 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed. 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct, 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services; 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability, 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage. 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/ 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Haar features calculation */ 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cv.h" 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdio.h> 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* these settings affect the quality of detection: change with care */ 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_ADJUST_FEATURES 1 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_ADJUST_WEIGHTS 0 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef int sumtype; 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef double sqsumtype; 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvHidHaarFeature 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sumtype *p0, *p1, *p2, *p3; 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float weight; 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rect[CV_HAAR_FEATURE_MAX]; 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvHidHaarFeature; 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvHidHaarTreeNode 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarFeature feature; 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float threshold; 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int left; 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int right; 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvHidHaarTreeNode; 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvHidHaarClassifier 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int count; 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //CvHaarFeature* orig_feature; 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarTreeNode* node; 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float* alpha; 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvHidHaarClassifier; 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvHidHaarStageClassifier 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int count; 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float threshold; 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifier* classifier; 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int two_rects; 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct CvHidHaarStageClassifier* next; 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct CvHidHaarStageClassifier* child; 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct CvHidHaarStageClassifier* parent; 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvHidHaarStageClassifier; 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct CvHidHaarClassifierCascade 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int count; 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int is_stump_based; 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int has_tilted_features; 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int is_tree; 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double inv_window_area; 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat sum, sqsum, tilted; 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarStageClassifier* stage_classifier; 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sqsumtype *pq0, *pq1, *pq2, *pq3; 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sumtype *p0, *p1, *p2, *p3; 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn void** ipp_stages; 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}; 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* IPP functions for object detection */ 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvHaarClassifierInitAlloc_32f_t icvHaarClassifierInitAlloc_32f_p = 0; 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvHaarClassifierFree_32f_t icvHaarClassifierFree_32f_p = 0; 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvApplyHaarClassifier_32f_C1R_t icvApplyHaarClassifier_32f_C1R_p = 0; 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvRectStdDev_32f_C1R_t icvRectStdDev_32f_C1R_p = 0; 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennconst int icv_object_win_border = 1; 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennconst float icv_stage_threshold_bias = 0.0001f; 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvHaarClassifierCascade* 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCreateHaarClassifierCascade( int stage_count ) 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifierCascade* cascade = 0; 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "icvCreateHaarClassifierCascade" ); 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int block_size = sizeof(*cascade) + stage_count*sizeof(*cascade->stage_classifier); 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( stage_count <= 0 ) 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsOutOfRange, "Number of stages should be positive" ); 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cascade = (CvHaarClassifierCascade*)cvAlloc( block_size )); 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( cascade, 0, block_size ); 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier = (CvHaarStageClassifier*)(cascade + 1); 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->flags = CV_HAAR_MAGIC_VAL; 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->count = stage_count; 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return cascade; 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReleaseHidHaarClassifierCascade( CvHidHaarClassifierCascade** _cascade ) 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( _cascade && *_cascade ) 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifierCascade* cascade = *_cascade; 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->ipp_stages && icvHaarClassifierFree_32f_p ) 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i; 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->ipp_stages[i] ) 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvHaarClassifierFree_32f_p( cascade->ipp_stages[i] ); 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &cascade->ipp_stages ); 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( _cascade ); 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* create more efficient internal representation of haar classifier cascade */ 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvHidHaarClassifierCascade* 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCreateHidHaarClassifierCascade( CvHaarClassifierCascade* cascade ) 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect* ipp_features = 0; 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float *ipp_weights = 0, *ipp_thresholds = 0, *ipp_val1 = 0, *ipp_val2 = 0; 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* ipp_counts = 0; 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifierCascade* out = 0; 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "icvCreateHidHaarClassifierCascade" ); 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, l; 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int datasize; 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int total_classifiers = 0; 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int total_nodes = 0; 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn char errorstr[100]; 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifier* haar_classifier_ptr; 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarTreeNode* haar_node_ptr; 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize orig_window_size; 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int has_tilted_features = 0; 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int max_count = 0; 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_HAAR_CLASSIFIER(cascade) ) 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->hid_cascade ) 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, "hid_cascade has been already created" ); 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !cascade->stage_classifier ) 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "" ); 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->count <= 0 ) 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsOutOfRange, "Negative number of cascade stages" ); 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn orig_window_size = cascade->orig_window_size; 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* check input structure correctness and calculate total memory size needed for 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn internal representation of the classifier cascade */ 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !stage_classifier->classifier || 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_classifier->count <= 0 ) 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( errorstr, "header of the stage classifier #%d is invalid " 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(has null pointers or non-positive classfier count)", i ); 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, errorstr ); 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_count = MAX( max_count, stage_classifier->count ); 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn total_classifiers += stage_classifier->count; 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < stage_classifier->count; j++ ) 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier = stage_classifier->classifier + j; 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn total_nodes += classifier->count; 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < classifier->count; l++ ) 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) 2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( classifier->haar_feature[l].rect[k].r.width ) 2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r = classifier->haar_feature[l].rect[k].r; 2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int tilted = classifier->haar_feature[l].tilted; 2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn has_tilted_features |= tilted != 0; 2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( r.width < 0 || r.height < 0 || r.y < 0 || 2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r.x + r.width > orig_window_size.width 2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || 2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (!tilted && 2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (r.x < 0 || r.y + r.height > orig_window_size.height)) 2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || 2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (tilted && (r.x - r.height < 0 || 2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r.y + r.width + r.height > orig_window_size.height))) 2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( errorstr, "rectangle #%d of the classifier #%d of " 2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "the stage classifier #%d is not inside " 2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "the reference (original) cascade window", k, j, i ); 2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, errorstr ); 2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // this is an upper boundary for the whole hidden cascade size 2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn datasize = sizeof(CvHidHaarClassifierCascade) + 2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(CvHidHaarStageClassifier)*cascade->count + 2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(CvHidHaarClassifier) * total_classifiers + 2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(CvHidHaarTreeNode) * total_nodes + 2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(void*)*(total_nodes + total_classifiers); 2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( out = (CvHidHaarClassifierCascade*)cvAlloc( datasize )); 2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( out, 0, sizeof(*out) ); 2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* init header */ 2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->count = cascade->count; 2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->stage_classifier = (CvHidHaarStageClassifier*)(out + 1); 2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn haar_classifier_ptr = (CvHidHaarClassifier*)(out->stage_classifier + cascade->count); 2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn haar_node_ptr = (CvHidHaarTreeNode*)(haar_classifier_ptr + total_classifiers); 2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->is_stump_based = 1; 2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->has_tilted_features = has_tilted_features; 2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->is_tree = 0; 2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* initialize internal representation */ 2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarStageClassifier* hid_stage_classifier = out->stage_classifier + i; 2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->count = stage_classifier->count; 2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->threshold = stage_classifier->threshold - icv_stage_threshold_bias; 2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->classifier = haar_classifier_ptr; 2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->two_rects = 1; 2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn haar_classifier_ptr += stage_classifier->count; 2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->parent = (stage_classifier->parent == -1) 2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ? NULL : out->stage_classifier + stage_classifier->parent; 2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->next = (stage_classifier->next == -1) 2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ? NULL : out->stage_classifier + stage_classifier->next; 2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->child = (stage_classifier->child == -1) 2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ? NULL : out->stage_classifier + stage_classifier->child; 2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->is_tree |= hid_stage_classifier->next != NULL; 3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < stage_classifier->count; j++ ) 3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier = stage_classifier->classifier + j; 3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifier* hid_classifier = hid_stage_classifier->classifier + j; 3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int node_count = classifier->count; 3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float* alpha_ptr = (float*)(haar_node_ptr + node_count); 3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_classifier->count = node_count; 3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_classifier->node = haar_node_ptr; 3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_classifier->alpha = alpha_ptr; 3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < node_count; l++ ) 3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarTreeNode* node = hid_classifier->node + l; 3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarFeature* feature = classifier->haar_feature + l; 3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( node, -1, sizeof(*node) ); 3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->threshold = classifier->threshold[l]; 3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->left = classifier->left[l]; 3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->right = classifier->right[l]; 3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fabs(feature->rect[2].weight) < DBL_EPSILON || 3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn feature->rect[2].r.width == 0 || 3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn feature->rect[2].r.height == 0 ) 3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( &(node->feature.rect[2]), 0, sizeof(node->feature.rect[2]) ); 3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->two_rects = 0; 3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memcpy( alpha_ptr, classifier->alpha, (node_count+1)*sizeof(alpha_ptr[0])); 3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn haar_node_ptr = 3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (CvHidHaarTreeNode*)cvAlignPtr(alpha_ptr+node_count+1, sizeof(void*)); 3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->is_stump_based &= node_count == 1; 3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int can_use_ipp = icvHaarClassifierInitAlloc_32f_p != 0 && 3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvHaarClassifierFree_32f_p != 0 && 3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvApplyHaarClassifier_32f_C1R_p != 0 && 3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvRectStdDev_32f_C1R_p != 0 && 3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn !out->has_tilted_features && !out->is_tree && out->is_stump_based; 3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( can_use_ipp ) 3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ipp_datasize = cascade->count*sizeof(out->ipp_stages[0]); 3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float ipp_weight_scale=(float)(1./((orig_window_size.width-icv_object_win_border*2)* 3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (orig_window_size.height-icv_object_win_border*2))); 3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( out->ipp_stages = (void**)cvAlloc( ipp_datasize )); 3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( out->ipp_stages, 0, ipp_datasize ); 3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_features = (CvRect*)cvAlloc( max_count*3*sizeof(ipp_features[0]) )); 3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_weights = (float*)cvAlloc( max_count*3*sizeof(ipp_weights[0]) )); 3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_thresholds = (float*)cvAlloc( max_count*sizeof(ipp_thresholds[0]) )); 3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_val1 = (float*)cvAlloc( max_count*sizeof(ipp_val1[0]) )); 3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_val2 = (float*)cvAlloc( max_count*sizeof(ipp_val2[0]) )); 3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_counts = (int*)cvAlloc( max_count*sizeof(ipp_counts[0]) )); 3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0, k = 0; j < stage_classifier->count; j++ ) 3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier = stage_classifier->classifier + j; 3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int rect_count = 2 + (classifier->haar_feature->rect[2].r.width != 0); 3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_thresholds[j] = classifier->threshold[0]; 3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_val1[j] = classifier->alpha[0]; 3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_val2[j] = classifier->alpha[1]; 3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_counts[j] = rect_count; 3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < rect_count; l++, k++ ) 3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_features[k] = classifier->haar_feature->rect[l].r; 3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //ipp_features[k].y = orig_window_size.height - ipp_features[k].y - ipp_features[k].height; 3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_weights[k] = classifier->haar_feature->rect[l].weight*ipp_weight_scale; 3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvHaarClassifierInitAlloc_32f_p( &out->ipp_stages[i], 3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_features, ipp_weights, ipp_thresholds, 3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_val1, ipp_val2, ipp_counts, stage_classifier->count ) < 0 ) 3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i < cascade->count ) 3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < i; j++ ) 3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvHaarClassifierFree_32f_p && out->ipp_stages[i] ) 3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvHaarClassifierFree_32f_p( out->ipp_stages[i] ); 3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &out->ipp_stages ); 3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->hid_cascade = out; 3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( (char*)haar_node_ptr - (char*)out <= datasize ); 4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cvGetErrStatus() < 0 ) 4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvReleaseHidHaarClassifierCascade( &out ); 4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_features ); 4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_weights ); 4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_thresholds ); 4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_val1 ); 4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_val2 ); 4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_counts ); 4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return out; 4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define sum_elem_ptr(sum,row,col) \ 4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((sumtype*)CV_MAT_ELEM_PTR_FAST((sum),(row),(col),sizeof(sumtype))) 4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define sqsum_elem_ptr(sqsum,row,col) \ 4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((sqsumtype*)CV_MAT_ELEM_PTR_FAST((sqsum),(row),(col),sizeof(sqsumtype))) 4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define calc_sum(rect,offset) \ 4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((rect).p0[offset] - (rect).p1[offset] - (rect).p2[offset] + (rect).p3[offset]) 4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void 4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* _cascade, 4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvArr* _sum, 4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvArr* _sqsum, 4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvArr* _tilted_sum, 4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double scale ) 4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME("cvSetImagesForHaarClassifierCascade"); 4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat sum_stub, *sum = (CvMat*)_sum; 4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat sqsum_stub, *sqsum = (CvMat*)_sqsum; 4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat tilted_stub, *tilted = (CvMat*)_tilted_sum; 4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifierCascade* cascade; 4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int coi0 = 0, coi1 = 0; 4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i; 4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect equ_rect; 4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double weight_scale; 4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) 4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); 4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( scale <= 0 ) 4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsOutOfRange, "Scale must be positive" ); 4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sum = cvGetMat( sum, &sum_stub, &coi0 )); 4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sqsum = cvGetMat( sqsum, &sqsum_stub, &coi1 )); 4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( coi0 || coi1 ) 4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_BadCOI, "COI is not supported" ); 4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_ARE_SIZES_EQ( sum, sqsum )) 4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedSizes, "All integral images must have the same size" ); 4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_TYPE(sqsum->type) != CV_64FC1 || 4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_MAT_TYPE(sum->type) != CV_32SC1 ) 4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, 4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" ); 4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !_cascade->hid_cascade ) 4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( icvCreateHidHaarClassifierCascade(_cascade) ); 4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade = _cascade->hid_cascade; 4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->has_tilted_features ) 4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( tilted = cvGetMat( tilted, &tilted_stub, &coi1 )); 4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_TYPE(tilted->type) != CV_32SC1 ) 4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, 4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" ); 4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( sum->step != tilted->step ) 4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedSizes, 4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Sum and tilted_sum must have the same stride (step, widthStep)" ); 4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_ARE_SIZES_EQ( sum, tilted )) 4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedSizes, "All integral images must have the same size" ); 4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->tilted = *tilted; 4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _cascade->scale = scale; 4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _cascade->real_window_size.width = cvRound( _cascade->orig_window_size.width * scale ); 4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _cascade->real_window_size.height = cvRound( _cascade->orig_window_size.height * scale ); 4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->sum = *sum; 4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->sqsum = *sqsum; 4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.x = equ_rect.y = cvRound(scale); 4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.width = cvRound((_cascade->orig_window_size.width-2)*scale); 4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.height = cvRound((_cascade->orig_window_size.height-2)*scale); 4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn weight_scale = 1./(equ_rect.width*equ_rect.height); 5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->inv_window_area = weight_scale; 5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->p0 = sum_elem_ptr(*sum, equ_rect.y, equ_rect.x); 5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->p1 = sum_elem_ptr(*sum, equ_rect.y, equ_rect.x + equ_rect.width ); 5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->p2 = sum_elem_ptr(*sum, equ_rect.y + equ_rect.height, equ_rect.x ); 5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->p3 = sum_elem_ptr(*sum, equ_rect.y + equ_rect.height, 5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.x + equ_rect.width ); 5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq0 = sqsum_elem_ptr(*sqsum, equ_rect.y, equ_rect.x); 5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq1 = sqsum_elem_ptr(*sqsum, equ_rect.y, equ_rect.x + equ_rect.width ); 5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq2 = sqsum_elem_ptr(*sqsum, equ_rect.y + equ_rect.height, equ_rect.x ); 5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq3 = sqsum_elem_ptr(*sqsum, equ_rect.y + equ_rect.height, 5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.x + equ_rect.width ); 5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* init pointers in haar features according to real window size and 5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn given image pointers */ 5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef _OPENMP 5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int max_threads = cvGetNumThreads(); 5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #pragma omp parallel for num_threads(max_threads) schedule(dynamic) 5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif // _OPENMP 5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < _cascade->count; i++ ) 5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j, k, l; 5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < cascade->stage_classifier[i].classifier[j].count; l++ ) 5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarFeature* feature = 5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &_cascade->stage_classifier[i].classifier[j].haar_feature[l]; 5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* CvHidHaarClassifier* classifier = 5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].classifier + j; */ 5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarFeature* hidfeature = 5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &cascade->stage_classifier[i].classifier[j].node[l].feature; 5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum0 = 0, area0 = 0; 5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r[3]; 5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int base_w = -1, base_h = -1; 5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int new_base_w = 0, new_base_h = 0; 5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int kx, ky; 5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int flagx = 0, flagy = 0; 5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int x0 = 0, y0 = 0; 5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int nr; 5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* align blocks */ 5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) 5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !hidfeature->rect[k].p0 ) 5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r[k] = feature->rect[k].r; 5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].width-1) ); 5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].x - r[0].x-1) ); 5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].height-1) ); 5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].y - r[0].y-1) ); 5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn nr = k; 5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_w += 1; 5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_h += 1; 5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn kx = r[0].width / base_w; 5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ky = r[0].height / base_h; 5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( kx <= 0 ) 5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flagx = 1; 5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn new_base_w = cvRound( r[0].width * scale ) / kx; 5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x0 = cvRound( r[0].x * scale ); 5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ky <= 0 ) 5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flagy = 1; 5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn new_base_h = cvRound( r[0].height * scale ) / ky; 5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y0 = cvRound( r[0].y * scale ); 5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < nr; k++ ) 5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect tr; 5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double correction_ratio; 5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flagx ) 5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.x = (r[k].x - r[0].x) * new_base_w / base_w + x0; 5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.width = r[k].width * new_base_w / base_w; 5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.x = cvRound( r[k].x * scale ); 5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.width = cvRound( r[k].width * scale ); 5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flagy ) 6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.y = (r[k].y - r[0].y) * new_base_h / base_h + y0; 6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.height = r[k].height * new_base_h / base_h; 6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.y = cvRound( r[k].y * scale ); 6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.height = cvRound( r[k].height * scale ); 6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_WEIGHTS 6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // RAINER START 6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const float orig_feature_size = (float)(feature->rect[k].r.width)*feature->rect[k].r.height; 6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const float orig_norm_size = (float)(_cascade->orig_window_size.width)*(_cascade->orig_window_size.height); 6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const float feature_size = float(tr.width*tr.height); 6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //const float normSize = float(equ_rect.width*equ_rect.height); 6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float target_ratio = orig_feature_size / orig_norm_size; 6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //float isRatio = featureSize / normSize; 6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //correctionRatio = targetRatio / isRatio / normSize; 6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn correction_ratio = target_ratio / feature_size; 6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // RAINER END 6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else 6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn correction_ratio = weight_scale * (!feature->tilted ? 1 : 0.5); 6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !feature->tilted ) 6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p0 = sum_elem_ptr(*sum, tr.y, tr.x); 6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p1 = sum_elem_ptr(*sum, tr.y, tr.x + tr.width); 6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p2 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x); 6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p3 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x + tr.width); 6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p2 = sum_elem_ptr(*tilted, tr.y + tr.width, tr.x + tr.width); 6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p3 = sum_elem_ptr(*tilted, tr.y + tr.width + tr.height, 6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.x + tr.width - tr.height); 6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p0 = sum_elem_ptr(*tilted, tr.y, tr.x); 6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p1 = sum_elem_ptr(*tilted, tr.y + tr.height, tr.x - tr.height); 6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].weight = (float)(feature->rect[k].weight * correction_ratio); 6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( k == 0 ) 6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn area0 = tr.width * tr.height; 6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum0 += hidfeature->rect[k].weight * tr.width * tr.height; 6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[0].weight = (float)(-sum0/area0); 6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* l */ 6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* j */ 6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_INLINE 6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renndouble icvEvalHidHaarClassifier( CvHidHaarClassifier* classifier, 6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double variance_norm_factor, 6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn size_t p_offset ) 6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = 0; 6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn do 6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarTreeNode* node = classifier->node + idx; 6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double t = node->threshold * variance_norm_factor; 6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( node->feature.rect[2].p0 ) 6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idx = sum < t ? node->left : node->right; 6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while( idx > 0 ); 6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return classifier->alpha[-idx]; 6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int 6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvRunHaarClassifierCascade( CvHaarClassifierCascade* _cascade, 6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint pt, int start_stage ) 6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result = -1; 6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME("cvRunHaarClassifierCascade"); 6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int p_offset, pq_offset; 6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j; 6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double mean, variance_norm_factor; 7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifierCascade* cascade; 7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) 7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid cascade pointer" ); 7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade = _cascade->hid_cascade; 7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !cascade ) 7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "Hidden cascade has not been created.\n" 7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Use cvSetImagesForHaarClassifierCascade" ); 7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.x < 0 || pt.y < 0 || 7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt.x + _cascade->real_window_size.width >= cascade->sum.width-2 || 7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt.y + _cascade->real_window_size.height >= cascade->sum.height-2 ) 7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x; 7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x; 7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mean = calc_sum(*cascade,p_offset)*cascade->inv_window_area; 7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor = cascade->pq0[pq_offset] - cascade->pq1[pq_offset] - 7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq2[pq_offset] + cascade->pq3[pq_offset]; 7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor = variance_norm_factor*cascade->inv_window_area - mean*mean; 7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( variance_norm_factor >= 0. ) 7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor = sqrt(variance_norm_factor); 7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor = 1.; 7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->is_tree ) 7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarStageClassifier* ptr; 7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( start_stage == 0 ); 7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = 1; 7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr = cascade->stage_classifier; 7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while( ptr ) 7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double stage_sum = 0; 7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < ptr->count; j++ ) 7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_sum += icvEvalHidHaarClassifier( ptr->classifier + j, 7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor, p_offset ); 7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( stage_sum >= ptr->threshold ) 7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr = ptr->child; 7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while( ptr && ptr->next == NULL ) ptr = ptr->parent; 7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ptr == NULL ) 7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = 0; 7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr = ptr->next; 7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( cascade->is_stump_based ) 7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = start_stage; i < cascade->count; i++ ) 7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double stage_sum = 0; 7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->stage_classifier[i].two_rects ) 7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarTreeNode* node = classifier->node; 7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum, t = node->threshold*variance_norm_factor, a, b; 7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a = classifier->alpha[0]; 7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn b = classifier->alpha[1]; 7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_sum += sum < t ? a : b; 7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHidHaarTreeNode* node = classifier->node; 7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum, t = node->threshold*variance_norm_factor, a, b; 7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( node->feature.rect[2].p0 ) 7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a = classifier->alpha[0]; 7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn b = classifier->alpha[1]; 7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_sum += sum < t ? a : b; 7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( stage_sum < cascade->stage_classifier[i].threshold ) 8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = -i; 8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = start_stage; i < cascade->count; i++ ) 8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double stage_sum = 0; 8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_sum += icvEvalHidHaarClassifier( 8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].classifier + j, 8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor, p_offset ); 8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( stage_sum < cascade->stage_classifier[i].threshold ) 8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = -i; 8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = 1; 8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result; 8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int is_equal( const void* _r1, const void* _r2, void* ) 8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvRect* r1 = (const CvRect*)_r1; 8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvRect* r2 = (const CvRect*)_r2; 8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int distance = cvRound(r1->width*0.2); 8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return r2->x <= r1->x + distance && 8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r2->x >= r1->x - distance && 8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r2->y <= r1->y + distance && 8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r2->y >= r1->y - distance && 8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r2->width <= cvRound( r1->width * 1.2 ) && 8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvRound( r2->width * 1.2 ) >= r1->width; 8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define VERY_ROUGH_SEARCH 0 8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq* 8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvHaarDetectObjects( const CvArr* _img, 8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifierCascade* cascade, 8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMemStorage* storage, double scale_factor, 8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int min_neighbors, int flags, CvSize min_size ) 8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int split_stage = 2; 8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat stub, *img = (CvMat*)_img; 8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat *temp = 0, *sum = 0, *tilted = 0, *sqsum = 0, *norm_img = 0, *sumcanny = 0, *img_small = 0; 8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* result_seq = 0; 8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMemStorage* temp_storage = 0; 8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp* comps = 0; 8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* seq_thread[CV_MAX_THREADS] = {0}; 8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, max_threads = 0; 8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvHaarDetectObjects" ); 8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq *seq = 0, *seq2 = 0, *idx_seq = 0, *big_seq = 0; 8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp result_comp = {{0,0,0,0},0}; 8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double factor; 8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int npass = 2, coi; 8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool do_canny_pruning = (flags & CV_HAAR_DO_CANNY_PRUNING) != 0; 8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool find_biggest_object = (flags & CV_HAAR_FIND_BIGGEST_OBJECT) != 0; 8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool rough_search = (flags & CV_HAAR_DO_ROUGH_SEARCH) != 0; 8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_HAAR_CLASSIFIER(cascade) ) 8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier cascade" ); 8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !storage ) 8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "Null storage pointer" ); 8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( img = cvGetMat( img, &stub, &coi )); 8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( coi ) 8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_BadCOI, "COI is not supported" ); 8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_DEPTH(img->type) != CV_8U ) 8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, "Only 8-bit images are supported" ); 8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object ) 8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flags &= ~CV_HAAR_SCALE_IMAGE; 8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( temp = cvCreateMat( img->rows, img->cols, CV_8UC1 )); 9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sum = cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 )); 9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sqsum = cvCreateMat( img->rows + 1, img->cols + 1, CV_64FC1 )); 9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( temp_storage = cvCreateChildMemStorage( storage )); 9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !cascade->hid_cascade ) 9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( icvCreateHidHaarClassifierCascade(cascade) ); 9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->hid_cascade->has_tilted_features ) 9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tilted = cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 ); 9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvRect), temp_storage ); 9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn seq2 = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), temp_storage ); 9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), storage ); 9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_threads = cvGetNumThreads(); 9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_threads > 1 ) 9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < max_threads; i++ ) 9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMemStorage* temp_storage_thread; 9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( temp_storage_thread = cvCreateMemStorage(0)); 9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( seq_thread[i] = cvCreateSeq( 0, sizeof(CvSeq), 9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(CvRect), temp_storage_thread )); 9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn seq_thread[0] = seq; 9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_CN(img->type) > 1 ) 9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvCvtColor( img, temp, CV_BGR2GRAY ); 9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn img = temp; 9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flags & CV_HAAR_FIND_BIGGEST_OBJECT ) 9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flags &= ~(CV_HAAR_SCALE_IMAGE|CV_HAAR_DO_CANNY_PRUNING); 9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flags & CV_HAAR_SCALE_IMAGE ) 9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize win_size0 = cascade->orig_window_size; 9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int use_ipp = cascade->hid_cascade->ipp_stages != 0 && 9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvApplyHaarClassifier_32f_C1R_p != 0; 9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( use_ipp ) 9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( norm_img = cvCreateMat( img->rows, img->cols, CV_32FC1 )); 9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( img_small = cvCreateMat( img->rows + 1, img->cols + 1, CV_8UC1 )); 9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( factor = 1; ; factor *= scale_factor ) 9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int strip_count, strip_size; 9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ystep = factor > 2. ? 1 : 2; 9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize win_size = { cvRound(win_size0.width*factor), 9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvRound(win_size0.height*factor) }; 9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize sz = { cvRound( img->cols/factor ), cvRound( img->rows/factor ) }; 9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize sz1 = { sz.width - win_size0.width, sz.height - win_size0.height }; 9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect equ_rect = { icv_object_win_border, icv_object_win_border, 9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn win_size0.width - icv_object_win_border*2, 9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn win_size0.height - icv_object_win_border*2 }; 9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat img1, sum1, sqsum1, norm1, tilted1, mask1; 9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat* _tilted = 0; 9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( sz1.width <= 0 || sz1.height <= 0 ) 9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( win_size.width < min_size.width || win_size.height < min_size.height ) 9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn continue; 9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn img1 = cvMat( sz.height, sz.width, CV_8UC1, img_small->data.ptr ); 9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, sum->data.ptr ); 9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sqsum1 = cvMat( sz.height+1, sz.width+1, CV_64FC1, sqsum->data.ptr ); 9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( tilted ) 9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tilted1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, tilted->data.ptr ); 9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _tilted = &tilted1; 9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn norm1 = cvMat( sz1.height, sz1.width, CV_32FC1, norm_img ? norm_img->data.ptr : 0 ); 9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask1 = cvMat( sz1.height, sz1.width, CV_8UC1, temp->data.ptr ); 9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvResize( img, &img1, CV_INTER_LINEAR ); 9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvIntegral( &img1, &sum1, &sqsum1, _tilted ); 9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_threads > 1 ) 9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn strip_count = MAX(MIN(sz1.height/ystep, max_threads*3), 1); 9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn strip_size = (sz1.height + strip_count - 1)/strip_count; 9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn strip_size = (strip_size / ystep)*ystep; 9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn strip_count = 1; 9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn strip_size = sz1.height; 9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !use_ipp ) 9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSetImagesForHaarClassifierCascade( cascade, &sum1, &sqsum1, 0, 1. ); 9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i <= sz.height; i++ ) 9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int* isum = (int*)(sum1.data.ptr + sum1.step*i); 9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float* fsum = (float*)isum; 9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int FLT_DELTA = -(1 << 24); 9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j; 10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j <= sz.width; j++ ) 10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fsum[j] = (float)(isum[j] + FLT_DELTA); 10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #ifdef _OPENMP 10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #pragma omp parallel for num_threads(max_threads) schedule(dynamic) 10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #endif 10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < strip_count; i++ ) 10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int thread_id = cvGetThreadNum(); 10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int positive = 0; 10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int y1 = i*strip_size, y2 = (i+1)*strip_size/* - ystep + 1*/; 10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize ssz; 10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int x, y, j; 10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i == strip_count - 1 || y2 > sz1.height ) 10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y2 = sz1.height; 10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ssz = cvSize(sz1.width, y2 - y1); 10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( use_ipp ) 10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvRectStdDev_32f_C1R_p( 10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (float*)(sum1.data.ptr + y1*sum1.step), sum1.step, 10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (double*)(sqsum1.data.ptr + y1*sqsum1.step), sqsum1.step, 10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (float*)(norm1.data.ptr + y1*norm1.step), norm1.step, ssz, equ_rect ); 10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn positive = (ssz.width/ystep)*((ssz.height + ystep-1)/ystep); 10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( mask1.data.ptr + y1*mask1.step, ystep == 1, mask1.height*mask1.step); 10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ystep > 1 ) 10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( y = y1, positive = 0; y < y2; y += ystep ) 10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( x = 0; x < ssz.width; x += ystep ) 10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask1.data.ptr[mask1.step*y + x] = (uchar)1; 10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->count; j++ ) 10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvApplyHaarClassifier_32f_C1R_p( 10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (float*)(sum1.data.ptr + y1*sum1.step), sum1.step, 10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (float*)(norm1.data.ptr + y1*norm1.step), norm1.step, 10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask1.data.ptr + y1*mask1.step, mask1.step, ssz, &positive, 10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->hid_cascade->stage_classifier[j].threshold, 10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->hid_cascade->ipp_stages[j]) < 0 ) 10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn positive = 0; 10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( positive <= 0 ) 10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( y = y1, positive = 0; y < y2; y += ystep ) 10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( x = 0; x < ssz.width; x += ystep ) 10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask1.data.ptr[mask1.step*y + x] = 10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvRunHaarClassifierCascade( cascade, cvPoint(x,y), 0 ) > 0; 10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn positive += mask1.data.ptr[mask1.step*y + x]; 10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( positive > 0 ) 10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( y = y1; y < y2; y += ystep ) 10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( x = 0; x < ssz.width; x += ystep ) 10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( mask1.data.ptr[mask1.step*y + x] != 0 ) 10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect obj_rect = { cvRound(x*factor), cvRound(y*factor), 10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn win_size.width, win_size.height }; 10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( seq_thread[thread_id], &obj_rect ); 10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // gather the results 10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_threads > 1 ) 10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < max_threads; i++ ) 10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* s = seq_thread[i]; 10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j, total = s->total; 10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqBlock* b = s->first; 10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < total; j += b->count, b = b->next ) 10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPushMulti( seq, b->data, b->count ); 10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n_factors = 0; 10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect scan_roi_rect = {0,0,0,0}; 10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool is_found = false, scan_roi = false; 10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvIntegral( img, sum, sqsum, tilted ); 10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( do_canny_pruning ) 10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sumcanny = cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 ); 10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvCanny( img, temp, 0, 50, 3 ); 11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvIntegral( temp, sumcanny ); 11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( (unsigned)split_stage >= (unsigned)cascade->count || 11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->hid_cascade->is_tree ) 11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn split_stage = cascade->count; 11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn npass = 1; 11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( n_factors = 0, factor = 1; 11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn factor*cascade->orig_window_size.width < img->cols - 10 && 11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn factor*cascade->orig_window_size.height < img->rows - 10; 11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n_factors++, factor *= scale_factor ) 11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ; 11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object ) 11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scale_factor = 1./scale_factor; 11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn factor *= scale_factor; 11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn big_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvRect), temp_storage ); 11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn factor = 1; 11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; n_factors-- > 0 && !is_found; factor *= scale_factor ) 11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const double ystep = MAX( 2, factor ); 11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize win_size = { cvRound( cascade->orig_window_size.width * factor ), 11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvRound( cascade->orig_window_size.height * factor )}; 11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect equ_rect = { 0, 0, 0, 0 }; 11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int *p0 = 0, *p1 = 0, *p2 = 0, *p3 = 0; 11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int *pq0 = 0, *pq1 = 0, *pq2 = 0, *pq3 = 0; 11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int pass, stage_offset = 0; 11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int start_x = 0, start_y = 0; 11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int end_x = cvRound((img->cols - win_size.width) / ystep); 11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int end_y = cvRound((img->rows - win_size.height) / ystep); 11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( win_size.width < min_size.width || win_size.height < min_size.height ) 11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object ) 11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn continue; 11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSetImagesForHaarClassifierCascade( cascade, sum, sqsum, tilted, factor ); 11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvZero( temp ); 11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( do_canny_pruning ) 11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.x = cvRound(win_size.width*0.15); 11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.y = cvRound(win_size.height*0.15); 11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.width = cvRound(win_size.width*0.7); 11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.height = cvRound(win_size.height*0.7); 11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p0 = (int*)(sumcanny->data.ptr + equ_rect.y*sumcanny->step) + equ_rect.x; 11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p1 = (int*)(sumcanny->data.ptr + equ_rect.y*sumcanny->step) 11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn + equ_rect.x + equ_rect.width; 11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p2 = (int*)(sumcanny->data.ptr + (equ_rect.y + equ_rect.height)*sumcanny->step) + equ_rect.x; 11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p3 = (int*)(sumcanny->data.ptr + (equ_rect.y + equ_rect.height)*sumcanny->step) 11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn + equ_rect.x + equ_rect.width; 11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq0 = (int*)(sum->data.ptr + equ_rect.y*sum->step) + equ_rect.x; 11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq1 = (int*)(sum->data.ptr + equ_rect.y*sum->step) 11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn + equ_rect.x + equ_rect.width; 11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq2 = (int*)(sum->data.ptr + (equ_rect.y + equ_rect.height)*sum->step) + equ_rect.x; 11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq3 = (int*)(sum->data.ptr + (equ_rect.y + equ_rect.height)*sum->step) 11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn + equ_rect.x + equ_rect.width; 11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( scan_roi ) 11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //adjust start_height and stop_height 11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn start_y = cvRound(scan_roi_rect.y / ystep); 11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn end_y = cvRound((scan_roi_rect.y + scan_roi_rect.height - win_size.height) / ystep); 11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn start_x = cvRound(scan_roi_rect.x / ystep); 11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn end_x = cvRound((scan_roi_rect.x + scan_roi_rect.width - win_size.width) / ystep); 11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->hid_cascade->count = split_stage; 11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( pass = 0; pass < npass; pass++ ) 11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #ifdef _OPENMP 11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #pragma omp parallel for num_threads(max_threads) schedule(dynamic) 11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #endif 11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( int _iy = start_y; _iy < end_y; _iy++ ) 11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int thread_id = cvGetThreadNum(); 11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int iy = cvRound(_iy*ystep); 11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int _ix, _xstep = 1; 11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* mask_row = temp->data.ptr + temp->step * iy; 11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( _ix = start_x; _ix < end_x; _ix += _xstep ) 11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ix = cvRound(_ix*ystep); // it really should be ystep 11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pass == 0 ) 11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result; 12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _xstep = 2; 12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( do_canny_pruning ) 12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int offset; 12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int s, sq; 12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn offset = iy*(sum->step/sizeof(p0[0])) + ix; 12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s = p0[offset] - p1[offset] - p2[offset] + p3[offset]; 12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sq = pq0[offset] - pq1[offset] - pq2[offset] + pq3[offset]; 12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( s < 100 || sq < 20 ) 12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn continue; 12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = cvRunHaarClassifierCascade( cascade, cvPoint(ix,iy), 0 ); 12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( result > 0 ) 12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pass < npass - 1 ) 12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask_row[ix] = 1; 12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect rect = cvRect(ix,iy,win_size.width,win_size.height); 12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( seq_thread[thread_id], &rect ); 12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( result < 0 ) 12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _xstep = 1; 12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( mask_row[ix] ) 12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result = cvRunHaarClassifierCascade( cascade, cvPoint(ix,iy), 12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_offset ); 12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( result > 0 ) 12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pass == npass - 1 ) 12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect rect = cvRect(ix,iy,win_size.width,win_size.height); 12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( seq_thread[thread_id], &rect ); 12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask_row[ix] = 0; 12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_offset = cascade->hid_cascade->count; 12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->hid_cascade->count = cascade->count; 12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // gather the results 12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_threads > 1 ) 12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < max_threads; i++ ) 12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* s = seq_thread[i]; 12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j, total = s->total; 12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqBlock* b = s->first; 12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < total; j += b->count, b = b->next ) 12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPushMulti( seq, b->data, b->count ); 12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object ) 12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* bseq = min_neighbors > 0 ? big_seq : seq; 12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( min_neighbors > 0 && !scan_roi ) 12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // group retrieved rectangles in order to filter out noise 12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ncomp = cvSeqPartition( seq, 0, &idx_seq, is_equal, 0 ); 12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( comps = (CvAvgComp*)cvAlloc( (ncomp+1)*sizeof(comps[0]))); 12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( comps, 0, (ncomp+1)*sizeof(comps[0])); 12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #if VERY_ROUGH_SEARCH 12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( rough_search ) 12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq->total; i++ ) 12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r1 = *(CvRect*)cvGetSeqElem( seq, i ); 12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = *(int*)cvGetSeqElem( idx_seq, i ); 12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( (unsigned)idx < (unsigned)ncomp ); 12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].neighbors++; 12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.x += r1.x; 12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.y += r1.y; 12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.width += r1.width; 12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.height += r1.height; 12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // calculate average bounding box 12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < ncomp; i++ ) 12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n = comps[i].neighbors; 12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( n >= min_neighbors ) 12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp comp; 12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = (comps[i].rect.x*2 + n)/(2*n); 12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = (comps[i].rect.y*2 + n)/(2*n); 12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = (comps[i].rect.width*2 + n)/(2*n); 12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = (comps[i].rect.height*2 + n)/(2*n); 12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.neighbors = n; 13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( bseq, &comp ); 13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #endif 13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0 ; i <= ncomp; i++ ) 13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[i].rect.x = comps[i].rect.y = INT_MAX; 13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // count number of neighbors 13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq->total; i++ ) 13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r1 = *(CvRect*)cvGetSeqElem( seq, i ); 13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = *(int*)cvGetSeqElem( idx_seq, i ); 13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( (unsigned)idx < (unsigned)ncomp ); 13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].neighbors++; 13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // rect.width and rect.height will store coordinate of right-bottom corner 13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.x = MIN(comps[idx].rect.x, r1.x); 13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.y = MIN(comps[idx].rect.y, r1.y); 13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.width = MAX(comps[idx].rect.width, r1.x+r1.width-1); 13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.height = MAX(comps[idx].rect.height, r1.y+r1.height-1); 13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // calculate enclosing box 13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < ncomp; i++ ) 13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n = comps[i].neighbors; 13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( n >= min_neighbors ) 13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp comp; 13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int t; 13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double min_scale = rough_search ? 0.6 : 0.4; 13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = comps[i].rect.x; 13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = comps[i].rect.y; 13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = comps[i].rect.width - comps[i].rect.x + 1; 13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = comps[i].rect.height - comps[i].rect.y + 1; 13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // update min_size 13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = cvRound( comp.rect.width*min_scale ); 13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_size.width = MAX( min_size.width, t ); 13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = cvRound( comp.rect.height*min_scale ); 13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_size.height = MAX( min_size.height, t ); 13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //expand the box by 20% because we could miss some neighbours 13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //see 'is_equal' function 13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #if 1 13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int offset = cvRound(comp.rect.width * 0.2); 13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int right = MIN( img->cols-1, comp.rect.x+comp.rect.width-1 + offset ); 13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int bottom = MIN( img->rows-1, comp.rect.y+comp.rect.height-1 + offset); 13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = MAX( comp.rect.x - offset, 0 ); 13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = MAX( comp.rect.y - offset, 0 ); 13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = right - comp.rect.x + 1; 13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = bottom - comp.rect.y + 1; 13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #endif 13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.neighbors = n; 13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( bseq, &comp ); 13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &comps ); 13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // extract the biggest rect 13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( bseq->total > 0 ) 13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int max_area = 0; 13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < bseq->total; i++ ) 13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp* comp = (CvAvgComp*)cvGetSeqElem( bseq, i ); 13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int area = comp->rect.width * comp->rect.height; 13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_area < area ) 13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_area = area; 13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result_comp.rect = comp->rect; 13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result_comp.neighbors = bseq == seq ? 1 : comp->neighbors; 13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //Prepare information for further scanning inside the biggest rectangle 13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #if VERY_ROUGH_SEARCH 13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // change scan ranges to roi in case of required 13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !rough_search && !scan_roi ) 13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scan_roi = true; 13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scan_roi_rect = result_comp.rect; 13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvClearSeq(bseq); 13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( rough_search ) 13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn is_found = true; 13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #else 13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !scan_roi ) 13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scan_roi = true; 14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scan_roi_rect = result_comp.rect; 14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvClearSeq(bseq); 14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #endif 14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( min_neighbors == 0 && !find_biggest_object ) 14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq->total; i++ ) 14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect* rect = (CvRect*)cvGetSeqElem( seq, i ); 14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp comp; 14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect = *rect; 14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.neighbors = 1; 14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( result_seq, &comp ); 14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( min_neighbors != 0 14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if VERY_ROUGH_SEARCH 14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn && (!find_biggest_object || !rough_search) 14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ) 14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // group retrieved rectangles in order to filter out noise 14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ncomp = cvSeqPartition( seq, 0, &idx_seq, is_equal, 0 ); 14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( comps = (CvAvgComp*)cvAlloc( (ncomp+1)*sizeof(comps[0]))); 14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( comps, 0, (ncomp+1)*sizeof(comps[0])); 14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // count number of neighbors 14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq->total; i++ ) 14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r1 = *(CvRect*)cvGetSeqElem( seq, i ); 14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = *(int*)cvGetSeqElem( idx_seq, i ); 14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( (unsigned)idx < (unsigned)ncomp ); 14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].neighbors++; 14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.x += r1.x; 14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.y += r1.y; 14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.width += r1.width; 14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.height += r1.height; 14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // calculate average bounding box 14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < ncomp; i++ ) 14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n = comps[i].neighbors; 14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( n >= min_neighbors ) 14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp comp; 14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = (comps[i].rect.x*2 + n)/(2*n); 14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = (comps[i].rect.y*2 + n)/(2*n); 14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = (comps[i].rect.width*2 + n)/(2*n); 14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = (comps[i].rect.height*2 + n)/(2*n); 14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.neighbors = comps[i].neighbors; 14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( seq2, &comp ); 14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !find_biggest_object ) 14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // filter out small face rectangles inside large face rectangles 14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq2->total; i++ ) 14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp r1 = *(CvAvgComp*)cvGetSeqElem( seq2, i ); 14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j, flag = 1; 14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < seq2->total; j++ ) 14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp r2 = *(CvAvgComp*)cvGetSeqElem( seq2, j ); 14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int distance = cvRound( r2.rect.width * 0.2 ); 14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i != j && 14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r1.rect.x >= r2.rect.x - distance && 14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r1.rect.y >= r2.rect.y - distance && 14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r1.rect.x + r1.rect.width <= r2.rect.x + r2.rect.width + distance && 14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r1.rect.y + r1.rect.height <= r2.rect.y + r2.rect.height + distance && 14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (r2.neighbors > MAX( 3, r1.neighbors ) || r1.neighbors < 3) ) 14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flag = 0; 14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flag ) 14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( result_seq, &r1 ); 14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int max_area = 0; 14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq2->total; i++ ) 14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp* comp = (CvAvgComp*)cvGetSeqElem( seq2, i ); 14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int area = comp->rect.width * comp->rect.height; 15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_area < area ) 15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_area = area; 15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result_comp = *comp; 15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object && result_comp.rect.width > 0 ) 15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( result_seq, &result_comp ); 15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_threads > 1 ) 15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < max_threads; i++ ) 15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( seq_thread[i] ) 15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMemStorage( &seq_thread[i]->storage ); 15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMemStorage( &temp_storage ); 15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &sum ); 15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &sqsum ); 15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &tilted ); 15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &temp ); 15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &sumcanny ); 15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &norm_img ); 15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &img_small ); 15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &comps ); 15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result_seq; 15326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 15336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvHaarClassifierCascade* 15366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvLoadCascadeCART( const char** input_cascade, int n, CvSize orig_window_size ) 15376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 15386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i; 15396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifierCascade* cascade = icvCreateHaarClassifierCascade(n); 15406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->orig_window_size = orig_window_size; 15416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < n; i++ ) 15436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j, count, l; 15456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float threshold = 0; 15466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const char* stage = input_cascade[i]; 15476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int dl = 0; 15486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* tree links */ 15506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int parent = -1; 15516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int next = -1; 15526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sscanf( stage, "%d%n", &count, &dl ); 15546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 15556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( count > 0 ); 15576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].count = count; 15586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].classifier = 15596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (CvHaarClassifier*)cvAlloc( count*sizeof(cascade->stage_classifier[i].classifier[0])); 15606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < count; j++ ) 15626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 15646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int k, rects = 0; 15656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn char str[100]; 15666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sscanf( stage, "%d%n", &classifier->count, &dl ); 15686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 15696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature = (CvHaarFeature*) cvAlloc( 15716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->count * ( sizeof( *classifier->haar_feature ) + 15726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->threshold ) + 15736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->left ) + 15746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->right ) ) + 15756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (classifier->count + 1) * sizeof( *classifier->alpha ) ); 15766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->threshold = (float*) (classifier->haar_feature+classifier->count); 15776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->left = (int*) (classifier->threshold + classifier->count); 15786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->right = (int*) (classifier->left + classifier->count); 15796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->alpha = (float*) (classifier->right + classifier->count); 15806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < classifier->count; l++ ) 15826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sscanf( stage, "%d%n", &rects, &dl ); 15846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 15856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( rects >= 2 && rects <= CV_HAAR_FEATURE_MAX ); 15876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < rects; k++ ) 15896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r; 15916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int band = 0; 15926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sscanf( stage, "%d%d%d%d%d%f%n", 15936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &r.x, &r.y, &r.width, &r.height, &band, 15946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &(classifier->haar_feature[l].rect[k].weight), &dl ); 15956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 15966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature[l].rect[k].r = r; 15976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sscanf( stage, "%s%n", str, &dl ); 15996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 16006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature[l].tilted = strncmp( str, "tilted", 6 ) == 0; 16026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = rects; k < CV_HAAR_FEATURE_MAX; k++ ) 16046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 16056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( classifier->haar_feature[l].rect + k, 0, 16066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(classifier->haar_feature[l].rect[k]) ); 16076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sscanf( stage, "%f%d%d%n", &(classifier->threshold[l]), 16106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &(classifier->left[l]), 16116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &(classifier->right[l]), &dl ); 16126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 16136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l <= classifier->count; l++ ) 16156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 16166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sscanf( stage, "%f%n", &(classifier->alpha[l]), &dl ); 16176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 16186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sscanf( stage, "%f%n", &threshold, &dl ); 16226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 16236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].threshold = threshold; 16256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* load tree links */ 16276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( sscanf( stage, "%d%d%n", &parent, &next, &dl ) != 2 ) 16286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 16296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn parent = i - 1; 16306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn next = -1; 16316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage += dl; 16336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].parent = parent; 16356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].next = next; 16366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].child = -1; 16376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( parent != -1 && cascade->stage_classifier[parent].child == -1 ) 16396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 16406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[parent].child = i; 16416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return cascade; 16456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 16466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifndef _MAX_PATH 16486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define _MAX_PATH 1024 16496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 16506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvHaarClassifierCascade* 16526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvLoadHaarClassifierCascade( const char* directory, CvSize orig_window_size ) 16536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 16546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const char** input_cascade = 0; 16556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifierCascade *cascade = 0; 16566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvLoadHaarClassifierCascade" ); 16586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 16606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, n; 16626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const char* slash; 16636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn char name[_MAX_PATH]; 16646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int size = 0; 16656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn char* ptr = 0; 16666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !directory ) 16686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "Null path is passed" ); 16696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n = (int)strlen(directory)-1; 16716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn slash = directory[n] == '\\' || directory[n] == '/' ? "" : "/"; 16726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* try to read the classifier from directory */ 16746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( n = 0; ; n++ ) 16756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 16766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( name, "%s%s%d/AdaBoostCARTHaarClassifier.txt", directory, slash, n ); 16776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn FILE* f = fopen( name, "rb" ); 16786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !f ) 16796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 16806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fseek( f, 0, SEEK_END ); 16816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn size += ftell( f ) + 1; 16826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fclose(f); 16836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( n == 0 && slash[0] ) 16866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 16876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cascade = (CvHaarClassifierCascade*)cvLoad( directory )); 16886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 16896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 16906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( n == 0 ) 16916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Invalid path" ); 16926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn size += (n+1)*sizeof(char*); 16946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( input_cascade = (const char**)cvAlloc( size )); 16956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr = (char*)(input_cascade + n + 1); 16966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 16976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < n; i++ ) 16986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 16996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( name, "%s/%d/AdaBoostCARTHaarClassifier.txt", directory, i ); 17006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn FILE* f = fopen( name, "rb" ); 17016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !f ) 17026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, "" ); 17036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fseek( f, 0, SEEK_END ); 17046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn size = ftell( f ); 17056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fseek( f, 0, SEEK_SET ); 17066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fread( ptr, 1, size, f ); 17076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fclose(f); 17086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn input_cascade[i] = ptr; 17096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr += size; 17106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *ptr++ = '\0'; 17116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 17126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn input_cascade[n] = 0; 17146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade = icvLoadCascadeCART( input_cascade, n, orig_window_size ); 17156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 17176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( input_cascade ) 17196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &input_cascade ); 17206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cvGetErrStatus() < 0 ) 17226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseHaarClassifierCascade( &cascade ); 17236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return cascade; 17256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 17266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void 17296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvReleaseHaarClassifierCascade( CvHaarClassifierCascade** _cascade ) 17306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 17316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( _cascade && *_cascade ) 17326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 17336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j; 17346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifierCascade* cascade = *_cascade; 17356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 17376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 17386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 17396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &cascade->stage_classifier[i].classifier[j].haar_feature ); 17406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &cascade->stage_classifier[i].classifier ); 17416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 17426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvReleaseHidHaarClassifierCascade( &cascade->hid_cascade ); 17436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( _cascade ); 17446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 17456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 17466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\ 17496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn* Persistence functions * 17506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/ 17516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* field names */ 17536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_SIZE_NAME "size" 17556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_STAGES_NAME "stages" 17566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_TREES_NAME "trees" 17576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_FEATURE_NAME "feature" 17586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_RECTS_NAME "rects" 17596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_TILTED_NAME "tilted" 17606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_THRESHOLD_NAME "threshold" 17616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_LEFT_NODE_NAME "left_node" 17626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_LEFT_VAL_NAME "left_val" 17636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_RIGHT_NODE_NAME "right_node" 17646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_RIGHT_VAL_NAME "right_val" 17656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_STAGE_THRESHOLD_NAME "stage_threshold" 17666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_PARENT_NAME "parent" 17676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define ICV_HAAR_NEXT_NAME "next" 17686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int 17706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvIsHaarClassifier( const void* struct_ptr ) 17716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 17726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_IS_HAAR_CLASSIFIER( struct_ptr ); 17736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 17746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void* 17766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvReadHaarClassifier( CvFileStorage* fs, CvFileNode* node ) 17776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 17786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifierCascade* cascade = NULL; 17796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvReadHaarClassifier" ); 17816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 17836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn char buf[256]; 17856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* seq_fn = NULL; /* sequence */ 17866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* fn = NULL; 17876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* stages_fn = NULL; 17886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader stages_reader; 17896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n; 17906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, l; 17916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int parent, next; 17926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( stages_fn = cvGetFileNodeByName( fs, node, ICV_HAAR_STAGES_NAME ) ); 17946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !stages_fn || !CV_NODE_IS_SEQ( stages_fn->tag) ) 17956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, "Invalid stages node" ); 17966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 17976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n = stages_fn->data.seq->total; 17986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cascade = icvCreateHaarClassifierCascade(n) ); 17996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* read size */ 18016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( seq_fn = cvGetFileNodeByName( fs, node, ICV_HAAR_SIZE_NAME ) ); 18026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !seq_fn || !CV_NODE_IS_SEQ( seq_fn->tag ) || seq_fn->data.seq->total != 2 ) 18036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, "size node is not a valid sequence." ); 18046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = (CvFileNode*) cvGetSeqElem( seq_fn->data.seq, 0 ) ); 18056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 ) 18066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, "Invalid size node: width must be positive integer" ); 18076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->orig_window_size.width = fn->data.i; 18086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = (CvFileNode*) cvGetSeqElem( seq_fn->data.seq, 1 ) ); 18096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 ) 18106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, "Invalid size node: height must be positive integer" ); 18116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->orig_window_size.height = fn->data.i; 18126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartReadSeq( stages_fn->data.seq, &stages_reader ) ); 18146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < n; ++i ) 18156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* stage_fn; 18176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* trees_fn; 18186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader trees_reader; 18196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_fn = (CvFileNode*) stages_reader.ptr; 18216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_MAP( stage_fn->tag ) ) 18226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Invalid stage %d", i ); 18246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 18256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 18266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( trees_fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_TREES_NAME ) ); 18286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !trees_fn || !CV_NODE_IS_SEQ( trees_fn->tag ) 18296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || trees_fn->data.seq->total <= 0 ) 18306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Trees node is not a valid sequence. (stage %d)", i ); 18326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 18336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 18346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cascade->stage_classifier[i].classifier = 18366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (CvHaarClassifier*) cvAlloc( trees_fn->data.seq->total 18376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * sizeof( cascade->stage_classifier[i].classifier[0] ) ) ); 18386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < trees_fn->data.seq->total; ++j ) 18396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].classifier[j].haar_feature = NULL; 18416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 18426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].count = trees_fn->data.seq->total; 18436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartReadSeq( trees_fn->data.seq, &trees_reader ) ); 18456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < trees_fn->data.seq->total; ++j ) 18466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* tree_fn; 18486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader tree_reader; 18496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier; 18506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int last_idx; 18516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier = &cascade->stage_classifier[i].classifier[j]; 18536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tree_fn = (CvFileNode*) trees_reader.ptr; 18546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_SEQ( tree_fn->tag ) || tree_fn->data.seq->total <= 0 ) 18556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Tree node is not a valid sequence." 18576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn " (stage %d, tree %d)", i, j ); 18586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 18596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 18606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->count = tree_fn->data.seq->total; 18626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( classifier->haar_feature = (CvHaarFeature*) cvAlloc( 18636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->count * ( sizeof( *classifier->haar_feature ) + 18646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->threshold ) + 18656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->left ) + 18666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->right ) ) + 18676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (classifier->count + 1) * sizeof( *classifier->alpha ) ) ); 18686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->threshold = (float*) (classifier->haar_feature+classifier->count); 18696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->left = (int*) (classifier->threshold + classifier->count); 18706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->right = (int*) (classifier->left + classifier->count); 18716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->alpha = (float*) (classifier->right + classifier->count); 18726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartReadSeq( tree_fn->data.seq, &tree_reader ) ); 18746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0, last_idx = 0; k < tree_fn->data.seq->total; ++k ) 18756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* node_fn; 18776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* feature_fn; 18786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* rects_fn; 18796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader rects_reader; 18806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 18816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node_fn = (CvFileNode*) tree_reader.ptr; 18826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_MAP( node_fn->tag ) ) 18836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Tree node %d is not a valid map. (stage %d, tree %d)", 18856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn k, i, j ); 18866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 18876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 18886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( feature_fn = cvGetFileNodeByName( fs, node_fn, 18896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ICV_HAAR_FEATURE_NAME ) ); 18906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !feature_fn || !CV_NODE_IS_MAP( feature_fn->tag ) ) 18916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 18926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Feature node is not a valid map. " 18936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 18946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 18956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 18966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( rects_fn = cvGetFileNodeByName( fs, feature_fn, 18976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ICV_HAAR_RECTS_NAME ) ); 18986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !rects_fn || !CV_NODE_IS_SEQ( rects_fn->tag ) 18996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || rects_fn->data.seq->total < 1 19006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || rects_fn->data.seq->total > CV_HAAR_FEATURE_MAX ) 19016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Rects node is not a valid sequence. " 19036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 19046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartReadSeq( rects_fn->data.seq, &rects_reader ) ); 19076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < rects_fn->data.seq->total; ++l ) 19086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvFileNode* rect_fn; 19106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r; 19116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 19126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rect_fn = (CvFileNode*) rects_reader.ptr; 19136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_SEQ( rect_fn->tag ) || rect_fn->data.seq->total != 5 ) 19146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Rect %d is not a valid sequence. " 19166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", l, i, j, k ); 19176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 19206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 0 ); 19216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i < 0 ) 19226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "x coordinate must be non-negative integer. " 19246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 19256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r.x = fn->data.i; 19286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 1 ); 19296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i < 0 ) 19306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "y coordinate must be non-negative integer. " 19326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 19336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r.y = fn->data.i; 19366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 2 ); 19376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 19386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || r.x + fn->data.i > cascade->orig_window_size.width ) 19396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "width must be positive integer and " 19416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(x + width) must not exceed window width. " 19426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 19436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r.width = fn->data.i; 19466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 3 ); 19476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= 0 19486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || r.y + fn->data.i > cascade->orig_window_size.height ) 19496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "height must be positive integer and " 19516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(y + height) must not exceed window height. " 19526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 19536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r.height = fn->data.i; 19566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn fn = CV_SEQ_ELEM( rect_fn->data.seq, CvFileNode, 4 ); 19576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_REAL( fn->tag ) ) 19586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "weight must be real number. " 19606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d, rect %d)", i, j, k, l ); 19616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 19646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature[k].rect[l].weight = (float) fn->data.f; 19656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature[k].rect[l].r = r; 19666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 19676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sizeof( *rect_fn ), rects_reader ); 19686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* for each rect */ 19696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = rects_fn->data.seq->total; l < CV_HAAR_FEATURE_MAX; ++l ) 19706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature[k].rect[l].weight = 0; 19726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature[k].rect[l].r = cvRect( 0, 0, 0, 0 ); 19736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 19756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, feature_fn, ICV_HAAR_TILTED_NAME)); 19766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !fn || !CV_NODE_IS_INT( fn->tag ) ) 19776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "tilted must be 0 or 1. " 19796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 19806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature[k].tilted = ( fn->data.i != 0 ); 19836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_THRESHOLD_NAME)); 19846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !fn || !CV_NODE_IS_REAL( fn->tag ) ) 19856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "threshold must be real number. " 19876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 19886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 19896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 19906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->threshold[k] = (float) fn->data.f; 19916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, node_fn, ICV_HAAR_LEFT_NODE_NAME)); 19926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fn ) 19936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= k 19956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || fn->data.i >= tree_fn->data.seq->total ) 19966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 19976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "left node must be valid node number. " 19986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 19996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* left node */ 20026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->left[k] = fn->data.i; 20036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 20056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, node_fn, 20076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ICV_HAAR_LEFT_VAL_NAME ) ); 20086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !fn ) 20096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "left node or left value must be specified. " 20116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 20126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_REAL( fn->tag ) ) 20156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "left value must be real number. " 20176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 20186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* left value */ 20216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( last_idx >= classifier->count + 1 ) 20226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Tree structure is broken: too many values. " 20246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 20256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->left[k] = -last_idx; 20286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->alpha[last_idx++] = (float) fn->data.f; 20296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, node_fn,ICV_HAAR_RIGHT_NODE_NAME)); 20316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fn ) 20326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_INT( fn->tag ) || fn->data.i <= k 20346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || fn->data.i >= tree_fn->data.seq->total ) 20356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "right node must be valid node number. " 20376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 20386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* right node */ 20416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->right[k] = fn->data.i; 20426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 20446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, node_fn, 20466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ICV_HAAR_RIGHT_VAL_NAME ) ); 20476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !fn ) 20486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "right node or right value must be specified. " 20506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 20516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_NODE_IS_REAL( fn->tag ) ) 20546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "right value must be real number. " 20566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 20576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* right value */ 20606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( last_idx >= classifier->count + 1 ) 20616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Tree structure is broken: too many values. " 20636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d, node %d)", i, j, k ); 20646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->right[k] = -last_idx; 20676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->alpha[last_idx++] = (float) fn->data.f; 20686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 20706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sizeof( *node_fn ), tree_reader ); 20716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* for each node */ 20726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( last_idx != classifier->count + 1 ) 20736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "Tree structure is broken: too few values. " 20756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(stage %d, tree %d)", i, j ); 20766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 20796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sizeof( *tree_fn ), trees_reader ); 20806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* for each tree */ 20816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 20826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_STAGE_THRESHOLD_NAME)); 20836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !fn || !CV_NODE_IS_REAL( fn->tag ) ) 20846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "stage threshold must be real number. (stage %d)", i ); 20866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 20886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].threshold = (float) fn->data.f; 20896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 20906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn parent = i - 1; 20916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn next = -1; 20926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 20936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_PARENT_NAME ) ); 20946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !fn || !CV_NODE_IS_INT( fn->tag ) 20956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || fn->data.i < -1 || fn->data.i >= cascade->count ) 20966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 20976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "parent must be integer number. (stage %d)", i ); 20986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 20996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 21006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn parent = fn->data.i; 21016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( fn = cvGetFileNodeByName( fs, stage_fn, ICV_HAAR_NEXT_NAME ) ); 21026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !fn || !CV_NODE_IS_INT( fn->tag ) 21036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || fn->data.i < -1 || fn->data.i >= cascade->count ) 21046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "next must be integer number. (stage %d)", i ); 21066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, buf ); 21076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 21086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn next = fn->data.i; 21096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].parent = parent; 21116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].next = next; 21126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].child = -1; 21136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( parent != -1 && cascade->stage_classifier[parent].child == -1 ) 21156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[parent].child = i; 21176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 21186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sizeof( *stage_fn ), stages_reader ); 21206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* for each stage */ 21216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 21236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cvGetErrStatus() < 0 ) 21256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseHaarClassifierCascade( &cascade ); 21276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade = NULL; 21286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 21296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return cascade; 21316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 21326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void 21346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvWriteHaarClassifier( CvFileStorage* fs, const char* name, const void* struct_ptr, 21356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAttrList attributes ) 21366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 21376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvWriteHaarClassifier" ); 21386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 21406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, l; 21426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn char buf[256]; 21436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvHaarClassifierCascade* cascade = (const CvHaarClassifierCascade*) struct_ptr; 21446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* TODO: parameters check */ 21466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, name, CV_NODE_MAP, CV_TYPE_NAME_HAAR, attributes ) ); 21486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, ICV_HAAR_SIZE_NAME, CV_NODE_SEQ | CV_NODE_FLOW ) ); 21506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, NULL, cascade->orig_window_size.width ) ); 21516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, NULL, cascade->orig_window_size.height ) ); 21526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* size */ 21536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, ICV_HAAR_STAGES_NAME, CV_NODE_SEQ ) ); 21556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; ++i ) 21566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, NULL, CV_NODE_MAP ) ); 21586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "stage %d", i ); 21596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteComment( fs, buf, 1 ) ); 21606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, ICV_HAAR_TREES_NAME, CV_NODE_SEQ ) ); 21626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; ++j ) 21646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* tree = &cascade->stage_classifier[i].classifier[j]; 21666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, NULL, CV_NODE_SEQ ) ); 21686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "tree %d", j ); 21696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteComment( fs, buf, 1 ) ); 21706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < tree->count; ++k ) 21726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarFeature* feature = &tree->haar_feature[k]; 21746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, NULL, CV_NODE_MAP ) ); 21766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( k ) 21776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "node %d", k ); 21796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 21806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 21816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( buf, "root node" ); 21836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 21846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteComment( fs, buf, 1 ) ); 21856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, ICV_HAAR_FEATURE_NAME, CV_NODE_MAP ) ); 21876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 21886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, ICV_HAAR_RECTS_NAME, CV_NODE_SEQ ) ); 21896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < CV_HAAR_FEATURE_MAX && feature->rect[l].r.width != 0; ++l ) 21906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 21916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartWriteStruct( fs, NULL, CV_NODE_SEQ | CV_NODE_FLOW ) ); 21926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, NULL, feature->rect[l].r.x ) ); 21936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, NULL, feature->rect[l].r.y ) ); 21946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, NULL, feature->rect[l].r.width ) ); 21956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, NULL, feature->rect[l].r.height ) ); 21966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteReal( fs, NULL, feature->rect[l].weight ) ); 21976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* rect */ 21986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 21996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* rects */ 22006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, ICV_HAAR_TILTED_NAME, feature->tilted ) ); 22016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* feature */ 22026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteReal( fs, ICV_HAAR_THRESHOLD_NAME, tree->threshold[k]) ); 22046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( tree->left[k] > 0 ) 22066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 22076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, ICV_HAAR_LEFT_NODE_NAME, tree->left[k] ) ); 22086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 22096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 22106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 22116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteReal( fs, ICV_HAAR_LEFT_VAL_NAME, 22126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tree->alpha[-tree->left[k]] ) ); 22136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 22146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( tree->right[k] > 0 ) 22166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 22176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, ICV_HAAR_RIGHT_NODE_NAME, tree->right[k] ) ); 22186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 22196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 22206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 22216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteReal( fs, ICV_HAAR_RIGHT_VAL_NAME, 22226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tree->alpha[-tree->right[k]] ) ); 22236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 22246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* split */ 22266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 22276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* tree */ 22296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 22306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* trees */ 22326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteReal( fs, ICV_HAAR_STAGE_THRESHOLD_NAME, 22346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].threshold) ); 22356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, ICV_HAAR_PARENT_NAME, 22376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].parent ) ); 22386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvWriteInt( fs, ICV_HAAR_NEXT_NAME, 22396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].next ) ); 22406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* stage */ 22426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* for each stage */ 22436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* stages */ 22456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvEndWriteStruct( fs ) ); /* root */ 22466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 22486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 22496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void* 22516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCloneHaarClassifier( const void* struct_ptr ) 22526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 22536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifierCascade* cascade = NULL; 22546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvCloneHaarClassifier" ); 22566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 22586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, n; 22606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvHaarClassifierCascade* cascade_src = 22616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (const CvHaarClassifierCascade*) struct_ptr; 22626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n = cascade_src->count; 22646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cascade = icvCreateHaarClassifierCascade(n) ); 22656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->orig_window_size = cascade_src->orig_window_size; 22666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < n; ++i ) 22686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 22696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].parent = cascade_src->stage_classifier[i].parent; 22706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].next = cascade_src->stage_classifier[i].next; 22716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].child = cascade_src->stage_classifier[i].child; 22726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].threshold = cascade_src->stage_classifier[i].threshold; 22736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].count = 0; 22756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cascade->stage_classifier[i].classifier = 22766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (CvHaarClassifier*) cvAlloc( cascade_src->stage_classifier[i].count 22776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * sizeof( cascade->stage_classifier[i].classifier[0] ) ) ); 22786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].count = cascade_src->stage_classifier[i].count; 22806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; ++j ) 22826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 22836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].classifier[j].haar_feature = NULL; 22846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 22856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; ++j ) 22876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 22886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvHaarClassifier* classifier_src = 22896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &cascade_src->stage_classifier[i].classifier[j]; 22906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier = 22916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &cascade->stage_classifier[i].classifier[j]; 22926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 22936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->count = classifier_src->count; 22946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( classifier->haar_feature = (CvHaarFeature*) cvAlloc( 22956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->count * ( sizeof( *classifier->haar_feature ) + 22966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->threshold ) + 22976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->left ) + 22986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof( *classifier->right ) ) + 22996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (classifier->count + 1) * sizeof( *classifier->alpha ) ) ); 23006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->threshold = (float*) (classifier->haar_feature+classifier->count); 23016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->left = (int*) (classifier->threshold + classifier->count); 23026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->right = (int*) (classifier->left + classifier->count); 23036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->alpha = (float*) (classifier->right + classifier->count); 23046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < classifier->count; ++k ) 23056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 23066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->haar_feature[k] = classifier_src->haar_feature[k]; 23076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->threshold[k] = classifier_src->threshold[k]; 23086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->left[k] = classifier_src->left[k]; 23096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->right[k] = classifier_src->right[k]; 23106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->alpha[k] = classifier_src->alpha[k]; 23116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 23126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier->alpha[classifier->count] = 23136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn classifier_src->alpha[classifier->count]; 23146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 23156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 23166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 23176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 23186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 23196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return cascade; 23206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 23216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 23226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 23236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvType haar_type( CV_TYPE_NAME_HAAR, icvIsHaarClassifier, 23246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (CvReleaseFunc)cvReleaseHaarClassifierCascade, 23256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvReadHaarClassifier, icvWriteHaarClassifier, 23266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvCloneHaarClassifier ); 23276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 23286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */ 2329