Update to 2.0.0 tree from current Fremantle build
[opencv] / apps / haartraining / cvhaarclassifier.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 /*
43  * cvhaarclassifier.cpp
44  *
45  * haar classifiers (stump, CART, stage, cascade)
46  */
47
48 #include "_cvhaartraining.h"
49
50
51 CvIntHaarClassifier* icvCreateCARTHaarClassifier( int count )
52 {
53     CvCARTHaarClassifier* cart;
54     size_t datasize;
55
56     datasize = sizeof( *cart ) +
57         ( sizeof( int ) +
58           sizeof( CvTHaarFeature ) + sizeof( CvFastHaarFeature ) +
59           sizeof( float ) + sizeof( int ) + sizeof( int ) ) * count +
60         sizeof( float ) * (count + 1);
61
62     cart = (CvCARTHaarClassifier*) cvAlloc( datasize );
63     memset( cart, 0, datasize );
64
65     cart->feature = (CvTHaarFeature*) (cart + 1);
66     cart->fastfeature = (CvFastHaarFeature*) (cart->feature + count);
67     cart->threshold = (float*) (cart->fastfeature + count);
68     cart->left = (int*) (cart->threshold + count);
69     cart->right = (int*) (cart->left + count);
70     cart->val = (float*) (cart->right + count);
71     cart->compidx = (int*) (cart->val + count + 1 );
72     cart->count = count;
73     cart->eval = icvEvalCARTHaarClassifier;
74     cart->save = icvSaveCARTHaarClassifier;
75     cart->release = icvReleaseHaarClassifier;
76
77     return (CvIntHaarClassifier*) cart;
78 }
79
80
81 void icvReleaseHaarClassifier( CvIntHaarClassifier** classifier )
82 {
83     cvFree( classifier );
84     *classifier = NULL;
85 }
86
87
88 void icvInitCARTHaarClassifier( CvCARTHaarClassifier* carthaar, CvCARTClassifier* cart,
89                                 CvIntHaarFeatures* intHaarFeatures )
90 {
91     int i;
92
93     for( i = 0; i < cart->count; i++ )
94     {
95         carthaar->feature[i] = intHaarFeatures->feature[cart->compidx[i]];
96         carthaar->fastfeature[i] = intHaarFeatures->fastfeature[cart->compidx[i]];
97         carthaar->threshold[i] = cart->threshold[i];
98         carthaar->left[i] = cart->left[i];
99         carthaar->right[i] = cart->right[i];
100         carthaar->val[i] = cart->val[i];
101         carthaar->compidx[i] = cart->compidx[i];
102     }
103     carthaar->count = cart->count;
104     carthaar->val[cart->count] = cart->val[cart->count];
105 }
106
107
108 float icvEvalCARTHaarClassifier( CvIntHaarClassifier* classifier,
109                                  sum_type* sum, sum_type* tilted, float normfactor )
110 {
111     int idx = 0;
112
113     do
114     {
115         if( cvEvalFastHaarFeature(
116                 ((CvCARTHaarClassifier*) classifier)->fastfeature + idx, sum, tilted )
117               < (((CvCARTHaarClassifier*) classifier)->threshold[idx] * normfactor) )
118         {
119             idx = ((CvCARTHaarClassifier*) classifier)->left[idx];
120         }
121         else
122         {
123             idx = ((CvCARTHaarClassifier*) classifier)->right[idx];
124         }
125     } while( idx > 0 );
126
127     return ((CvCARTHaarClassifier*) classifier)->val[-idx];
128 }
129
130
131 CvIntHaarClassifier* icvCreateStageHaarClassifier( int count, float threshold )
132 {
133     CvStageHaarClassifier* stage;
134     size_t datasize;
135
136     datasize = sizeof( *stage ) + sizeof( CvIntHaarClassifier* ) * count;
137     stage = (CvStageHaarClassifier*) cvAlloc( datasize );
138     memset( stage, 0, datasize );
139
140     stage->count = count;
141     stage->threshold = threshold;
142     stage->classifier = (CvIntHaarClassifier**) (stage + 1);
143
144     stage->eval = icvEvalStageHaarClassifier;
145     stage->save = icvSaveStageHaarClassifier;
146     stage->release = icvReleaseStageHaarClassifier;
147
148     return (CvIntHaarClassifier*) stage;
149 }
150
151
152 void icvReleaseStageHaarClassifier( CvIntHaarClassifier** classifier )
153 {
154     int i;
155
156     for( i = 0; i < ((CvStageHaarClassifier*) *classifier)->count; i++ )
157     {
158         if( ((CvStageHaarClassifier*) *classifier)->classifier[i] != NULL )
159         {
160             ((CvStageHaarClassifier*) *classifier)->classifier[i]->release(
161                 &(((CvStageHaarClassifier*) *classifier)->classifier[i]) );
162         }
163     }
164
165     cvFree( classifier );
166     *classifier = NULL;
167 }
168
169
170 float icvEvalStageHaarClassifier( CvIntHaarClassifier* classifier,
171                                   sum_type* sum, sum_type* tilted, float normfactor )
172 {
173     int i;
174     float stage_sum;
175
176     stage_sum = 0.0F;
177     for( i = 0; i < ((CvStageHaarClassifier*) classifier)->count; i++ )
178     {
179         stage_sum +=
180             ((CvStageHaarClassifier*) classifier)->classifier[i]->eval(
181                 ((CvStageHaarClassifier*) classifier)->classifier[i],
182                 sum, tilted, normfactor );
183     }
184
185     return stage_sum;
186 }
187
188
189 CvIntHaarClassifier* icvCreateCascadeHaarClassifier( int count )
190 {
191     CvCascadeHaarClassifier* ptr;
192     size_t datasize;
193
194     datasize = sizeof( *ptr ) + sizeof( CvIntHaarClassifier* ) * count;
195     ptr = (CvCascadeHaarClassifier*) cvAlloc( datasize );
196     memset( ptr, 0, datasize );
197
198     ptr->count = count;
199     ptr->classifier = (CvIntHaarClassifier**) (ptr + 1);
200
201     ptr->eval = icvEvalCascadeHaarClassifier;
202     ptr->save = NULL;
203     ptr->release = icvReleaseCascadeHaarClassifier;
204
205     return (CvIntHaarClassifier*) ptr;
206 }
207
208
209 void icvReleaseCascadeHaarClassifier( CvIntHaarClassifier** classifier )
210 {
211     int i;
212
213     for( i = 0; i < ((CvCascadeHaarClassifier*) *classifier)->count; i++ )
214     {
215         if( ((CvCascadeHaarClassifier*) *classifier)->classifier[i] != NULL )
216         {
217             ((CvCascadeHaarClassifier*) *classifier)->classifier[i]->release(
218                 &(((CvCascadeHaarClassifier*) *classifier)->classifier[i]) );
219         }
220     }
221
222     cvFree( classifier );
223     *classifier = NULL;
224 }
225
226
227 float icvEvalCascadeHaarClassifier( CvIntHaarClassifier* classifier,
228                                     sum_type* sum, sum_type* tilted, float normfactor )
229 {
230     int i;
231
232     for( i = 0; i < ((CvCascadeHaarClassifier*) classifier)->count; i++ )
233     {
234         if( ((CvCascadeHaarClassifier*) classifier)->classifier[i]->eval(
235                     ((CvCascadeHaarClassifier*) classifier)->classifier[i],
236                     sum, tilted, normfactor )
237             < ( ((CvStageHaarClassifier*)
238                     ((CvCascadeHaarClassifier*) classifier)->classifier[i])->threshold
239                             - CV_THRESHOLD_EPS) )
240         {
241             return 0.0;
242         }
243     }
244
245     return 1.0;
246 }
247
248
249 void icvSaveHaarFeature( CvTHaarFeature* feature, FILE* file )
250 {
251     fprintf( file, "%d\n", ( ( feature->rect[2].weight == 0.0F ) ? 2 : 3) );
252     fprintf( file, "%d %d %d %d %d %d\n",
253         feature->rect[0].r.x,
254         feature->rect[0].r.y,
255         feature->rect[0].r.width,
256         feature->rect[0].r.height,
257         0,
258         (int) (feature->rect[0].weight) );
259     fprintf( file, "%d %d %d %d %d %d\n",
260         feature->rect[1].r.x,
261         feature->rect[1].r.y,
262         feature->rect[1].r.width,
263         feature->rect[1].r.height,
264         0,
265         (int) (feature->rect[1].weight) );
266     if( feature->rect[2].weight != 0.0F )
267     {
268         fprintf( file, "%d %d %d %d %d %d\n",
269             feature->rect[2].r.x,
270             feature->rect[2].r.y,
271             feature->rect[2].r.width,
272             feature->rect[2].r.height,
273             0,
274             (int) (feature->rect[2].weight) );
275     }
276     fprintf( file, "%s\n", &(feature->desc[0]) );
277 }
278
279
280 void icvLoadHaarFeature( CvTHaarFeature* feature, FILE* file )
281 {
282     int nrect;
283     int j;
284     int tmp;
285     int weight;
286
287     nrect = 0;
288     fscanf( file, "%d", &nrect );
289
290     assert( nrect <= CV_HAAR_FEATURE_MAX );
291
292     for( j = 0; j < nrect; j++ )
293     {
294         fscanf( file, "%d %d %d %d %d %d",
295             &(feature->rect[j].r.x),
296             &(feature->rect[j].r.y),
297             &(feature->rect[j].r.width),
298             &(feature->rect[j].r.height),
299             &tmp, &weight );
300         feature->rect[j].weight = (float) weight;
301     }
302     for( j = nrect; j < CV_HAAR_FEATURE_MAX; j++ )
303     {
304         feature->rect[j].r.x = 0;
305         feature->rect[j].r.y = 0;
306         feature->rect[j].r.width = 0;
307         feature->rect[j].r.height = 0;
308         feature->rect[j].weight = 0.0f;
309     }
310     fscanf( file, "%s", &(feature->desc[0]) );
311     feature->tilted = ( feature->desc[0] == 't' );
312 }
313
314
315 void icvSaveCARTHaarClassifier( CvIntHaarClassifier* classifier, FILE* file )
316 {
317     int i;
318     int count;
319
320     count = ((CvCARTHaarClassifier*) classifier)->count;
321     fprintf( file, "%d\n", count );
322     for( i = 0; i < count; i++ )
323     {
324         icvSaveHaarFeature( &(((CvCARTHaarClassifier*) classifier)->feature[i]), file );
325         fprintf( file, "%e %d %d\n",
326             ((CvCARTHaarClassifier*) classifier)->threshold[i],
327             ((CvCARTHaarClassifier*) classifier)->left[i],
328             ((CvCARTHaarClassifier*) classifier)->right[i] );
329     }
330     for( i = 0; i <= count; i++ )
331     {
332         fprintf( file, "%e ", ((CvCARTHaarClassifier*) classifier)->val[i] );
333     }
334     fprintf( file, "\n" );
335 }
336
337
338 CvIntHaarClassifier* icvLoadCARTHaarClassifier( FILE* file, int step )
339 {
340     CvCARTHaarClassifier* ptr;
341     int i;
342     int count;
343
344     ptr = NULL;
345     fscanf( file, "%d", &count );
346     if( count > 0 )
347     {
348         ptr = (CvCARTHaarClassifier*) icvCreateCARTHaarClassifier( count );
349         for( i = 0; i < count; i++ )
350         {
351             icvLoadHaarFeature( &(ptr->feature[i]), file );
352             fscanf( file, "%f %d %d", &(ptr->threshold[i]), &(ptr->left[i]),
353                                       &(ptr->right[i]) );
354         }
355         for( i = 0; i <= count; i++ )
356         {
357             fscanf( file, "%f", &(ptr->val[i]) );
358         }
359         icvConvertToFastHaarFeature( ptr->feature, ptr->fastfeature, ptr->count, step );
360     }
361
362     return (CvIntHaarClassifier*) ptr;
363 }
364
365
366 void icvSaveStageHaarClassifier( CvIntHaarClassifier* classifier, FILE* file )
367 {
368     int count;
369     int i;
370     float threshold;
371
372     count = ((CvStageHaarClassifier*) classifier)->count;
373     fprintf( file, "%d\n", count );
374     for( i = 0; i < count; i++ )
375     {
376         ((CvStageHaarClassifier*) classifier)->classifier[i]->save(
377             ((CvStageHaarClassifier*) classifier)->classifier[i], file );
378     }
379
380     threshold = ((CvStageHaarClassifier*) classifier)->threshold;
381
382     /* to be compatible with the previous implementation */
383     /* threshold = 2.0F * ((CvStageHaarClassifier*) classifier)->threshold - count; */
384
385     fprintf( file, "%e\n", threshold );
386 }
387
388
389
390 CvIntHaarClassifier* icvLoadCARTStageHaarClassifierF( FILE* file, int step )
391 {
392     CvStageHaarClassifier* ptr = NULL;
393
394     //CV_FUNCNAME( "icvLoadCARTStageHaarClassifierF" );
395
396     __BEGIN__;
397
398     if( file != NULL )
399     {
400         int count;
401         int i;
402         float threshold;
403
404         count = 0;
405         fscanf( file, "%d", &count );
406         if( count > 0 )
407         {
408             ptr = (CvStageHaarClassifier*) icvCreateStageHaarClassifier( count, 0.0F );
409             for( i = 0; i < count; i++ )
410             {
411                 ptr->classifier[i] = icvLoadCARTHaarClassifier( file, step );
412             }
413
414             fscanf( file, "%f", &threshold );
415
416             ptr->threshold = threshold;
417             /* to be compatible with the previous implementation */
418             /* ptr->threshold = 0.5F * (threshold + count); */
419         }
420         if( feof( file ) )
421         {
422             ptr->release( (CvIntHaarClassifier**) &ptr );
423             ptr = NULL;
424         }
425     }
426
427     __END__;
428
429     return (CvIntHaarClassifier*) ptr;
430 }
431
432
433 CvIntHaarClassifier* icvLoadCARTStageHaarClassifier( const char* filename, int step )
434 {
435     CvIntHaarClassifier* ptr = NULL;
436
437     CV_FUNCNAME( "icvLoadCARTStageHaarClassifier" );
438
439     __BEGIN__;
440
441     FILE* file;
442
443     file = fopen( filename, "r" );
444     if( file )
445     {
446         CV_CALL( ptr = icvLoadCARTStageHaarClassifierF( file, step ) );
447         fclose( file );
448     }
449
450     __END__;
451
452     return ptr;
453 }
454
455 /* tree cascade classifier */
456
457 /* evaluates a tree cascade classifier */
458
459 float icvEvalTreeCascadeClassifier( CvIntHaarClassifier* classifier,
460                                     sum_type* sum, sum_type* tilted, float normfactor )
461 {
462     CvTreeCascadeNode* ptr;
463
464     ptr = ((CvTreeCascadeClassifier*) classifier)->root;
465
466     while( ptr )
467     {
468         if( ptr->stage->eval( (CvIntHaarClassifier*) ptr->stage,
469                               sum, tilted, normfactor )
470                 >= ptr->stage->threshold - CV_THRESHOLD_EPS )
471         {
472             ptr = ptr->child;
473         }
474         else
475         {
476             while( ptr && ptr->next == NULL ) ptr = ptr->parent;
477             if( ptr == NULL ) return 0.0F;
478             ptr = ptr->next;
479         }
480     }
481
482     return 1.0F;
483 }
484
485 /* sets path int the tree form the root to the leaf node */
486
487 void icvSetLeafNode( CvTreeCascadeClassifier* tcc, CvTreeCascadeNode* leaf )
488 {
489     CV_FUNCNAME( "icvSetLeafNode" );
490
491     __BEGIN__;
492
493     CvTreeCascadeNode* ptr;
494
495     ptr = NULL;
496     while( leaf )
497     {
498         leaf->child_eval = ptr;
499         ptr = leaf;
500         leaf = leaf->parent;
501     }
502
503     leaf = tcc->root;
504     while( leaf && leaf != ptr ) leaf = leaf->next;
505     if( leaf != ptr )
506         CV_ERROR( CV_StsError, "Invalid tcc or leaf node." );
507
508     tcc->root_eval = ptr;
509
510     __END__;
511 }
512
513 /* evaluates a tree cascade classifier. used in filtering */
514
515 float icvEvalTreeCascadeClassifierFilter( CvIntHaarClassifier* classifier, sum_type* sum,
516                                           sum_type* tilted, float normfactor )
517 {
518     CvTreeCascadeNode* ptr;
519     CvTreeCascadeClassifier* tree;
520
521     tree = (CvTreeCascadeClassifier*) classifier;
522
523
524
525     ptr = ((CvTreeCascadeClassifier*) classifier)->root_eval;
526     while( ptr )
527     {
528         if( ptr->stage->eval( (CvIntHaarClassifier*) ptr->stage,
529                               sum, tilted, normfactor )
530                 < ptr->stage->threshold - CV_THRESHOLD_EPS )
531         {
532             return 0.0F;
533         }
534         ptr = ptr->child_eval;
535     }
536
537     return 1.0F;
538 }
539
540 /* creates tree cascade node */
541
542 CvTreeCascadeNode* icvCreateTreeCascadeNode()
543 {
544     CvTreeCascadeNode* ptr = NULL;
545
546     CV_FUNCNAME( "icvCreateTreeCascadeNode" );
547
548     __BEGIN__;
549     size_t data_size;
550
551     data_size = sizeof( *ptr );
552     CV_CALL( ptr = (CvTreeCascadeNode*) cvAlloc( data_size ) );
553     memset( ptr, 0, data_size );
554
555     __END__;
556
557     return ptr;
558 }
559
560 /* releases all tree cascade nodes accessible via links */
561
562 void icvReleaseTreeCascadeNodes( CvTreeCascadeNode** node )
563 {
564     //CV_FUNCNAME( "icvReleaseTreeCascadeNodes" );
565
566     __BEGIN__;
567
568     if( node && *node )
569     {
570         CvTreeCascadeNode* ptr;
571         CvTreeCascadeNode* ptr_;
572
573         ptr = *node;
574
575         while( ptr )
576         {
577             while( ptr->child ) ptr = ptr->child;
578
579             if( ptr->stage ) ptr->stage->release( (CvIntHaarClassifier**) &ptr->stage );
580             ptr_ = ptr;
581
582             while( ptr && ptr->next == NULL ) ptr = ptr->parent;
583             if( ptr ) ptr = ptr->next;
584
585             cvFree( &ptr_ );
586         }
587     }
588
589     __END__;
590 }
591
592
593 /* releases tree cascade classifier */
594
595 void icvReleaseTreeCascadeClassifier( CvIntHaarClassifier** classifier )
596 {
597     if( classifier && *classifier )
598     {
599         icvReleaseTreeCascadeNodes( &((CvTreeCascadeClassifier*) *classifier)->root );
600         cvFree( classifier );
601         *classifier = NULL;
602     }
603 }
604
605
606 void icvPrintTreeCascade( CvTreeCascadeNode* root )
607 {
608     //CV_FUNCNAME( "icvPrintTreeCascade" );
609
610     __BEGIN__;
611
612     CvTreeCascadeNode* node;
613     CvTreeCascadeNode* n;
614     char buf0[256];
615     char buf[256];
616     int level;
617     int i;
618     int max_level;
619
620     node = root;
621     level = max_level = 0;
622     while( node )
623     {
624         while( node->child ) { node = node->child; level++; }
625         if( level > max_level ) { max_level = level; }
626         while( node && !node->next ) { node = node->parent; level--; }
627         if( node ) node = node->next;
628     }
629
630     printf( "\nTree Classifier\n" );
631     printf( "Stage\n" );
632     for( i = 0; i <= max_level; i++ ) printf( "+---" );
633     printf( "+\n" );
634     for( i = 0; i <= max_level; i++ ) printf( "|%3d", i );
635     printf( "|\n" );
636     for( i = 0; i <= max_level; i++ ) printf( "+---" );
637     printf( "+\n\n" );
638
639     node = root;
640
641     buf[0] = 0;
642     while( node )
643     {
644         sprintf( buf + strlen( buf ), "%3d", node->idx );
645         while( node->child )
646         {
647             node = node->child;
648             sprintf( buf + strlen( buf ),
649                 ((node->idx < 10) ? "---%d" : ((node->idx < 100) ? "--%d" : "-%d")),
650                 node->idx );
651         }
652         printf( " %s\n", buf );
653
654         while( node && !node->next ) { node = node->parent; }
655         if( node )
656         {
657             node = node->next;
658
659             n = node->parent;
660             buf[0] = 0;
661             while( n )
662             {
663                 if( n->next )
664                     sprintf( buf0, "  | %s", buf );
665                 else
666                     sprintf( buf0, "    %s", buf );
667                 strcpy( buf, buf0 );
668                 n = n->parent;
669             }
670             printf( " %s  |\n", buf );
671         }
672     }
673     printf( "\n" );
674     fflush( stdout );
675
676     __END__;
677 }
678
679
680
681 CvIntHaarClassifier* icvLoadTreeCascadeClassifier( const char* filename, int step,
682                                                    int* splits )
683 {
684     CvTreeCascadeClassifier* ptr = NULL;
685     CvTreeCascadeNode** nodes = NULL;
686
687     CV_FUNCNAME( "icvLoadTreeCascadeClassifier" );
688
689     __BEGIN__;
690
691     size_t data_size;
692     CvStageHaarClassifier* stage;
693     char stage_name[PATH_MAX];
694     char* suffix;
695     int i, num;
696     FILE* f;
697     int result, parent=0, next=0;
698     int stub;
699
700     if( !splits ) splits = &stub;
701
702     *splits = 0;
703
704     data_size = sizeof( *ptr );
705
706     CV_CALL( ptr = (CvTreeCascadeClassifier*) cvAlloc( data_size ) );
707     memset( ptr, 0, data_size );
708
709     ptr->eval = icvEvalTreeCascadeClassifier;
710     ptr->release = icvReleaseTreeCascadeClassifier;
711
712     sprintf( stage_name, "%s/", filename );
713     suffix = stage_name + strlen( stage_name );
714
715     for( i = 0; ; i++ )
716     {
717         sprintf( suffix, "%d/%s", i, CV_STAGE_CART_FILE_NAME );
718         f = fopen( stage_name, "r" );
719         if( !f ) break;
720         fclose( f );
721     }
722     num = i;
723
724     if( num < 1 ) EXIT;
725
726     data_size = sizeof( *nodes ) * num;
727     CV_CALL( nodes = (CvTreeCascadeNode**) cvAlloc( data_size ) );
728
729     for( i = 0; i < num; i++ )
730     {
731         sprintf( suffix, "%d/%s", i, CV_STAGE_CART_FILE_NAME );
732         f = fopen( stage_name, "r" );
733         CV_CALL( stage = (CvStageHaarClassifier*)
734             icvLoadCARTStageHaarClassifierF( f, step ) );
735
736         result = ( f && stage ) ? fscanf( f, "%d%d", &parent, &next ) : 0;
737         if( f ) fclose( f );
738
739         if( result != 2 )
740         {
741             num = i;
742             break;
743         }
744
745         printf( "Stage %d loaded\n", i );
746
747         if( parent >= i || (next != -1 && next != i + 1) )
748             CV_ERROR( CV_StsError, "Invalid tree links" );
749
750         CV_CALL( nodes[i] = icvCreateTreeCascadeNode() );
751         nodes[i]->stage = stage;
752         nodes[i]->idx = i;
753         nodes[i]->parent = (parent != -1 ) ? nodes[parent] : NULL;
754         nodes[i]->next = ( next != -1 ) ? nodes[i] : NULL;
755         nodes[i]->child = NULL;
756     }
757     for( i = 0; i < num; i++ )
758     {
759         if( nodes[i]->next )
760         {
761             (*splits)++;
762             nodes[i]->next = nodes[i+1];
763         }
764         if( nodes[i]->parent && nodes[i]->parent->child == NULL )
765         {
766             nodes[i]->parent->child = nodes[i];
767         }
768     }
769     ptr->root = nodes[0];
770     ptr->next_idx = num;
771
772     __END__;
773
774     cvFree( &nodes );
775
776     return (CvIntHaarClassifier*) ptr;
777 }
778
779
780 CvTreeCascadeNode* icvFindDeepestLeaves( CvTreeCascadeClassifier* tcc )
781 {
782     CvTreeCascadeNode* leaves;
783
784     //CV_FUNCNAME( "icvFindDeepestLeaves" );
785
786     __BEGIN__;
787
788     int level, cur_level;
789     CvTreeCascadeNode* ptr;
790     CvTreeCascadeNode* last;
791
792     leaves = last = NULL;
793
794     ptr = tcc->root;
795     level = -1;
796     cur_level = 0;
797
798     /* find leaves with maximal level */
799     while( ptr )
800     {
801         if( ptr->child ) { ptr = ptr->child; cur_level++; }
802         else
803         {
804             if( cur_level == level )
805             {
806                 last->next_same_level = ptr;
807                 ptr->next_same_level = NULL;
808                 last = ptr;
809             }
810             if( cur_level > level )
811             {
812                 level = cur_level;
813                 leaves = last = ptr;
814                 ptr->next_same_level = NULL;
815             }
816             while( ptr && ptr->next == NULL ) { ptr = ptr->parent; cur_level--; }
817             if( ptr ) ptr = ptr->next;
818         }
819     }
820
821     __END__;
822
823     return leaves;
824 }
825
826 /* End of file. */