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_POINT_SET( 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)) &&
232 s_c <= sn1_c && s_c <= sn2_c && s_c < e && j > 1 && prev2_null == 0) ||
233 (s_c < eps && j > 0 && prev_null == 0) )
235 prev_null = prev2_null = 1;
236 if( s_c < threshold )
238 if( ptr1[j_1] == NULL && ptr1[j] == NULL )
241 ptr2[i_buf - 1] = NULL;
247 /* form next vertex */
249 tree_one.sign = (char) (CV_SIGN( s ));
252 tree_one.area = fabs( s );
253 tree_one.next_v1 = ptr1[j_1];
254 tree_one.next_v2 = ptr1[j];
256 CV_WRITE_SEQ_ELEM( tree_one, writer );
257 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
259 if( ptr1[j_1] != NULL )
260 ptr1[j_1]->prev_v = cur_adr;
261 if( ptr1[j] != NULL )
262 ptr1[j]->prev_v = cur_adr;
265 ptr2[i_buf - 1] = cur_adr;
268 tree_end = (_CvTrianAttr *) writer.ptr;
275 /* form next vertex */
278 tree_one.sign = (char) (CV_SIGN( s ));
279 tree_one.area = fabs( s );
282 tree_one.next_v1 = ptr1[j_1];
283 tree_one.next_v2 = ptr1[j];
285 CV_WRITE_SEQ_ELEM( tree_one, writer );
286 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
288 if( ptr1[j_1] != NULL )
289 ptr1[j_1]->prev_v = cur_adr;
290 if( ptr1[j] != NULL )
291 ptr1[j]->prev_v = cur_adr;
294 ptr2[i_buf - 1] = cur_adr;
304 /* the current triangle is'not LMIAT */
322 if( j != i - 1 || i_end == -1 )
323 ptr2[i_buf] = ptr1[j];
324 else if( i_end == 0 )
327 ptr2[i_buf] = tree_end;
329 num2[i_buf] = num1[j];
332 /* go to next vertex */
376 /* constract tree root */
378 return CV_BADFACTOR_ERR;
388 /* first pair of the triangles */
389 CV_MATCH_CHECK( status,
390 icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a, &b ));
391 CV_MATCH_CHECK( status,
392 icvCalcTriAttr( contour, tn2, tn1, nmn1, tp1, nmp1, &sn2, &sn2_c, &hn2,
394 /* second pair of the triangles */
395 CV_MATCH_CHECK( status,
396 icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1, &an1,
398 CV_MATCH_CHECK( status,
399 icvCalcTriAttr( contour, tp1, tn2, nmn2, t, nm, &sp1, &sp1_c, &hp1, &ap1,
402 a_s_c = fabs( s_c - sn2_c );
403 a_sp1_c = fabs( sp1_c - sn1_c );
405 if( a_s_c > a_sp1_c )
406 /* form child vertexs for the root */
409 tree_one.sign = (char) (CV_SIGN( s ));
410 tree_one.area = fabs( s );
413 tree_one.next_v1 = ptr2[3];
414 tree_one.next_v2 = ptr2[0];
417 tree_two.sign = (char) (CV_SIGN( sn2 ));
418 tree_two.area = fabs( sn2 );
419 tree_two.r1 = hn2 / an2;
420 tree_two.r2 = bn2 / an2;
421 tree_two.next_v1 = ptr2[1];
422 tree_two.next_v2 = ptr2[2];
424 CV_WRITE_SEQ_ELEM( tree_one, writer );
425 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
429 if( ptr2[3] != NULL )
430 ptr2[3]->prev_v = cur_adr;
431 if( ptr2[0] != NULL )
432 ptr2[0]->prev_v = cur_adr;
437 CV_WRITE_SEQ_ELEM( tree_two, writer );
438 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
440 if( ptr2[1] != NULL )
441 ptr2[1]->prev_v = cur_adr;
442 if( ptr2[2] != NULL )
443 ptr2[2]->prev_v = cur_adr;
453 CV_WRITE_SEQ_ELEM( tree_two, writer );
454 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
456 if( ptr2[1] != NULL )
457 ptr2[1]->prev_v = cur_adr;
458 if( ptr2[2] != NULL )
459 ptr2[2]->prev_v = cur_adr;
464 CV_WRITE_SEQ_ELEM( tree_one, writer );
465 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
467 if( ptr2[3] != NULL )
468 ptr2[3]->prev_v = cur_adr;
469 if( ptr2[0] != NULL )
470 ptr2[0]->prev_v = cur_adr;
482 tree_one.sign = (char) (CV_SIGN( sp1 ));
483 tree_one.area = fabs( sp1 );
484 tree_one.r1 = hp1 / ap1;
485 tree_one.r2 = bp1 / ap1;
486 tree_one.next_v1 = ptr2[2];
487 tree_one.next_v2 = ptr2[3];
490 tree_two.sign = (char) (CV_SIGN( sn1 ));
491 tree_two.area = fabs( sn1 );
492 tree_two.r1 = hn1 / an1;
493 tree_two.r2 = bn1 / an1;
494 tree_two.next_v1 = ptr2[0];
495 tree_two.next_v2 = ptr2[1];
497 CV_WRITE_SEQ_ELEM( tree_one, writer );
498 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
502 if( ptr2[2] != NULL )
503 ptr2[2]->prev_v = cur_adr;
504 if( ptr2[3] != NULL )
505 ptr2[3]->prev_v = cur_adr;
510 CV_WRITE_SEQ_ELEM( tree_two, writer );
511 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
513 if( ptr2[0] != NULL )
514 ptr2[0]->prev_v = cur_adr;
515 if( ptr2[1] != NULL )
516 ptr2[1]->prev_v = cur_adr;
526 CV_WRITE_SEQ_ELEM( tree_two, writer );
527 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
529 if( ptr2[0] != NULL )
530 ptr2[0]->prev_v = cur_adr;
531 if( ptr2[1] != NULL )
532 ptr2[1]->prev_v = cur_adr;
537 CV_WRITE_SEQ_ELEM( tree_one, writer );
538 cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
540 if( ptr2[2] != NULL )
541 ptr2[2]->prev_v = cur_adr;
542 if( ptr2[3] != NULL )
543 ptr2[3]->prev_v = cur_adr;
555 s = cvContourArea( contour );
557 tree_root->pt = pt1[1];
559 tree_root->area = fabs( s );
562 tree_root->next_v1 = ptr1[0];
563 tree_root->next_v2 = ptr1[1];
564 tree_root->prev_v = NULL;
566 ptr1[0]->prev_v = (_CvTrianAttr *) tree_root;
567 ptr1[1]->prev_v = (_CvTrianAttr *) tree_root;
569 /* write binary tree root */
570 /* CV_WRITE_SEQ_ELEM (tree_one, start_writer); */
572 /* create Sequence hearder */
573 *((CvSeq **) tree) = cvEndWriteSeq( &writer );
574 /* write points for the main segment into sequence header */
575 (*tree)->p1 = pt1[0];
589 /****************************************************************************************\
591 triangle attributes calculations
593 \****************************************************************************************/
595 icvCalcTriAttr( const CvSeq * contour, CvPoint t2, CvPoint t1, int n1,
596 CvPoint t3, int n3, double *s, double *s_c,
597 double *h, double *a, double *b )
599 double x13, y13, x12, y12, l_base, nx, ny, qq;
606 qq = x13 * x13 + y13 * y13;
607 l_base = cvSqrt( (float) (qq) );
613 *h = nx * x12 + ny * y12;
615 *s = (*h) * l_base / 2.;
617 *b = nx * y12 - ny * x12;
620 /* calculate interceptive area */
621 *s_c = cvContourArea( contour, cvSlice(n1, n3+1));
635 /*F///////////////////////////////////////////////////////////////////////////////////////
636 // Name: cvCreateContourTree
638 // Create binary tree representation for the contour
641 // contour - pointer to input contour object.
642 // storage - pointer to the current storage block
643 // tree - output pointer to the binary tree representation
644 // threshold - threshold for the binary tree building
647 CV_IMPL CvContourTree*
648 cvCreateContourTree( const CvSeq* contour, CvMemStorage* storage, double threshold )
650 CvContourTree* tree = 0;
652 IPPI_CALL( icvCreateContourTree( contour, storage, &tree, threshold ));
658 /*F///////////////////////////////////////////////////////////////////////////////////////
659 // Name: icvContourFromContourTree
661 // reconstracts contour from binary tree representation
664 // tree - pointer to the input binary tree representation
665 // storage - pointer to the current storage block
666 // contour - pointer to output contour object.
667 // criteria - criteria for the definition threshold value
668 // for the contour reconstracting (level or precision)
671 cvContourFromContourTree( const CvContourTree* tree,
672 CvMemStorage* storage,
673 CvTermCriteria criteria )
676 _CvTrianAttr **ptr_buf = 0; /* pointer to the pointer's buffer */
686 char log_iter, log_eps;
687 int out_hearder_size;
688 _CvTrianAttr *tree_one = 0, tree_root; /* current vertex */
693 CV_FUNCNAME("cvContourFromContourTree");
698 CV_ERROR( CV_StsNullPtr, "" );
700 if( !CV_IS_SEQ_POLYGON_TREE( tree ))
701 CV_ERROR( CV_StsBadArg, "" );
703 criteria = cvCheckTermCriteria( criteria, 0., 100 );
710 log_iter = (char) (criteria.type == CV_TERMCRIT_ITER ||
711 (criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS));
712 log_eps = (char) (criteria.type == CV_TERMCRIT_EPS ||
713 (criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS));
715 cvStartReadSeq( (CvSeq *) tree, &reader, 0 );
717 out_hearder_size = sizeof( CvContour );
719 seq_flags = CV_SEQ_POLYGON;
720 cvStartWriteSeq( seq_flags, out_hearder_size, sizeof( CvPoint ), storage, &writer );
722 ptr_buf = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
724 level_buf = (int *) cvAlloc( lpt * (sizeof( int )));
726 memset( ptr_buf, 0, lpt * sizeof( _CvTrianAttr * ));
728 /* write the first tree root's point as a start point of the result contour */
729 CV_WRITE_SEQ_ELEM( tree->p1, writer );
730 /* write the second tree root"s point into buffer */
732 /* read the root of the tree */
733 CV_READ_SEQ_ELEM( tree_root, reader );
735 tree_one = &tree_root;
736 area_all = tree_one->area;
739 threshold = criteria.epsilon * area_all;
741 threshold = 10 * area_all;
744 level = criteria.max_iter;
748 /* contour from binary tree constraction */
751 if( tree_one != NULL && (cur_level <= level || tree_one->area >= threshold) )
752 /* go to left sub tree for the vertex and save pointer to the right vertex */
753 /* into the buffer */
755 ptr_buf[i_buf] = tree_one;
758 level_buf[i_buf] = cur_level;
762 tree_one = tree_one->next_v1;
769 CvPoint pt = ptr_buf[i_buf]->pt;
770 CV_WRITE_SEQ_ELEM( pt, writer );
771 tree_one = ptr_buf[i_buf]->next_v2;
774 cur_level = level_buf[i_buf] + 1;
780 contour = cvEndWriteSeq( &writer );
781 cvBoundingRect( contour, 1 );
786 cvFree( &level_buf );