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 1 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef int sumtype; 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef double sqsumtype; 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct MyCvHidHaarFeature 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sumtype *p0, *p1, *p2, *p3; 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int weight; 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rect[CV_HAAR_FEATURE_MAX]; 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarFeature; 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct MyCvHidHaarTreeNode 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarFeature feature; 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int threshold; 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int left; 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int right; 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarTreeNode; 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct MyCvHidHaarClassifier 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int count; 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //CvHaarFeature* orig_feature; 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarTreeNode* node; 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float* alpha; 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifier; 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct MyCvHidHaarStageClassifier 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int count; 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float threshold; 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifier* classifier; 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int two_rects; 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct MyCvHidHaarStageClassifier* next; 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct MyCvHidHaarStageClassifier* child; 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct MyCvHidHaarStageClassifier* parent; 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarStageClassifier; 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct MyCvHidHaarClassifierCascade 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 MyCvHidHaarStageClassifier* 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 Rennconst int icv_object_win_border = 1; 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennconst float icv_stage_threshold_bias = 0.0001f; 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int myis_equal( const void* _r1, const void* _r2, void* ) 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvRect* r1 = (const CvRect*)_r1; 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvRect* r2 = (const CvRect*)_r2; 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int distance = cvRound(r1->width*0.2); 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return r2->x <= r1->x + distance && 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r2->x >= r1->x - distance && 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r2->y <= r1->y + distance && 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r2->y >= r1->y - distance && 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r2->width <= cvRound( r1->width * 1.2 ) && 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvRound( r2->width * 1.2 ) >= r1->width; 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennmyicvReleaseHidHaarClassifierCascade( MyCvHidHaarClassifierCascade** _cascade ) 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( _cascade && *_cascade ) 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /*CvHidHaarClassifierCascade* cascade = *_cascade; 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->ipp_stages && icvHaarClassifierFree_32f_p ) 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i; 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->ipp_stages[i] ) 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvHaarClassifierFree_32f_p( cascade->ipp_stages[i] ); 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &cascade->ipp_stages );*/ 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( _cascade ); 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* create more efficient internal representation of haar classifier cascade */ 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic MyCvHidHaarClassifierCascade* 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennmyicvCreateHidHaarClassifierCascade( CvHaarClassifierCascade* cascade ) 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect* ipp_features = 0; 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float *ipp_weights = 0, *ipp_thresholds = 0, *ipp_val1 = 0, *ipp_val2 = 0; 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* ipp_counts = 0; 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifierCascade* out = 0; 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "icvCreateHidHaarClassifierCascade" ); 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k, l; 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int datasize; 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int total_classifiers = 0; 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int total_nodes = 0; 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn char errorstr[100]; 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifier* haar_classifier_ptr; 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarTreeNode* haar_node_ptr; 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize orig_window_size; 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int has_tilted_features = 0; 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int max_count = 0; 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_HAAR_CLASSIFIER(cascade) ) 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->hid_cascade ) 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, "hid_cascade has been already created" ); 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !cascade->stage_classifier ) 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "" ); 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->count <= 0 ) 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsOutOfRange, "Negative number of cascade stages" ); 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn orig_window_size = cascade->orig_window_size; 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* check input structure correctness and calculate total memory size needed for 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn internal representation of the classifier cascade */ 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !stage_classifier->classifier || 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_classifier->count <= 0 ) 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( errorstr, "header of the stage classifier #%d is invalid " 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "(has null pointers or non-positive classfier count)", i ); 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsError, errorstr ); 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_count = MAX( max_count, stage_classifier->count ); 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn total_classifiers += stage_classifier->count; 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < stage_classifier->count; j++ ) 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier = stage_classifier->classifier + j; 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn total_nodes += classifier->count; 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < classifier->count; l++ ) 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( classifier->haar_feature[l].rect[k].r.width ) 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r = classifier->haar_feature[l].rect[k].r; 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int tilted = classifier->haar_feature[l].tilted; 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn has_tilted_features |= tilted != 0; 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( r.width < 0 || r.height < 0 || r.y < 0 || 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r.x + r.width > orig_window_size.width 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (!tilted && 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (r.x < 0 || r.y + r.height > orig_window_size.height)) 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn || 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (tilted && (r.x - r.height < 0 || 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r.y + r.width + r.height > orig_window_size.height))) 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sprintf( errorstr, "rectangle #%d of the classifier #%d of " 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "the stage classifier #%d is not inside " 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "the reference (original) cascade window", k, j, i ); 2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, errorstr ); 2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // this is an upper boundary for the whole hidden cascade size 2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn datasize = sizeof(MyCvHidHaarClassifierCascade) + 2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(MyCvHidHaarStageClassifier)*cascade->count + 2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(MyCvHidHaarClassifier) * total_classifiers + 2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(MyCvHidHaarTreeNode) * total_nodes + 2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(void*)*(total_nodes + total_classifiers); 2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( out = (MyCvHidHaarClassifierCascade*)cvAlloc( datasize )); 2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( out, 0, sizeof(*out) ); 2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* init header */ 2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->count = cascade->count; 2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->stage_classifier = (MyCvHidHaarStageClassifier*)(out + 1); 2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn haar_classifier_ptr = (MyCvHidHaarClassifier*)(out->stage_classifier + cascade->count); 2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn haar_node_ptr = (MyCvHidHaarTreeNode*)(haar_classifier_ptr + total_classifiers); 2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->is_stump_based = 1; 2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->has_tilted_features = has_tilted_features; 2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->is_tree = 0; 2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* initialize internal representation */ 2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarStageClassifier* hid_stage_classifier = out->stage_classifier + i; 2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->count = stage_classifier->count; 2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->threshold = stage_classifier->threshold - icv_stage_threshold_bias; 2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->classifier = haar_classifier_ptr; 2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->two_rects = 1; 2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn haar_classifier_ptr += stage_classifier->count; 2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->parent = (stage_classifier->parent == -1) 2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ? NULL : out->stage_classifier + stage_classifier->parent; 2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->next = (stage_classifier->next == -1) 2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ? NULL : out->stage_classifier + stage_classifier->next; 2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->child = (stage_classifier->child == -1) 2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ? NULL : out->stage_classifier + stage_classifier->child; 2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->is_tree |= hid_stage_classifier->next != NULL; 2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < stage_classifier->count; j++ ) 2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier = stage_classifier->classifier + j; 2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifier* hid_classifier = hid_stage_classifier->classifier + j; 2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int node_count = classifier->count; 2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float* alpha_ptr = (float*)(haar_node_ptr + node_count); 2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_classifier->count = node_count; 2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_classifier->node = haar_node_ptr; 2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_classifier->alpha = alpha_ptr; 2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < node_count; l++ ) 2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarTreeNode* node = hid_classifier->node + l; 2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarFeature* feature = classifier->haar_feature + l; 2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( node, -1, sizeof(*node) ); 3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->threshold = (int)((classifier->threshold[l]) * 65536.0); 3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->left = classifier->left[l]; 3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->right = classifier->right[l]; 3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fabs(feature->rect[2].weight) < DBL_EPSILON || 3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn feature->rect[2].r.width == 0 || 3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn feature->rect[2].r.height == 0 ) 3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( &(node->feature.rect[2]), 0, sizeof(node->feature.rect[2]) ); 3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hid_stage_classifier->two_rects = 0; 3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memcpy( alpha_ptr, classifier->alpha, (node_count+1)*sizeof(alpha_ptr[0])); 3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn haar_node_ptr = 3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (MyCvHidHaarTreeNode*)cvAlignPtr(alpha_ptr+node_count+1, sizeof(void*)); 3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn out->is_stump_based &= node_count == 1; 3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /*{ 3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int can_use_ipp = icvHaarClassifierInitAlloc_32f_p != 0 && 3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvHaarClassifierFree_32f_p != 0 && 3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvApplyHaarClassifier_32f_C1R_p != 0 && 3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvRectStdDev_32f_C1R_p != 0 && 3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn !out->has_tilted_features && !out->is_tree && out->is_stump_based; 3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( can_use_ipp ) 3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ipp_datasize = cascade->count*sizeof(out->ipp_stages[0]); 3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float ipp_weight_scale=(float)(1./((orig_window_size.width-icv_object_win_border*2)* 3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (orig_window_size.height-icv_object_win_border*2))); 3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( out->ipp_stages = (void**)cvAlloc( ipp_datasize )); 3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( out->ipp_stages, 0, ipp_datasize ); 3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_features = (CvRect*)cvAlloc( max_count*3*sizeof(ipp_features[0]) )); 3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_weights = (float*)cvAlloc( max_count*3*sizeof(ipp_weights[0]) )); 3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_thresholds = (float*)cvAlloc( max_count*sizeof(ipp_thresholds[0]) )); 3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_val1 = (float*)cvAlloc( max_count*sizeof(ipp_val1[0]) )); 3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_val2 = (float*)cvAlloc( max_count*sizeof(ipp_val2[0]) )); 3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ipp_counts = (int*)cvAlloc( max_count*sizeof(ipp_counts[0]) )); 3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < cascade->count; i++ ) 3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i; 3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0, k = 0; j < stage_classifier->count; j++ ) 3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifier* classifier = stage_classifier->classifier + j; 3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int rect_count = 2 + (classifier->haar_feature->rect[2].r.width != 0); 3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_thresholds[j] = classifier->threshold[0]; 3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_val1[j] = classifier->alpha[0]; 3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_val2[j] = classifier->alpha[1]; 3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_counts[j] = rect_count; 3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < rect_count; l++, k++ ) 3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_features[k] = classifier->haar_feature->rect[l].r; 3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //ipp_features[k].y = orig_window_size.height - ipp_features[k].y - ipp_features[k].height; 3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_weights[k] = classifier->haar_feature->rect[l].weight*ipp_weight_scale; 3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvHaarClassifierInitAlloc_32f_p( &out->ipp_stages[i], 3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_features, ipp_weights, ipp_thresholds, 3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ipp_val1, ipp_val2, ipp_counts, stage_classifier->count ) < 0 ) 3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i < cascade->count ) 3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < i; j++ ) 3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvHaarClassifierFree_32f_p && out->ipp_stages[i] ) 3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvHaarClassifierFree_32f_p( out->ipp_stages[i] ); 3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &out->ipp_stages ); 3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn }*/ 3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->hid_cascade = (CvHidHaarClassifierCascade*)out; 3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( (char*)haar_node_ptr - (char*)out <= datasize ); 3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cvGetErrStatus() < 0 ) 3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn myicvReleaseHidHaarClassifierCascade( &out ); 3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_features ); 3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_weights ); 3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_thresholds ); 3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_val1 ); 3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_val2 ); 3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &ipp_counts ); 3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return out; 3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define calc_sum(rect,offset) \ 3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn((rect).p0[offset] - (rect).p1[offset] - (rect).p2[offset] + (rect).p3[offset]) 4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_INLINE 4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renndouble myicvEvalHidHaarClassifier( MyCvHidHaarClassifier* classifier, 4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double variance_norm_factor, 4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn size_t p_offset ) 4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = 0; 4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn do 4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarTreeNode* node = classifier->node + idx; 4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double t = node->threshold * variance_norm_factor; 4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( node->feature.rect[2].p0 ) 4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idx = sum < t ? node->left : node->right; 4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while( idx > 0 ); 4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return classifier->alpha[-idx]; 4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*********************** Special integer sqrt **************************/ 4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennint 4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennisqrt(int x) 4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* 4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Logically, these are unsigned. We need the sign bit to test 4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * whether (op - res - one) underflowed. 4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn register int op, res, one; 4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn op = x; 4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn res = 0; 4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* "one" starts at the highest power of four <= than the argument. */ 4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn one = 1 << 30; /* second-to-top bit set */ 4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while (one > op) one >>= 2; 4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while (one != 0) { 4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (op >= res + one) { 4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn op = op - (res + one); 4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn res = res + 2 * one; 4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn res /= 2; 4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn one /= 4; 4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return(res); 4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define NEXT(n, i) (((n) + (i)/(n)) >> 1) 4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennunsigned int isqrt1(int number) { 4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn unsigned int n = 1; 460a8b25eaceacd9aa58022d5da72f92fcc98eb6c1bDan Austin unsigned int n1 = NEXT(n, (unsigned int)number); 4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 462a8b25eaceacd9aa58022d5da72f92fcc98eb6c1bDan Austin while(abs((int)(n1 - n)) > 1) { 4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n = n1; 4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n1 = NEXT(n, number); 4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while((n1*n1) > number) { 4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n1 -= 1; 4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return n1; 4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/***********************************************************************/ 4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int 4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennmycvRunHaarClassifierCascade( CvHaarClassifierCascade* _cascade, 4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint pt, int start_stage ) 4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result = -1; 4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME("mycvRunHaarClassifierCascade"); 4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int p_offset, pq_offset; 4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int pq0, pq1, pq2, pq3; 4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j; 4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double mean; 4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int variance_norm_factor; 4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifierCascade* cascade; 4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) 4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid cascade pointer" ); 4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade = (MyCvHidHaarClassifierCascade*)_cascade->hid_cascade; 4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !cascade ) 4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "Hidden cascade has not been created.\n" 4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Use cvSetImagesForHaarClassifierCascade" ); 4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.x < 0 || pt.y < 0 || 4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt.x + _cascade->real_window_size.width >= cascade->sum.width-2 || 4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt.y + _cascade->real_window_size.height >= cascade->sum.height-2 ) 5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_offset = pt.y * (cascade->sum.step/sizeof(sumtype)) + pt.x; 5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq_offset = pt.y * (cascade->sqsum.step/sizeof(sqsumtype)) + pt.x; 5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mean = calc_sum(*cascade,p_offset) * cascade->inv_window_area; 5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq0 = cascade->pq0[pq_offset]; 5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq1 = cascade->pq1[pq_offset]; 5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq2 = cascade->pq2[pq_offset]; 5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pq3 = cascade->pq3[pq_offset]; 5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor = pq0 - pq1 - pq2 + pq3; 5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor = variance_norm_factor * cascade->inv_window_area - mean * mean; 5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( variance_norm_factor >= 0. ) 5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor = sqrt(variance_norm_factor); 5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn variance_norm_factor = 1.; 5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( cascade->is_tree ) 5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// MyCvHidHaarStageClassifier* ptr; 5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// assert( start_stage == 0 ); 5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// result = 1; 5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ptr = cascade->stage_classifier; 5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// while( ptr ) 5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// double stage_sum = 0; 5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( j = 0; j < ptr->count; j++ ) 5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// stage_sum += myicvEvalHidHaarClassifier( ptr->classifier + j, 5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// variance_norm_factor, p_offset ); 5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( stage_sum >= ptr->threshold ) 5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ptr = ptr->child; 5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// else 5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// while( ptr && ptr->next == NULL ) ptr = ptr->parent; 5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( ptr == NULL ) 5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// result = 0; 5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// EXIT; 5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ptr = ptr->next; 5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// else if( cascade->is_stump_based ) 5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = start_stage; i < cascade->count; i++ ) 5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double stage_sum = 0; 5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->stage_classifier[i].two_rects ) 5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarTreeNode* node = classifier->node; 5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int t = node->threshold * variance_norm_factor; 5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_sum += classifier->alpha[sum >= t]; 5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifier* classifier = cascade->stage_classifier[i].classifier + j; 5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarTreeNode* node = classifier->node; 5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int t = node->threshold * variance_norm_factor; 5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int sum = calc_sum(node->feature.rect[0],p_offset) * node->feature.rect[0].weight; 5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[1],p_offset) * node->feature.rect[1].weight; 5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( node->feature.rect[2].p0 ) 5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum += calc_sum(node->feature.rect[2],p_offset) * node->feature.rect[2].weight; 5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_sum += classifier->alpha[sum >= t]; 5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( stage_sum < cascade->stage_classifier[i].threshold ) 5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = -i; 5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// else 5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( i = start_stage; i < cascade->count; i++ ) 5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// double stage_sum = 0; 5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// stage_sum += myicvEvalHidHaarClassifier( 6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cascade->stage_classifier[i].classifier + j, 6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// variance_norm_factor, p_offset ); 6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( stage_sum < cascade->stage_classifier[i].threshold ) 6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// result = -i; 6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// EXIT; 6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = 1; 6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result; 6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define sum_elem_ptr(sum,row,col) \ 6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn((sumtype*)CV_MAT_ELEM_PTR_FAST((sum),(row),(col),sizeof(sumtype))) 6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define sqsum_elem_ptr(sqsum,row,col) \ 6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn((sqsumtype*)CV_MAT_ELEM_PTR_FAST((sqsum),(row),(col),sizeof(sqsumtype))) 6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void 6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennmycvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* _cascade, 6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvArr* _sum, 6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvArr* _sqsum, 6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const CvArr* _tilted_sum, 6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double scale ) 6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME("cvSetImagesForHaarClassifierCascade"); 6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat sum_stub, *sum = (CvMat*)_sum; 6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat sqsum_stub, *sqsum = (CvMat*)_sqsum; 6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat tilted_stub, *tilted = (CvMat*)_tilted_sum; 6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarClassifierCascade* cascade; 6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int coi0 = 0, coi1 = 0; 6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i; 6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect equ_rect; 6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double weight_scale; 6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_HAAR_CLASSIFIER(_cascade) ) 6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( !_cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" ); 6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( scale <= 0 ) 6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsOutOfRange, "Scale must be positive" ); 6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sum = cvGetMat( sum, &sum_stub, &coi0 )); 6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sqsum = cvGetMat( sqsum, &sqsum_stub, &coi1 )); 6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( coi0 || coi1 ) 6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_BadCOI, "COI is not supported" ); 6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_ARE_SIZES_EQ( sum, sqsum )) 6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedSizes, "All integral images must have the same size" ); 6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_TYPE(sqsum->type) != CV_64FC1 || 6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_MAT_TYPE(sum->type) != CV_32SC1 ) 6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, 6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" ); 6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !_cascade->hid_cascade ) 6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( myicvCreateHidHaarClassifierCascade(_cascade) ); 6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade = (MyCvHidHaarClassifierCascade*)_cascade->hid_cascade; 6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cascade->has_tilted_features ) 6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( tilted = cvGetMat( tilted, &tilted_stub, &coi1 )); 6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_TYPE(tilted->type) != CV_32SC1 ) 6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, 6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Only (32s, 64f, 32s) combination of (sum,sqsum,tilted_sum) formats is allowed" ); 6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( sum->step != tilted->step ) 6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedSizes, 6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Sum and tilted_sum must have the same stride (step, widthStep)" ); 6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_ARE_SIZES_EQ( sum, tilted )) 6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedSizes, "All integral images must have the same size" ); 6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->tilted = *tilted; 6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _cascade->scale = scale; 6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _cascade->real_window_size.width = cvRound( _cascade->orig_window_size.width * scale ); 6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _cascade->real_window_size.height = cvRound( _cascade->orig_window_size.height * scale ); 6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->sum = *sum; 6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->sqsum = *sqsum; 6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.x = equ_rect.y = cvRound(scale); 6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.width = cvRound((_cascade->orig_window_size.width-2)*scale); 6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.height = cvRound((_cascade->orig_window_size.height-2)*scale); 6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn weight_scale = 1./(equ_rect.width*equ_rect.height); 6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->inv_window_area = weight_scale; 7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->p0 = sum_elem_ptr(*sum, equ_rect.y, equ_rect.x); 7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->p1 = sum_elem_ptr(*sum, equ_rect.y, equ_rect.x + equ_rect.width ); 7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->p2 = sum_elem_ptr(*sum, equ_rect.y + equ_rect.height, equ_rect.x ); 7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->p3 = sum_elem_ptr(*sum, equ_rect.y + equ_rect.height, 7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.x + equ_rect.width ); 7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq0 = sqsum_elem_ptr(*sqsum, equ_rect.y, equ_rect.x); 7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq1 = sqsum_elem_ptr(*sqsum, equ_rect.y, equ_rect.x + equ_rect.width ); 7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq2 = sqsum_elem_ptr(*sqsum, equ_rect.y + equ_rect.height, equ_rect.x ); 7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->pq3 = sqsum_elem_ptr(*sqsum, equ_rect.y + equ_rect.height, 7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn equ_rect.x + equ_rect.width ); 7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* init pointers in haar features according to real window size and 7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn given image pointers */ 7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef _OPENMP 7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int max_threads = cvGetNumThreads(); 7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#pragma omp parallel for num_threads(max_threads) schedule(dynamic) 7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif // _OPENMP 7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < _cascade->count; i++ ) 7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j, k, l; 7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < cascade->stage_classifier[i].count; j++ ) 7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( l = 0; l < cascade->stage_classifier[i].classifier[j].count; l++ ) 7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarFeature* feature = 7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &_cascade->stage_classifier[i].classifier[j].haar_feature[l]; 7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* CvHidHaarClassifier* classifier = 7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cascade->stage_classifier[i].classifier + j; */ 7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn MyCvHidHaarFeature* hidfeature = 7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn &cascade->stage_classifier[i].classifier[j].node[l].feature; 7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sum0 = 0, area0 = 0; 7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r[3]; 7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int base_w = -1, base_h = -1; 7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int new_base_w = 0, new_base_h = 0; 7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int kx, ky; 7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int flagx = 0, flagy = 0; 7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int x0 = 0, y0 = 0; 7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int nr; 7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* align blocks */ 7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ ) 7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !hidfeature->rect[k].p0 ) 7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r[k] = feature->rect[k].r; 7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].width-1) ); 7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_w = (int)CV_IMIN( (unsigned)base_w, (unsigned)(r[k].x - r[0].x-1) ); 7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].height-1) ); 7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_h = (int)CV_IMIN( (unsigned)base_h, (unsigned)(r[k].y - r[0].y-1) ); 7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn nr = k; 7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_w += 1; 7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn base_h += 1; 7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn kx = r[0].width / base_w; 7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ky = r[0].height / base_h; 7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( kx <= 0 ) 7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flagx = 1; 7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn new_base_w = cvRound( r[0].width * scale ) / kx; 7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x0 = cvRound( r[0].x * scale ); 7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ky <= 0 ) 7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flagy = 1; 7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn new_base_h = cvRound( r[0].height * scale ) / ky; 7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y0 = cvRound( r[0].y * scale ); 7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float tmpweight[3] = {0}; 7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < nr; k++ ) 7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect tr; 7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double correction_ratio; 7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flagx ) 7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.x = (r[k].x - r[0].x) * new_base_w / base_w + x0; 7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.width = r[k].width * new_base_w / base_w; 7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.x = cvRound( r[k].x * scale ); 7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.width = cvRound( r[k].width * scale ); 7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_FEATURES 8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flagy ) 8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.y = (r[k].y - r[0].y) * new_base_h / base_h + y0; 8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.height = r[k].height * new_base_h / base_h; 8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.y = cvRound( r[k].y * scale ); 8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.height = cvRound( r[k].height * scale ); 8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if CV_ADJUST_WEIGHTS 8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // RAINER START 8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const float orig_feature_size = (float)(feature->rect[k].r.width)*feature->rect[k].r.height; 8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const float orig_norm_size = (float)(_cascade->orig_window_size.width)*(_cascade->orig_window_size.height); 8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const float feature_size = float(tr.width*tr.height); 8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //const float normSize = float(equ_rect.width*equ_rect.height); 8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float target_ratio = orig_feature_size / orig_norm_size; 8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //float isRatio = featureSize / normSize; 8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //correctionRatio = targetRatio / isRatio / normSize; 8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn correction_ratio = target_ratio / feature_size; 8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // RAINER END 8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else 8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn correction_ratio = weight_scale * (!feature->tilted ? 1 : 0.5); 8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !feature->tilted ) 8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p0 = sum_elem_ptr(*sum, tr.y, tr.x); 8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p1 = sum_elem_ptr(*sum, tr.y, tr.x + tr.width); 8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p2 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x); 8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p3 = sum_elem_ptr(*sum, tr.y + tr.height, tr.x + tr.width); 8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p2 = sum_elem_ptr(*tilted, tr.y + tr.width, tr.x + tr.width); 8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p3 = sum_elem_ptr(*tilted, tr.y + tr.width + tr.height, 8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tr.x + tr.width - tr.height); 8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p0 = sum_elem_ptr(*tilted, tr.y, tr.x); 8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn hidfeature->rect[k].p1 = sum_elem_ptr(*tilted, tr.y + tr.height, tr.x - tr.height); 8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// hidfeature->rect[k].weight = (float)(feature->rect[k].weight * correction_ratio); 8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tmpweight[k] = (float)(feature->rect[k].weight * correction_ratio); 8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( k == 0 ) 8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn area0 = tr.width * tr.height; 8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// sum0 += hidfeature->rect[k].weight * tr.width * tr.height; 8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sum0 += tmpweight[k] * tr.width * tr.height; 8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tmpweight[0] = (float)(-sum0/area0); 8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(int ii = 0; ii < nr; hidfeature->rect[ii].weight = (int)(tmpweight[ii] * 65536.0), ii++); 8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* l */ 8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } /* j */ 8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvMat *temp = 0, *sum = 0, *sqsum = 0; 8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renndouble tickFreqTimes1000 = ((double)cvGetTickFrequency()*1000.); 8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvSeq* 8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennmycvHaarDetectObjects( const CvArr* _img, 8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvHaarClassifierCascade* cascade, 8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMemStorage* storage, double scale_factor, 8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int min_neighbors, int flags, CvSize min_size ) 8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int split_stage = 2; 8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat stub, *img = (CvMat*)_img; 8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat *tilted = 0, *norm_img = 0, *sumcanny = 0, *img_small = 0; 8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* result_seq = 0; 8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMemStorage* temp_storage = 0; 8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp* comps = 0; 8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* seq_thread[CV_MAX_THREADS] = {0}; 8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, max_threads = 0; 8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double t1; 8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvHaarDetectObjects" ); 8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double t = (double)cvGetTickCount(); 8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq *seq = 0, *seq2 = 0, *idx_seq = 0, *big_seq = 0; 8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp result_comp = {{0,0,0,0},0}; 8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double factor; 8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int npass = 2, coi; 8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool do_canny_pruning = (flags & CV_HAAR_DO_CANNY_PRUNING) != 0; 8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool find_biggest_object = (flags & CV_HAAR_FIND_BIGGEST_OBJECT) != 0; 9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool rough_search = (flags & CV_HAAR_DO_ROUGH_SEARCH) != 0; 9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_HAAR_CLASSIFIER(cascade) ) 9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier cascade" ); 9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !storage ) 9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "Null storage pointer" ); 9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( img = cvGetMat( img, &stub, &coi )); 9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( coi ) 9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_BadCOI, "COI is not supported" ); 9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_DEPTH(img->type) != CV_8U ) 9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, "Only 8-bit images are supported" ); 9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( scale_factor <= 1 ) 9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsOutOfRange, "scale factor must be > 1" ); 9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object ) 9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flags &= ~CV_HAAR_SCALE_IMAGE; 9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if(!temp) { 9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( temp = cvCreateMat( img->rows, img->cols, CV_8UC1 )); 9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if(!sum) { 9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sum = cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 )); 9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if(!sqsum) { 9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sqsum = cvCreateMat( img->rows + 1, img->cols + 1, CV_64FC1 )); 9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( temp_storage = cvCreateChildMemStorage( storage )); 9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !cascade->hid_cascade ) 9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( myicvCreateHidHaarClassifierCascade(cascade) ); 9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ((MyCvHidHaarClassifierCascade*)cascade->hid_cascade)->has_tilted_features ) 9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tilted = cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 ); 9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvRect), temp_storage ); 9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn seq2 = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), temp_storage ); 9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvAvgComp), storage ); 9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_threads = cvGetNumThreads(); 9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_threads > 1 ) 9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < max_threads; i++ ) 9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMemStorage* temp_storage_thread; 9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( temp_storage_thread = cvCreateMemStorage(0)); 9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( seq_thread[i] = cvCreateSeq( 0, sizeof(CvSeq), 9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sizeof(CvRect), temp_storage_thread )); 9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn seq_thread[0] = seq; 9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_CN(img->type) > 1 ) 9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvCvtColor( img, temp, CV_BGR2GRAY ); 9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn img = temp; 9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flags & CV_HAAR_FIND_BIGGEST_OBJECT ) 9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flags &= ~(CV_HAAR_SCALE_IMAGE|CV_HAAR_DO_CANNY_PRUNING); 9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( flags & CV_HAAR_SCALE_IMAGE ) 9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvSize win_size0 = cascade->orig_window_size; 9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// /*int use_ipp = cascade->hid_cascade->ipp_stages != 0 && 9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// icvApplyHaarClassifier_32f_C1R_p != 0; 9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( use_ipp ) 9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CV_CALL( norm_img = cvCreateMat( img->rows, img->cols, CV_32FC1 ));*/ 9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CV_CALL( img_small = cvCreateMat( img->rows + 1, img->cols + 1, CV_8UC1 )); 9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( factor = 1; ; factor *= scale_factor ) 9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int strip_count, strip_size; 9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int ystep = factor > 2. ? 1 : 2; 9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvSize win_size = { cvRound(win_size0.width*factor), 9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cvRound(win_size0.height*factor) }; 9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvSize sz = { cvRound( img->cols/factor ), cvRound( img->rows/factor ) }; 9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvSize sz1 = { sz.width - win_size0.width, sz.height - win_size0.height }; 9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// /*CvRect equ_rect = { icv_object_win_border, icv_object_win_border, 9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// win_size0.width - icv_object_win_border*2, 9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// win_size0.height - icv_object_win_border*2 };*/ 9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvMat img1, sum1, sqsum1, norm1, tilted1, mask1; 9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvMat* _tilted = 0; 9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( sz1.width <= 0 || sz1.height <= 0 ) 9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// break; 9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( win_size.width < min_size.width || win_size.height < min_size.height ) 9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// continue; 9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// img1 = cvMat( sz.height, sz.width, CV_8UC1, img_small->data.ptr ); 9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// sum1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, sum->data.ptr ); 9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// sqsum1 = cvMat( sz.height+1, sz.width+1, CV_64FC1, sqsum->data.ptr ); 9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( tilted ) 9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// tilted1 = cvMat( sz.height+1, sz.width+1, CV_32SC1, tilted->data.ptr ); 9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// _tilted = &tilted1; 9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// norm1 = cvMat( sz1.height, sz1.width, CV_32FC1, norm_img ? norm_img->data.ptr : 0 ); 10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// mask1 = cvMat( sz1.height, sz1.width, CV_8UC1, temp->data.ptr ); 10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cvResize( img, &img1, CV_INTER_LINEAR ); 10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cvIntegral( &img1, &sum1, &sqsum1, _tilted ); 10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( max_threads > 1 ) 10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// strip_count = MAX(MIN(sz1.height/ystep, max_threads*3), 1); 10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// strip_size = (sz1.height + strip_count - 1)/strip_count; 10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// strip_size = (strip_size / ystep)*ystep; 10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// else 10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// strip_count = 1; 10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// strip_size = sz1.height; 10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// //if( !use_ipp ) 10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cvSetImagesForHaarClassifierCascade( cascade, &sum1, &sqsum1, 0, 1. ); 10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// /*else 10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( i = 0; i <= sz.height; i++ ) 10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// const int* isum = (int*)(sum1.data.ptr + sum1.step*i); 10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// float* fsum = (float*)isum; 10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// const int FLT_DELTA = -(1 << 24); 10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int j; 10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( j = 0; j <= sz.width; j++ ) 10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// fsum[j] = (float)(isum[j] + FLT_DELTA); 10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// }*/ 10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//#ifdef _OPENMP 10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//#pragma omp parallel for num_threads(max_threads) schedule(dynamic) 10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//#endif 10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( i = 0; i < strip_count; i++ ) 10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int thread_id = cvGetThreadNum(); 10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int positive = 0; 10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int y1 = i*strip_size, y2 = (i+1)*strip_size/* - ystep + 1*/; 10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvSize ssz; 10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int x, y; 10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( i == strip_count - 1 || y2 > sz1.height ) 10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// y2 = sz1.height; 10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ssz = cvSize(sz1.width, y2 - y1); 10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// /*if( use_ipp ) 10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// icvRectStdDev_32f_C1R_p( 10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (float*)(sum1.data.ptr + y1*sum1.step), sum1.step, 10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (double*)(sqsum1.data.ptr + y1*sqsum1.step), sqsum1.step, 10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (float*)(norm1.data.ptr + y1*norm1.step), norm1.step, ssz, equ_rect ); 10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// positive = (ssz.width/ystep)*((ssz.height + ystep-1)/ystep); 10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// memset( mask1.data.ptr + y1*mask1.step, ystep == 1, mask1.height*mask1.step); 10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( ystep > 1 ) 10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( y = y1, positive = 0; y < y2; y += ystep ) 10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( x = 0; x < ssz.width; x += ystep ) 10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// mask1.data.ptr[mask1.step*y + x] = (uchar)1; 10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( int j = 0; j < cascade->count; j++ ) 10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( icvApplyHaarClassifier_32f_C1R_p( 10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (float*)(sum1.data.ptr + y1*sum1.step), sum1.step, 10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (float*)(norm1.data.ptr + y1*norm1.step), norm1.step, 10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// mask1.data.ptr + y1*mask1.step, mask1.step, ssz, &positive, 10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cascade->hid_cascade->stage_classifier[j].threshold, 10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cascade->hid_cascade->ipp_stages[j]) < 0 ) 10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// positive = 0; 10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// break; 10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( positive <= 0 ) 10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// break; 10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// else*/ 10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( y = y1, positive = 0; y < y2; y += ystep ) 10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( x = 0; x < ssz.width; x += ystep ) 10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// mask1.data.ptr[mask1.step*y + x] = 10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// mycvRunHaarClassifierCascade( cascade, cvPoint(x,y), 0 ) > 0; 10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// positive += mask1.data.ptr[mask1.step*y + x]; 10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( positive > 0 ) 10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( y = y1; y < y2; y += ystep ) 10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( x = 0; x < ssz.width; x += ystep ) 10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( mask1.data.ptr[mask1.step*y + x] != 0 ) 10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvRect obj_rect = { cvRound(x*factor), cvRound(y*factor), 10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// win_size.width, win_size.height }; 10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cvSeqPush( seq_thread[thread_id], &obj_rect ); 11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// // gather the results 11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( max_threads > 1 ) 11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( i = 0; i < max_threads; i++ ) 11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvSeq* s = seq_thread[i]; 11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int j, total = s->total; 11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// CvSeqBlock* b = s->first; 11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// for( j = 0; j < total; j += b->count, b = b->next ) 11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cvSeqPushMulti( seq, b->data, b->count ); 11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// else 11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t1 = (double)cvGetTickCount(); 11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// printf( "init time = %gms\n", (t1 - t)/tickFreqTimes1000); 11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = t1; 11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n_factors = 0; 11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect scan_roi_rect = {0,0,0,0}; 11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bool is_found = false, scan_roi = false; 11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvIntegral( img, sum, sqsum, tilted ); 11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( do_canny_pruning ) 11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// sumcanny = cvCreateMat( img->rows + 1, img->cols + 1, CV_32SC1 ); 11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cvCanny( img, temp, 0, 50, 3 ); 11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// cvIntegral( temp, sumcanny ); 11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( (unsigned)split_stage >= (unsigned)cascade->count || 11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((MyCvHidHaarClassifierCascade*)cascade->hid_cascade)->is_tree ) 11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn split_stage = cascade->count; 11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn npass = 1; 11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( n_factors = 0, factor = 1; 11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn factor*cascade->orig_window_size.width < img->cols - 10 && 11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn factor*cascade->orig_window_size.height < img->rows - 10; 11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n_factors++, factor *= scale_factor ) 11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ; 11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object ) 11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scale_factor = 1./scale_factor; 11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn factor *= scale_factor; 11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn big_seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvRect), temp_storage ); 11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn factor = 1; 11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; n_factors-- > 0 && !is_found; factor *= scale_factor ) 11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const double ystep = MAX( 2, factor ); 11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize win_size = { cvRound( cascade->orig_window_size.width * factor ), 11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvRound( cascade->orig_window_size.height * factor )}; 11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect equ_rect = { 0, 0, 0, 0 }; 11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int *p0 = 0, *p1 = 0, *p2 = 0, *p3 = 0; 11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int *pq0 = 0, *pq1 = 0, *pq2 = 0, *pq3 = 0; 11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int pass, stage_offset = 0; 11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int start_x = 0, start_y = 0; 11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int end_x = cvRound((img->cols - win_size.width) / ystep); 11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int end_y = cvRound((img->rows - win_size.height) / ystep); 11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( win_size.width < min_size.width || win_size.height < min_size.height ) 11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object ) 11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn continue; 11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mycvSetImagesForHaarClassifierCascade( cascade, sum, sqsum, tilted, factor ); 11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvZero( temp ); 11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( do_canny_pruning ) 11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// equ_rect.x = cvRound(win_size.width*0.15); 11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// equ_rect.y = cvRound(win_size.height*0.15); 11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// equ_rect.width = cvRound(win_size.width*0.7); 11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// equ_rect.height = cvRound(win_size.height*0.7); 11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// p0 = (int*)(sumcanny->data.ptr + equ_rect.y*sumcanny->step) + equ_rect.x; 11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// p1 = (int*)(sumcanny->data.ptr + equ_rect.y*sumcanny->step) 11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// + equ_rect.x + equ_rect.width; 11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// p2 = (int*)(sumcanny->data.ptr + (equ_rect.y + equ_rect.height)*sumcanny->step) + equ_rect.x; 11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// p3 = (int*)(sumcanny->data.ptr + (equ_rect.y + equ_rect.height)*sumcanny->step) 11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// + equ_rect.x + equ_rect.width; 11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// pq0 = (int*)(sum->data.ptr + equ_rect.y*sum->step) + equ_rect.x; 11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// pq1 = (int*)(sum->data.ptr + equ_rect.y*sum->step) 11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// + equ_rect.x + equ_rect.width; 11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// pq2 = (int*)(sum->data.ptr + (equ_rect.y + equ_rect.height)*sum->step) + equ_rect.x; 11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// pq3 = (int*)(sum->data.ptr + (equ_rect.y + equ_rect.height)*sum->step) 11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// + equ_rect.x + equ_rect.width; 12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( scan_roi ) 12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //adjust start_height and stop_height 12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn start_y = cvRound(scan_roi_rect.y / ystep); 12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn end_y = cvRound((scan_roi_rect.y + scan_roi_rect.height - win_size.height) / ystep); 12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn start_x = cvRound(scan_roi_rect.x / ystep); 12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn end_x = cvRound((scan_roi_rect.x + scan_roi_rect.width - win_size.width) / ystep); 12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((MyCvHidHaarClassifierCascade*)cascade->hid_cascade)->count = split_stage; 12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( pass = 0; pass < npass; pass++ ) 12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef _OPENMP 12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#pragma omp parallel for num_threads(max_threads) schedule(dynamic) 12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( int _iy = start_y; _iy < end_y; _iy++ ) 12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int thread_id = cvGetThreadNum(); 12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int iy = cvRound(_iy*ystep); 12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int _ix, _xstep = 1; 12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* mask_row = temp->data.ptr + temp->step * iy; 12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( _ix = start_x; _ix < end_x; _ix += _xstep ) 12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ix = cvRound(_ix*ystep); // it really should be ystep 12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pass == 0 ) 12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result; 12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _xstep = 2; 12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( do_canny_pruning ) 12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// { 12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int offset; 12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// int s, sq; 12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// offset = iy*(sum->step/sizeof(p0[0])) + ix; 12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// s = p0[offset] - p1[offset] - p2[offset] + p3[offset]; 12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// sq = pq0[offset] - pq1[offset] - pq2[offset] + pq3[offset]; 12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// if( s < 100 || sq < 20 ) 12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// continue; 12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// } 12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = mycvRunHaarClassifierCascade( cascade, cvPoint(ix,iy), 0 ); 12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( result > 0 ) 12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pass < npass - 1 ) 12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask_row[ix] = 1; 12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect rect = cvRect(ix,iy,win_size.width,win_size.height); 12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( seq_thread[thread_id], &rect ); 12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( result < 0 ) 12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _xstep = 1; 12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( mask_row[ix] ) 12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result = mycvRunHaarClassifierCascade( cascade, cvPoint(ix,iy), 12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_offset ); 12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( result > 0 ) 12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pass == npass - 1 ) 12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect rect = cvRect(ix,iy,win_size.width,win_size.height); 12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( seq_thread[thread_id], &rect ); 12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask_row[ix] = 0; 12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stage_offset = ((MyCvHidHaarClassifierCascade*)cascade->hid_cascade)->count; 12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((MyCvHidHaarClassifierCascade*)cascade->hid_cascade)->count = cascade->count; 12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // gather the results 12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_threads > 1 ) 12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < max_threads; i++ ) 12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* s = seq_thread[i]; 12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j, total = s->total; 12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqBlock* b = s->first; 12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < total; j += b->count, b = b->next ) 12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPushMulti( seq, b->data, b->count ); 12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object ) 12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* bseq = min_neighbors > 0 ? big_seq : seq; 12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( min_neighbors > 0 && !scan_roi ) 12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // group retrieved rectangles in order to filter out noise 13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ncomp = cvSeqPartition( seq, 0, &idx_seq, myis_equal, 0 ); 13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( comps = (CvAvgComp*)cvAlloc( (ncomp+1)*sizeof(comps[0]))); 13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( comps, 0, (ncomp+1)*sizeof(comps[0])); 13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if VERY_ROUGH_SEARCH 13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( rough_search ) 13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq->total; i++ ) 13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r1 = *(CvRect*)cvGetSeqElem( seq, i ); 13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = *(int*)cvGetSeqElem( idx_seq, i ); 13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( (unsigned)idx < (unsigned)ncomp ); 13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].neighbors++; 13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.x += r1.x; 13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.y += r1.y; 13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.width += r1.width; 13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.height += r1.height; 13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // calculate average bounding box 13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < ncomp; i++ ) 13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n = comps[i].neighbors; 13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( n >= min_neighbors ) 13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp comp; 13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = (comps[i].rect.x*2 + n)/(2*n); 13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = (comps[i].rect.y*2 + n)/(2*n); 13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = (comps[i].rect.width*2 + n)/(2*n); 13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = (comps[i].rect.height*2 + n)/(2*n); 13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.neighbors = n; 13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( bseq, &comp ); 13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0 ; i <= ncomp; i++ ) 13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[i].rect.x = comps[i].rect.y = INT_MAX; 13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // count number of neighbors 13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq->total; i++ ) 13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r1 = *(CvRect*)cvGetSeqElem( seq, i ); 13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = *(int*)cvGetSeqElem( idx_seq, i ); 13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( (unsigned)idx < (unsigned)ncomp ); 13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].neighbors++; 13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // rect.width and rect.height will store coordinate of right-bottom corner 13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.x = MIN(comps[idx].rect.x, r1.x); 13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.y = MIN(comps[idx].rect.y, r1.y); 13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.width = MAX(comps[idx].rect.width, r1.x+r1.width-1); 13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.height = MAX(comps[idx].rect.height, r1.y+r1.height-1); 13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // calculate enclosing box 13596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < ncomp; i++ ) 13606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n = comps[i].neighbors; 13626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( n >= min_neighbors ) 13636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp comp; 13656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int t; 13666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double min_scale = rough_search ? 0.6 : 0.4; 13676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = comps[i].rect.x; 13686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = comps[i].rect.y; 13696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = comps[i].rect.width - comps[i].rect.x + 1; 13706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = comps[i].rect.height - comps[i].rect.y + 1; 13716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // update min_size 13736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = cvRound( comp.rect.width*min_scale ); 13746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_size.width = MAX( min_size.width, t ); 13756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = cvRound( comp.rect.height*min_scale ); 13776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_size.height = MAX( min_size.height, t ); 13786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //expand the box by 20% because we could miss some neighbours 13806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //see 'is_equal' function 13816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if 1 13826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int offset = cvRound(comp.rect.width * 0.2); 13836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int right = MIN( img->cols-1, comp.rect.x+comp.rect.width-1 + offset ); 13846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int bottom = MIN( img->rows-1, comp.rect.y+comp.rect.height-1 + offset); 13856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = MAX( comp.rect.x - offset, 0 ); 13866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = MAX( comp.rect.y - offset, 0 ); 13876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = right - comp.rect.x + 1; 13886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = bottom - comp.rect.y + 1; 13896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 13906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.neighbors = n; 13926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( bseq, &comp ); 13936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &comps ); 13986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // extract the biggest rect 14016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( bseq->total > 0 ) 14026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int max_area = 0; 14046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < bseq->total; i++ ) 14056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp* comp = (CvAvgComp*)cvGetSeqElem( bseq, i ); 14076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int area = comp->rect.width * comp->rect.height; 14086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_area < area ) 14096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_area = area; 14116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result_comp.rect = comp->rect; 14126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result_comp.neighbors = bseq == seq ? 1 : comp->neighbors; 14136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //Prepare information for further scanning inside the biggest rectangle 14176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if VERY_ROUGH_SEARCH 14196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // change scan ranges to roi in case of required 14206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !rough_search && !scan_roi ) 14216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scan_roi = true; 14236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scan_roi_rect = result_comp.rect; 14246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvClearSeq(bseq); 14256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( rough_search ) 14276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn is_found = true; 14286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else 14296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !scan_roi ) 14306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scan_roi = true; 14326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scan_roi_rect = result_comp.rect; 14336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvClearSeq(bseq); 14346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 14366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// t1 = (double)cvGetTickCount(); 14426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// printf( "factors time = %gms\n", (t1 - t)/tickFreqTimes1000); 14436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// t = t1; 14446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( min_neighbors == 0 && !find_biggest_object ) 14466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq->total; i++ ) 14486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect* rect = (CvRect*)cvGetSeqElem( seq, i ); 14506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp comp; 14516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect = *rect; 14526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.neighbors = 1; 14536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( result_seq, &comp ); 14546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( min_neighbors != 0 14586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if VERY_ROUGH_SEARCH 14596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn && (!find_biggest_object || !rough_search) 14606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 14616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ) 14626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // group retrieved rectangles in order to filter out noise 14646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int ncomp = cvSeqPartition( seq, 0, &idx_seq, myis_equal, 0 ); 14656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( comps = (CvAvgComp*)cvAlloc( (ncomp+1)*sizeof(comps[0]))); 14666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( comps, 0, (ncomp+1)*sizeof(comps[0])); 14676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // count number of neighbors 14696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq->total; i++ ) 14706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect r1 = *(CvRect*)cvGetSeqElem( seq, i ); 14726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = *(int*)cvGetSeqElem( idx_seq, i ); 14736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( (unsigned)idx < (unsigned)ncomp ); 14746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].neighbors++; 14766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.x += r1.x; 14786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.y += r1.y; 14796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.width += r1.width; 14806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comps[idx].rect.height += r1.height; 14816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // calculate average bounding box 14846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < ncomp; i++ ) 14856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n = comps[i].neighbors; 14876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( n >= min_neighbors ) 14886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 14896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp comp; 14906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = (comps[i].rect.x*2 + n)/(2*n); 14916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = (comps[i].rect.y*2 + n)/(2*n); 14926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = (comps[i].rect.width*2 + n)/(2*n); 14936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = (comps[i].rect.height*2 + n)/(2*n); 14946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.neighbors = comps[i].neighbors; 14956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 14966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( seq2, &comp ); 14976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 14996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !find_biggest_object ) 15016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // filter out small face rectangles inside large face rectangles 15036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq2->total; i++ ) 15046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp r1 = *(CvAvgComp*)cvGetSeqElem( seq2, i ); 15066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int j, flag = 1; 15076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < seq2->total; j++ ) 15096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp r2 = *(CvAvgComp*)cvGetSeqElem( seq2, j ); 15116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int distance = cvRound( r2.rect.width * 0.2 ); 15126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i != j && 15146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r1.rect.x >= r2.rect.x - distance && 15156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r1.rect.y >= r2.rect.y - distance && 15166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r1.rect.x + r1.rect.width <= r2.rect.x + r2.rect.width + distance && 15176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn r1.rect.y + r1.rect.height <= r2.rect.y + r2.rect.height + distance && 15186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (r2.neighbors > MAX( 3, r1.neighbors ) || r1.neighbors < 3) ) 15196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flag = 0; 15216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 15226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flag ) 15266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( result_seq, &r1 ); 15276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 15306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int max_area = 0; 15326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < seq2->total; i++ ) 15336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvAvgComp* comp = (CvAvgComp*)cvGetSeqElem( seq2, i ); 15356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int area = comp->rect.width * comp->rect.height; 15366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_area < area ) 15376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_area = area; 15396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result_comp = *comp; 15406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t1 = (double)cvGetTickCount(); 15466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// printf( "results eval time = %gms\n", (t1 - t)/tickFreqTimes1000); 15476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = t1; 15486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( find_biggest_object && result_comp.rect.width > 0 ) 15506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSeqPush( result_seq, &result_comp ); 15516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 15536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_threads > 1 ) 15556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < max_threads; i++ ) 15566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 15576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( seq_thread[i] ) 15586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMemStorage( &seq_thread[i]->storage ); 15596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 15606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMemStorage( &temp_storage ); 15626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &sum ); 15636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &sqsum ); 15646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &tilted ); 15656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &temp ); 15666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &sumcanny ); 15676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &norm_img ); 15686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &img_small ); 15696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &comps ); 15706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 15716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result_seq; 15726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1573