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.
47 // check_slice (and/or check) seem(s) to be broken, or this is a bug in function
48 // (or its inability to handle possible self-intersections in the generated contours).
50 // At least, if // return TotalErrors;
51 // is uncommented in check_slice, the test fails easily.
52 // So, now (and it looks like since 0.9.6)
53 // we only check that the set of vertices of the approximated polygon is
54 // a subset of vertices of the original contour.
57 class CV_ApproxPolyTest : public CvTest
63 //int write_default_params(CvFileStorage* fs);
66 //int read_params( CvFileStorage* fs );
68 int check_slice( CvPoint StartPt, CvPoint EndPt,
69 CvSeqReader* SrcReader, float Eps,
71 int check( CvSeq* SrcSeq, CvSeq* DstSeq, float Eps );
73 bool get_contour( int /*type*/, CvSeq** Seq, int* d,
74 CvMemStorage* storage );
80 CV_ApproxPolyTest::CV_ApproxPolyTest():
81 CvTest( "contour-approx", "cvApproxPoly" )
83 support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
87 CV_ApproxPolyTest::~CV_ApproxPolyTest()
93 void CV_ApproxPolyTest::clear()
99 /*int CV_ApproxPolyTest::write_default_params( CvFileStorage* fs )
101 CvTest::write_default_params( fs );
102 if( ts->get_testing_mode() != CvTS::TIMING_MODE )
104 write_param( fs, "test_case_count", test_case_count );
110 int CV_ApproxPolyTest::read_params( CvFileStorage* fs )
112 int code = CvTest::read_params( fs );
116 test_case_count = cvReadInt( find_param( fs, "test_case_count" ), test_case_count );
117 min_log_size = cvTsClipInt( min_log_size, 1, 10 );
122 bool CV_ApproxPolyTest::get_contour( int /*type*/, CvSeq** Seq, int* d,
123 CvMemStorage* storage )
125 CvRNG* rng = ts->get_rng();
126 int max_x = INT_MIN, max_y = INT_MIN, min_x = INT_MAX, min_y = INT_MAX;
129 int total = cvTsRandInt(rng) % 1000 + 1;
132 double deg_to_rad = CV_PI/180.;
135 center.x = cvTsRandInt( rng ) % 1000;
136 center.y = cvTsRandInt( rng ) % 1000;
137 radius = cvTsRandInt( rng ) % 1000;
138 angle = cvTsRandInt( rng ) % 360;
140 seq = cvCreateSeq( CV_SEQ_POLYGON, sizeof(CvContour), sizeof(CvPoint), storage );
142 for( i = 0; i < total; i++ )
144 int d_radius = cvTsRandInt( rng ) % 10 - 5;
145 int d_angle = 360/total;//cvTsRandInt( rng ) % 10 - 5;
146 pt.x = cvRound( center.x + radius*cos(angle*deg_to_rad));
147 pt.y = cvRound( center.x - radius*sin(angle*deg_to_rad));
150 cvSeqPush( seq, &pt );
152 max_x = MAX( max_x, pt.x );
153 max_y = MAX( max_y, pt.y );
155 min_x = MIN( min_x, pt.x );
156 min_y = MIN( min_y, pt.y );
159 *d = (max_x - min_x)*(max_x - min_x) + (max_y - min_y)*(max_y - min_y);
165 int CV_ApproxPolyTest::check_slice( CvPoint StartPt, CvPoint EndPt,
166 CvSeqReader* SrcReader, float Eps,
181 int j, TotalErrors = 0;
183 ////////////////////////////////
184 if( SrcReader == NULL )
190 ///////// init line ////////////
193 dx = (double)StartPt.x - (double)EndPt.x;
194 dy = (double)StartPt.y - (double)EndPt.y;
196 if( ( dx == 0 ) && ( dy == 0 ) ) flag = false;
201 C = dy * (double)StartPt.x - dx * (double)StartPt.y;
202 Sq = sqrt( A*A + B*B );
209 /////// find start point and check distance ////////
210 for( j = *_j; j < Count; j++ )
212 CV_READ_SEQ_ELEM( Pt, *SrcReader );
213 if( StartPt.x == Pt.x && StartPt.y == Pt.y ) break;
216 if( flag ) dist = sin_a * Pt.y + cos_a * Pt.x - d;
217 else dist = sqrt( (double)(EndPt.y - Pt.y)*(EndPt.y - Pt.y) + (EndPt.x - Pt.x)*(EndPt.x - Pt.x) );
218 if( dist > Eps ) TotalErrors++;
224 //return TotalErrors;
229 int CV_ApproxPolyTest::check( CvSeq* SrcSeq, CvSeq* DstSeq, float Eps )
232 CvSeqReader DstReader;
233 CvSeqReader SrcReader;
234 CvPoint StartPt, EndPt;
241 assert( SrcSeq && DstSeq );
243 ////////// init ////////////////////
244 Count = SrcSeq->total;
246 cvStartReadSeq( DstSeq, &DstReader, 0 );
247 cvStartReadSeq( SrcSeq, &SrcReader, 0 );
249 CV_READ_SEQ_ELEM( StartPt, DstReader );
250 for( i = 0 ; i < Count ; )
252 CV_READ_SEQ_ELEM( EndPt, SrcReader );
254 if( StartPt.x == EndPt.x && StartPt.y == EndPt.y ) break;
257 ///////// start ////////////////
258 for( i = 1, j = 0 ; i <= DstSeq->total ; )
260 ///////// read slice ////////////
263 CV_READ_SEQ_ELEM( StartPt, DstReader );
266 TotalErrors += check_slice( StartPt, EndPt, &SrcReader, Eps, &j, Count );
274 } // for( int i = 0 ; i < DstSeq->total ; i++ )
280 //extern CvTestContourGenerator cvTsTestContours[];
282 void CV_ApproxPolyTest::run( int /*start_from*/ )
285 CvMemStorage* storage = 0;
286 ////////////// Variables ////////////////
287 int IntervalsCount = 10;
289 //CvTestContourGenerator Cont;
290 CvSeq* SrcSeq = NULL;
293 float dDiam, Eps, EpsStep;
295 for( int i = 0; i < 30; i++ )
299 ts->update_context( this, i, false );
301 ///////////////////// init contour /////////
303 while( sqrt(dDiam) / IntervalsCount == 0 )
306 cvReleaseMemStorage(&storage);
308 storage = cvCreateMemStorage( 0 );
309 if( get_contour( 0, &SrcSeq, &iDiam, storage ) )
310 dDiam = (float)iDiam;
312 dDiam = (float)sqrt( dDiam );
314 storage = SrcSeq->storage;
316 ////////////////// test /////////////
317 EpsStep = dDiam / IntervalsCount ;
318 for( Eps = EpsStep ; Eps < dDiam ; Eps += EpsStep )
320 cvSaveMemStoragePos( storage, &pos );
322 ////////// call function ////////////
323 DstSeq = cvApproxPoly( SrcSeq, SrcSeq->header_size, storage,
324 CV_POLY_APPROX_DP, Eps );
328 ts->printf( CvTS::LOG,
329 "cvApproxPoly returned NULL for contour #%d, espilon = %g\n", i, Eps );
330 code = CvTS::FAIL_INVALID_OUTPUT;
332 } // if( DstSeq == NULL )
334 code = check( SrcSeq, DstSeq, Eps );
337 ts->printf( CvTS::LOG,
338 "Incorrect result for the contour #%d approximated with epsilon=%g\n", i, Eps );
339 code = CvTS::FAIL_BAD_ACCURACY;
343 cvRestoreMemStoragePos( storage, &pos );
344 } // for( Eps = EpsStep ; Eps <= Diam ; Eps += EpsStep )
346 ///////////// free memory ///////////////////
347 cvReleaseMemStorage(&storage);
348 } // for( int i = 0; NULL != ( Cont = Contours[i] ) ; i++ )
351 cvReleaseMemStorage(&storage);
354 ts->set_failed_test_info( code );
358 CV_ApproxPolyTest contour_approx;