1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
43 #define CV_MATCH_CHECK( status, cvFun ) \
46 if( status != CV_OK ) \
51 icvCalcTriAttr( const CvSeq * contour, CvPoint t2, CvPoint t1, int n1,
52 CvPoint t3, int n3, double *s, double *s_c,
53 double *h, double *a, double *b );
55 /*F///////////////////////////////////////////////////////////////////////////////////////
56 // Name: icvCreateContourTree
58 // Create binary tree representation for the contour
61 // contour - pointer to input contour object.
62 // storage - pointer to the current storage block
63 // tree - output pointer to the binary tree representation
64 // threshold - threshold for the binary tree building
68 icvCreateContourTree( const CvSeq * contour, CvMemStorage * storage,
69 CvContourTree ** tree, double threshold )
71 CvPoint *pt_p; /* pointer to previos points */
72 CvPoint *pt_n; /* pointer to next points */
73 CvPoint *pt1, *pt2; /* pointer to current points */
75 CvPoint t, tp1, tp2, tp3, tn1, tn2, tn3;
76 int lpt, flag, i, j, i_tree, j_1, j_3, i_buf;
77 double s, sp1, sp2, sn1, sn2, s_c, sp1_c, sp2_c, sn1_c, sn2_c, h, hp1, hp2, hn1, hn2,
78 a, ap1, ap2, an1, an2, b, bp1, bp2, bn1, bn2;
79 double a_s_c, a_sp1_c;
81 _CvTrianAttr **ptr_p, **ptr_n, **ptr1, **ptr2; /* pointers to pointers of triangles */
82 _CvTrianAttr *cur_adr;
84 int *num_p, *num_n, *num1, *num2; /* numbers of input contour points */
85 int nm, nmp1, nmp2, nmp3, nmn1, nmn2, nmn3;
86 int seq_flags = 1, i_end, prev_null, prev2_null;
92 _CvTrianAttr tree_one, tree_two, *tree_end, *tree_root;
96 assert( contour != NULL && contour->total >= 4 );
100 return CV_NULLPTR_ERR;
101 if( contour->total < 4 )
102 return CV_BADSIZE_ERR;
104 if( !CV_IS_SEQ_POLYGON( contour ))
105 return CV_BADFLAG_ERR;
108 /* Convert Sequence to array */
109 lpt = contour->total;
111 num_p = num_n = NULL;
112 ptr_p = ptr_n = ptr1 = ptr2 = NULL;
115 pt_p = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint ));
116 pt_n = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint ));
118 num_p = (int *) cvAlloc( lpt * sizeof( int ));
119 num_n = (int *) cvAlloc( lpt * sizeof( int ));
121 hearder_size = sizeof( CvContourTree );
122 seq_flags = CV_SEQ_POLYGON_TREE;
123 cvStartWriteSeq( seq_flags, hearder_size, sizeof( _CvTrianAttr ), storage, &writer );
125 ptr_p = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
126 ptr_n = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
128 memset( ptr_p, 0, lpt * sizeof( _CvTrianAttr * ));
129 memset( ptr_n, 0, lpt * sizeof( _CvTrianAttr * ));
131 if( pt_p == NULL || pt_n == NULL )
132 return CV_OUTOFMEM_ERR;
133 if( ptr_p == NULL || ptr_n == NULL )
134 return CV_OUTOFMEM_ERR;
136 /* write fild for the binary tree root */
137 /* start_writer = writer; */
139 tree_one.pt.x = tree_one.pt.y = 0;
142 tree_one.r1 = tree_one.r2 = 0;
143 tree_one.next_v1 = tree_one.next_v2 = tree_one.prev_v = NULL;
145 CV_WRITE_SEQ_ELEM( tree_one, writer );
146 tree_root = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
148 if( cvCvtSeqToArray( contour, (char *) pt_p ) == (char *) contour )
149 return CV_BADPOINT_ERR;
151 for( i = 0; i < lpt; i++ )
157 e = 20.; /* initial threshold value */
164 /* binary tree constraction */
202 CV_MATCH_CHECK( status,
203 icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a,
205 CV_MATCH_CHECK( status,
206 icvCalcTriAttr( contour, tp1, tp2, nmp2, t, nm, &sp1, &sp1_c, &hp1,
208 CV_MATCH_CHECK( status,
209 icvCalcTriAttr( contour, tp2, tp3, nmp3, tp1, nmp1, &sp2, &sp2_c, &hp2,
211 CV_MATCH_CHECK( status,
212 icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1,
217 prev_null = prev2_null = 0;
218 for( j = 0; j < i; j++ )
227 CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tn2, tn1, nmn1, tn3, nmn3,
228 &sn2, &sn2_c, &hn2, &an2, &bn2 ));
230 if( (s_c < sp1_c && s_c < sp2_c && s_c <= sn1_c && s_c <= sn2_c && s_c < e) ||
231 (s_c == sp1_c && s_c <= sp2_c || s_c == sp2_c && s_c <= sp1_c) && s_c <= sn1_c
232 && s_c <= sn2_c && s_c < e && j > 1 && prev2_null == 0 || (s_c < eps && j > 0
236 prev_null = prev2_null = 1;
237 if( s_c < threshold )
239 if( ptr1[j_1] == NULL && ptr1[j] == NULL )
242 ptr2[i_buf - 1] = NULL;
248 /* form next vertex */
250 tree_one.sign = (char) (CV_SIGN( s ));
253 tree_one.area = fabs( s );
254 tree_one.next_v1 = ptr1[j_1];
255 tree_one.next_v2 = ptr1[j];
257 CV_WRITE_SEQ_ELEM( tree_one, writer );
258 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
260 if( ptr1[j_1] != NULL )
261 ptr1[j_1]->prev_v = cur_adr;
262 if( ptr1[j] != NULL )
263 ptr1[j]->prev_v = cur_adr;
266 ptr2[i_buf - 1] = cur_adr;
269 tree_end = (_CvTrianAttr *) writer.ptr;
276 /* form next vertex */
279 tree_one.sign = (char) (CV_SIGN( s ));
280 tree_one.area = fabs( s );
283 tree_one.next_v1 = ptr1[j_1];
284 tree_one.next_v2 = ptr1[j];
286 CV_WRITE_SEQ_ELEM( tree_one, writer );
287 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
289 if( ptr1[j_1] != NULL )
290 ptr1[j_1]->prev_v = cur_adr;
291 if( ptr1[j] != NULL )
292 ptr1[j]->prev_v = cur_adr;
295 ptr2[i_buf - 1] = cur_adr;
305 /* the current triangle is'not LMIAT */
323 if( j != i - 1 || i_end == -1 )
324 ptr2[i_buf] = ptr1[j];
325 else if( i_end == 0 )
328 ptr2[i_buf] = tree_end;
330 num2[i_buf] = num1[j];
333 /* go to next vertex */
377 /* constract tree root */
379 return CV_BADFACTOR_ERR;
389 /* first pair of the triangles */
390 CV_MATCH_CHECK( status,
391 icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a, &b ));
392 CV_MATCH_CHECK( status,
393 icvCalcTriAttr( contour, tn2, tn1, nmn1, tp1, nmp1, &sn2, &sn2_c, &hn2,
395 /* second pair of the triangles */
396 CV_MATCH_CHECK( status,
397 icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1, &an1,
399 CV_MATCH_CHECK( status,
400 icvCalcTriAttr( contour, tp1, tn2, nmn2, t, nm, &sp1, &sp1_c, &hp1, &ap1,
403 a_s_c = fabs( s_c - sn2_c );
404 a_sp1_c = fabs( sp1_c - sn1_c );
406 if( a_s_c > a_sp1_c )
407 /* form child vertexs for the root */
410 tree_one.sign = (char) (CV_SIGN( s ));
411 tree_one.area = fabs( s );
414 tree_one.next_v1 = ptr2[3];
415 tree_one.next_v2 = ptr2[0];
418 tree_two.sign = (char) (CV_SIGN( sn2 ));
419 tree_two.area = fabs( sn2 );
420 tree_two.r1 = hn2 / an2;
421 tree_two.r2 = bn2 / an2;
422 tree_two.next_v1 = ptr2[1];
423 tree_two.next_v2 = ptr2[2];
425 CV_WRITE_SEQ_ELEM( tree_one, writer );
426 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
430 if( ptr2[3] != NULL )
431 ptr2[3]->prev_v = cur_adr;
432 if( ptr2[0] != NULL )
433 ptr2[0]->prev_v = cur_adr;
438 CV_WRITE_SEQ_ELEM( tree_two, writer );
439 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
441 if( ptr2[1] != NULL )
442 ptr2[1]->prev_v = cur_adr;
443 if( ptr2[2] != NULL )
444 ptr2[2]->prev_v = cur_adr;
454 CV_WRITE_SEQ_ELEM( tree_two, writer );
455 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
457 if( ptr2[1] != NULL )
458 ptr2[1]->prev_v = cur_adr;
459 if( ptr2[2] != NULL )
460 ptr2[2]->prev_v = cur_adr;
465 CV_WRITE_SEQ_ELEM( tree_one, writer );
466 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
468 if( ptr2[3] != NULL )
469 ptr2[3]->prev_v = cur_adr;
470 if( ptr2[0] != NULL )
471 ptr2[0]->prev_v = cur_adr;
483 tree_one.sign = (char) (CV_SIGN( sp1 ));
484 tree_one.area = fabs( sp1 );
485 tree_one.r1 = hp1 / ap1;
486 tree_one.r2 = bp1 / ap1;
487 tree_one.next_v1 = ptr2[2];
488 tree_one.next_v2 = ptr2[3];
491 tree_two.sign = (char) (CV_SIGN( sn1 ));
492 tree_two.area = fabs( sn1 );
493 tree_two.r1 = hn1 / an1;
494 tree_two.r2 = bn1 / an1;
495 tree_two.next_v1 = ptr2[0];
496 tree_two.next_v2 = ptr2[1];
498 CV_WRITE_SEQ_ELEM( tree_one, writer );
499 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
503 if( ptr2[2] != NULL )
504 ptr2[2]->prev_v = cur_adr;
505 if( ptr2[3] != NULL )
506 ptr2[3]->prev_v = cur_adr;
511 CV_WRITE_SEQ_ELEM( tree_two, writer );
512 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
514 if( ptr2[0] != NULL )
515 ptr2[0]->prev_v = cur_adr;
516 if( ptr2[1] != NULL )
517 ptr2[1]->prev_v = cur_adr;
527 CV_WRITE_SEQ_ELEM( tree_two, writer );
528 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
530 if( ptr2[0] != NULL )
531 ptr2[0]->prev_v = cur_adr;
532 if( ptr2[1] != NULL )
533 ptr2[1]->prev_v = cur_adr;
538 CV_WRITE_SEQ_ELEM( tree_one, writer );
539 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
541 if( ptr2[2] != NULL )
542 ptr2[2]->prev_v = cur_adr;
543 if( ptr2[3] != NULL )
544 ptr2[3]->prev_v = cur_adr;
556 s = cvContourArea( contour );
558 tree_root->pt = pt1[1];
560 tree_root->area = fabs( s );
563 tree_root->next_v1 = ptr1[0];
564 tree_root->next_v2 = ptr1[1];
565 tree_root->prev_v = NULL;
567 ptr1[0]->prev_v = (_CvTrianAttr *) tree_root;
568 ptr1[1]->prev_v = (_CvTrianAttr *) tree_root;
570 /* write binary tree root */
571 /* CV_WRITE_SEQ_ELEM (tree_one, start_writer); */
573 /* create Sequence hearder */
574 *((CvSeq **) tree) = cvEndWriteSeq( &writer );
575 /* write points for the main segment into sequence header */
576 (*tree)->p1 = pt1[0];
590 /****************************************************************************************\
592 triangle attributes calculations
594 \****************************************************************************************/
596 icvCalcTriAttr( const CvSeq * contour, CvPoint t2, CvPoint t1, int n1,
597 CvPoint t3, int n3, double *s, double *s_c,
598 double *h, double *a, double *b )
600 double x13, y13, x12, y12, l_base, nx, ny, qq;
607 qq = x13 * x13 + y13 * y13;
608 l_base = cvSqrt( (float) (qq) );
614 *h = nx * x12 + ny * y12;
616 *s = (*h) * l_base / 2.;
618 *b = nx * y12 - ny * x12;
621 /* calculate interceptive area */
622 *s_c = cvContourArea( contour, cvSlice(n1, n3+1));
636 /*F///////////////////////////////////////////////////////////////////////////////////////
637 // Name: cvCreateContourTree
639 // Create binary tree representation for the contour
642 // contour - pointer to input contour object.
643 // storage - pointer to the current storage block
644 // tree - output pointer to the binary tree representation
645 // threshold - threshold for the binary tree building
648 CV_IMPL CvContourTree*
649 cvCreateContourTree( const CvSeq* contour, CvMemStorage* storage, double threshold )
651 CvContourTree* tree = 0;
653 CV_FUNCNAME( "cvCreateContourTree" );
656 IPPI_CALL( icvCreateContourTree( contour, storage, &tree, threshold ));
665 /*F///////////////////////////////////////////////////////////////////////////////////////
666 // Name: icvContourFromContourTree
668 // reconstracts contour from binary tree representation
671 // tree - pointer to the input binary tree representation
672 // storage - pointer to the current storage block
673 // contour - pointer to output contour object.
674 // criteria - criteria for the definition threshold value
675 // for the contour reconstracting (level or precision)
678 cvContourFromContourTree( const CvContourTree* tree,
679 CvMemStorage* storage,
680 CvTermCriteria criteria )
683 _CvTrianAttr **ptr_buf = 0; /* pointer to the pointer's buffer */
693 char log_iter, log_eps;
694 int out_hearder_size;
695 _CvTrianAttr *tree_one = 0, tree_root; /* current vertex */
700 CV_FUNCNAME("cvContourFromContourTree");
705 CV_ERROR( CV_StsNullPtr, "" );
707 if( !CV_IS_SEQ_POLYGON_TREE( tree ))
708 CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR );
710 criteria = cvCheckTermCriteria( criteria, 0., 100 );
717 log_iter = (char) (criteria.type == CV_TERMCRIT_ITER ||
718 (criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS));
719 log_eps = (char) (criteria.type == CV_TERMCRIT_EPS ||
720 (criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS));
722 cvStartReadSeq( (CvSeq *) tree, &reader, 0 );
724 out_hearder_size = sizeof( CvContour );
726 seq_flags = CV_SEQ_POLYGON;
727 cvStartWriteSeq( seq_flags, out_hearder_size, sizeof( CvPoint ), storage, &writer );
729 ptr_buf = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
730 if( ptr_buf == NULL )
731 CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR );
734 level_buf = (int *) cvAlloc( lpt * (sizeof( int )));
736 if( level_buf == NULL )
737 CV_ERROR_FROM_STATUS( CV_OUTOFMEM_ERR );
740 memset( ptr_buf, 0, lpt * sizeof( _CvTrianAttr * ));
742 /* write the first tree root's point as a start point of the result contour */
743 CV_WRITE_SEQ_ELEM( tree->p1, writer );
744 /* write the second tree root"s point into buffer */
746 /* read the root of the tree */
747 CV_READ_SEQ_ELEM( tree_root, reader );
749 tree_one = &tree_root;
750 area_all = tree_one->area;
753 threshold = criteria.epsilon * area_all;
755 threshold = 10 * area_all;
758 level = criteria.max_iter;
762 /* contour from binary tree constraction */
765 if( tree_one != NULL && (cur_level <= level || tree_one->area >= threshold) )
766 /* go to left sub tree for the vertex and save pointer to the right vertex */
767 /* into the buffer */
769 ptr_buf[i_buf] = tree_one;
772 level_buf[i_buf] = cur_level;
776 tree_one = tree_one->next_v1;
783 CvPoint pt = ptr_buf[i_buf]->pt;
784 CV_WRITE_SEQ_ELEM( pt, writer );
785 tree_one = ptr_buf[i_buf]->next_v2;
788 cur_level = level_buf[i_buf] + 1;
794 contour = cvEndWriteSeq( &writer );
795 cvBoundingRect( contour, 1 );
800 cvFree( &level_buf );