Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgproc/test/test_approxpoly.cpp
16354 views
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
#include "test_precomp.hpp"
43
44
namespace opencv_test { namespace {
45
46
//
47
// TODO!!!:
48
// check_slice (and/or check) seem(s) to be broken, or this is a bug in function
49
// (or its inability to handle possible self-intersections in the generated contours).
50
//
51
// At least, if // return TotalErrors;
52
// is uncommented in check_slice, the test fails easily.
53
// So, now (and it looks like since 0.9.6)
54
// we only check that the set of vertices of the approximated polygon is
55
// a subset of vertices of the original contour.
56
//
57
58
class CV_ApproxPolyTest : public cvtest::BaseTest
59
{
60
public:
61
CV_ApproxPolyTest();
62
~CV_ApproxPolyTest();
63
void clear();
64
//int write_default_params(CvFileStorage* fs);
65
66
protected:
67
//int read_params( CvFileStorage* fs );
68
69
int check_slice( CvPoint StartPt, CvPoint EndPt,
70
CvSeqReader* SrcReader, float Eps,
71
int* j, int Count );
72
int check( CvSeq* SrcSeq, CvSeq* DstSeq, float Eps );
73
74
bool get_contour( int /*type*/, CvSeq** Seq, int* d,
75
CvMemStorage* storage );
76
77
void run(int);
78
};
79
80
81
CV_ApproxPolyTest::CV_ApproxPolyTest()
82
{
83
}
84
85
86
CV_ApproxPolyTest::~CV_ApproxPolyTest()
87
{
88
clear();
89
}
90
91
92
void CV_ApproxPolyTest::clear()
93
{
94
cvtest::BaseTest::clear();
95
}
96
97
98
/*int CV_ApproxPolyTest::write_default_params( CvFileStorage* fs )
99
{
100
cvtest::BaseTest::write_default_params( fs );
101
if( ts->get_testing_mode() != cvtest::TS::TIMING_MODE )
102
{
103
write_param( fs, "test_case_count", test_case_count );
104
}
105
return 0;
106
}
107
108
109
int CV_ApproxPolyTest::read_params( CvFileStorage* fs )
110
{
111
int code = cvtest::BaseTest::read_params( fs );
112
if( code < 0 )
113
return code;
114
115
test_case_count = cvReadInt( find_param( fs, "test_case_count" ), test_case_count );
116
min_log_size = cvtest::clipInt( min_log_size, 1, 10 );
117
return 0;
118
}*/
119
120
121
bool CV_ApproxPolyTest::get_contour( int /*type*/, CvSeq** Seq, int* d,
122
CvMemStorage* storage )
123
{
124
RNG& rng = ts->get_rng();
125
int max_x = INT_MIN, max_y = INT_MIN, min_x = INT_MAX, min_y = INT_MAX;
126
int i;
127
CvSeq* seq;
128
int total = cvtest::randInt(rng) % 1000 + 1;
129
Point center;
130
int radius, angle;
131
double deg_to_rad = CV_PI/180.;
132
Point pt;
133
134
center.x = cvtest::randInt( rng ) % 1000;
135
center.y = cvtest::randInt( rng ) % 1000;
136
radius = cvtest::randInt( rng ) % 1000;
137
angle = cvtest::randInt( rng ) % 360;
138
139
seq = cvCreateSeq( CV_SEQ_POLYGON, sizeof(CvContour), sizeof(CvPoint), storage );
140
141
for( i = 0; i < total; i++ )
142
{
143
int d_radius = cvtest::randInt( rng ) % 10 - 5;
144
int d_angle = 360/total;//cvtest::randInt( rng ) % 10 - 5;
145
pt.x = cvRound( center.x + radius*cos(angle*deg_to_rad));
146
pt.y = cvRound( center.x - radius*sin(angle*deg_to_rad));
147
radius += d_radius;
148
angle += d_angle;
149
cvSeqPush( seq, &pt );
150
151
max_x = MAX( max_x, pt.x );
152
max_y = MAX( max_y, pt.y );
153
154
min_x = MIN( min_x, pt.x );
155
min_y = MIN( min_y, pt.y );
156
}
157
158
*d = (max_x - min_x)*(max_x - min_x) + (max_y - min_y)*(max_y - min_y);
159
*Seq = seq;
160
return true;
161
}
162
163
164
int CV_ApproxPolyTest::check_slice( CvPoint StartPt, CvPoint EndPt,
165
CvSeqReader* SrcReader, float Eps,
166
int* _j, int Count )
167
{
168
///////////
169
Point Pt;
170
///////////
171
bool flag;
172
double dy,dx;
173
double A,B,C;
174
double Sq;
175
double sin_a = 0;
176
double cos_a = 0;
177
double d = 0;
178
double dist;
179
///////////
180
int j, TotalErrors = 0;
181
182
////////////////////////////////
183
if( SrcReader == NULL )
184
{
185
assert( false );
186
return 0;
187
}
188
189
///////// init line ////////////
190
flag = true;
191
192
dx = (double)StartPt.x - (double)EndPt.x;
193
dy = (double)StartPt.y - (double)EndPt.y;
194
195
if( ( dx == 0 ) && ( dy == 0 ) ) flag = false;
196
else
197
{
198
A = -dy;
199
B = dx;
200
C = dy * (double)StartPt.x - dx * (double)StartPt.y;
201
Sq = sqrt( A*A + B*B );
202
203
sin_a = B/Sq;
204
cos_a = A/Sq;
205
d = C/Sq;
206
}
207
208
/////// find start point and check distance ////////
209
for( j = *_j; j < Count; j++ )
210
{
211
{ CvPoint pt_ = CV_STRUCT_INITIALIZER; CV_READ_SEQ_ELEM(pt_, *SrcReader); Pt = pt_; }
212
if( StartPt.x == Pt.x && StartPt.y == Pt.y ) break;
213
else
214
{
215
if( flag ) dist = sin_a * Pt.y + cos_a * Pt.x - d;
216
else dist = sqrt( (double)(EndPt.y - Pt.y)*(EndPt.y - Pt.y) + (EndPt.x - Pt.x)*(EndPt.x - Pt.x) );
217
if( dist > Eps ) TotalErrors++;
218
}
219
}
220
221
*_j = j;
222
223
//return TotalErrors;
224
return 0;
225
}
226
227
228
int CV_ApproxPolyTest::check( CvSeq* SrcSeq, CvSeq* DstSeq, float Eps )
229
{
230
//////////
231
CvSeqReader DstReader;
232
CvSeqReader SrcReader;
233
CvPoint StartPt = {0, 0}, EndPt = {0, 0};
234
///////////
235
int TotalErrors = 0;
236
///////////
237
int Count;
238
int i,j;
239
240
assert( SrcSeq && DstSeq );
241
242
////////// init ////////////////////
243
Count = SrcSeq->total;
244
245
cvStartReadSeq( DstSeq, &DstReader, 0 );
246
cvStartReadSeq( SrcSeq, &SrcReader, 0 );
247
248
CV_READ_SEQ_ELEM( StartPt, DstReader );
249
for( i = 0 ; i < Count ; )
250
{
251
CV_READ_SEQ_ELEM( EndPt, SrcReader );
252
i++;
253
if( StartPt.x == EndPt.x && StartPt.y == EndPt.y ) break;
254
}
255
256
///////// start ////////////////
257
for( i = 1, j = 0 ; i <= DstSeq->total ; )
258
{
259
///////// read slice ////////////
260
EndPt.x = StartPt.x;
261
EndPt.y = StartPt.y;
262
CV_READ_SEQ_ELEM( StartPt, DstReader );
263
i++;
264
265
TotalErrors += check_slice( StartPt, EndPt, &SrcReader, Eps, &j, Count );
266
267
if( j > Count )
268
{
269
TotalErrors++;
270
return TotalErrors;
271
} //if( !flag )
272
273
} // for( int i = 0 ; i < DstSeq->total ; i++ )
274
275
return TotalErrors;
276
}
277
278
279
//extern CvTestContourGenerator cvTsTestContours[];
280
281
void CV_ApproxPolyTest::run( int /*start_from*/ )
282
{
283
int code = cvtest::TS::OK;
284
CvMemStorage* storage = 0;
285
////////////// Variables ////////////////
286
int IntervalsCount = 10;
287
///////////
288
//CvTestContourGenerator Cont;
289
CvSeq* SrcSeq = NULL;
290
CvSeq* DstSeq;
291
int iDiam;
292
float dDiam, Eps, EpsStep;
293
294
for( int i = 0; i < 30; i++ )
295
{
296
CvMemStoragePos pos;
297
298
ts->update_context( this, i, false );
299
300
///////////////////// init contour /////////
301
dDiam = 0;
302
while( sqrt(dDiam) / IntervalsCount == 0 )
303
{
304
if( storage != 0 )
305
cvReleaseMemStorage(&storage);
306
307
storage = cvCreateMemStorage( 0 );
308
if( get_contour( 0, &SrcSeq, &iDiam, storage ) )
309
dDiam = (float)iDiam;
310
}
311
dDiam = (float)sqrt( dDiam );
312
313
storage = SrcSeq->storage;
314
315
////////////////// test /////////////
316
EpsStep = dDiam / IntervalsCount ;
317
for( Eps = EpsStep ; Eps < dDiam ; Eps += EpsStep )
318
{
319
cvSaveMemStoragePos( storage, &pos );
320
321
////////// call function ////////////
322
DstSeq = cvApproxPoly( SrcSeq, SrcSeq->header_size, storage,
323
CV_POLY_APPROX_DP, Eps );
324
325
if( DstSeq == NULL )
326
{
327
ts->printf( cvtest::TS::LOG,
328
"cvApproxPoly returned NULL for contour #%d, espilon = %g\n", i, Eps );
329
code = cvtest::TS::FAIL_INVALID_OUTPUT;
330
goto _exit_;
331
} // if( DstSeq == NULL )
332
333
code = check( SrcSeq, DstSeq, Eps );
334
if( code != 0 )
335
{
336
ts->printf( cvtest::TS::LOG,
337
"Incorrect result for the contour #%d approximated with epsilon=%g\n", i, Eps );
338
code = cvtest::TS::FAIL_BAD_ACCURACY;
339
goto _exit_;
340
}
341
342
cvRestoreMemStoragePos( storage, &pos );
343
} // for( Eps = EpsStep ; Eps <= Diam ; Eps += EpsStep )
344
345
///////////// free memory ///////////////////
346
cvReleaseMemStorage(&storage);
347
} // for( int i = 0; NULL != ( Cont = Contours[i] ) ; i++ )
348
349
_exit_:
350
cvReleaseMemStorage(&storage);
351
352
if( code < 0 )
353
ts->set_failed_test_info( code );
354
}
355
356
TEST(Imgproc_ApproxPoly, accuracy) { CV_ApproxPolyTest test; test.safe_run(); }
357
358
}} // namespace
359
360