Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgproc/test/test_imgwarp.cpp
16339 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
class CV_ImgWarpBaseTest : public cvtest::ArrayTest
47
{
48
public:
49
CV_ImgWarpBaseTest( bool warp_matrix );
50
51
protected:
52
int read_params( CvFileStorage* fs );
53
int prepare_test_case( int test_case_idx );
54
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
55
void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
56
void fill_array( int test_case_idx, int i, int j, Mat& arr );
57
58
int interpolation;
59
int max_interpolation;
60
double spatial_scale_zoom, spatial_scale_decimate;
61
};
62
63
64
CV_ImgWarpBaseTest::CV_ImgWarpBaseTest( bool warp_matrix )
65
{
66
test_array[INPUT].push_back(NULL);
67
if( warp_matrix )
68
test_array[INPUT].push_back(NULL);
69
test_array[INPUT_OUTPUT].push_back(NULL);
70
test_array[REF_INPUT_OUTPUT].push_back(NULL);
71
max_interpolation = 5;
72
interpolation = 0;
73
element_wise_relative_error = false;
74
spatial_scale_zoom = 0.01;
75
spatial_scale_decimate = 0.005;
76
}
77
78
79
int CV_ImgWarpBaseTest::read_params( CvFileStorage* fs )
80
{
81
int code = cvtest::ArrayTest::read_params( fs );
82
return code;
83
}
84
85
86
void CV_ImgWarpBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
87
{
88
cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
89
if( CV_MAT_DEPTH(type) == CV_32F )
90
{
91
low = Scalar::all(-10.);
92
high = Scalar::all(10);
93
}
94
}
95
96
97
void CV_ImgWarpBaseTest::get_test_array_types_and_sizes( int test_case_idx,
98
vector<vector<Size> >& sizes, vector<vector<int> >& types )
99
{
100
RNG& rng = ts->get_rng();
101
int depth = cvtest::randInt(rng) % 3;
102
int cn = cvtest::randInt(rng) % 3 + 1;
103
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
104
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F;
105
cn += cn == 2;
106
107
types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
108
if( test_array[INPUT].size() > 1 )
109
types[INPUT][1] = cvtest::randInt(rng) & 1 ? CV_32FC1 : CV_64FC1;
110
111
interpolation = cvtest::randInt(rng) % max_interpolation;
112
}
113
114
115
void CV_ImgWarpBaseTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
116
{
117
if( i != INPUT || j != 0 )
118
cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
119
}
120
121
int CV_ImgWarpBaseTest::prepare_test_case( int test_case_idx )
122
{
123
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
124
Mat& img = test_mat[INPUT][0];
125
int i, j, cols = img.cols;
126
int type = img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
127
double scale = depth == CV_16U ? 1000. : 255.*0.5;
128
double space_scale = spatial_scale_decimate;
129
vector<float> buffer(img.cols*cn);
130
131
if( code <= 0 )
132
return code;
133
134
if( test_mat[INPUT_OUTPUT][0].cols >= img.cols &&
135
test_mat[INPUT_OUTPUT][0].rows >= img.rows )
136
space_scale = spatial_scale_zoom;
137
138
for( i = 0; i < img.rows; i++ )
139
{
140
uchar* ptr = img.ptr(i);
141
switch( cn )
142
{
143
case 1:
144
for( j = 0; j < cols; j++ )
145
buffer[j] = (float)((sin((i+1)*space_scale)*sin((j+1)*space_scale)+1.)*scale);
146
break;
147
case 2:
148
for( j = 0; j < cols; j++ )
149
{
150
buffer[j*2] = (float)((sin((i+1)*space_scale)+1.)*scale);
151
buffer[j*2+1] = (float)((sin((i+j)*space_scale)+1.)*scale);
152
}
153
break;
154
case 3:
155
for( j = 0; j < cols; j++ )
156
{
157
buffer[j*3] = (float)((sin((i+1)*space_scale)+1.)*scale);
158
buffer[j*3+1] = (float)((sin(j*space_scale)+1.)*scale);
159
buffer[j*3+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
160
}
161
break;
162
case 4:
163
for( j = 0; j < cols; j++ )
164
{
165
buffer[j*4] = (float)((sin((i+1)*space_scale)+1.)*scale);
166
buffer[j*4+1] = (float)((sin(j*space_scale)+1.)*scale);
167
buffer[j*4+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
168
buffer[j*4+3] = (float)((sin((i-j)*space_scale)+1.)*scale);
169
}
170
break;
171
default:
172
assert(0);
173
}
174
175
/*switch( depth )
176
{
177
case CV_8U:
178
for( j = 0; j < cols*cn; j++ )
179
ptr[j] = (uchar)cvRound(buffer[j]);
180
break;
181
case CV_16U:
182
for( j = 0; j < cols*cn; j++ )
183
((ushort*)ptr)[j] = (ushort)cvRound(buffer[j]);
184
break;
185
case CV_32F:
186
for( j = 0; j < cols*cn; j++ )
187
((float*)ptr)[j] = (float)buffer[j];
188
break;
189
default:
190
assert(0);
191
}*/
192
cv::Mat src(1, cols*cn, CV_32F, &buffer[0]);
193
cv::Mat dst(1, cols*cn, depth, ptr);
194
src.convertTo(dst, dst.type());
195
}
196
197
return code;
198
}
199
200
201
/////////////////////////
202
203
class CV_ResizeTest : public CV_ImgWarpBaseTest
204
{
205
public:
206
CV_ResizeTest();
207
208
protected:
209
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
210
void run_func();
211
void prepare_to_validation( int /*test_case_idx*/ );
212
double get_success_error_level( int test_case_idx, int i, int j );
213
};
214
215
216
CV_ResizeTest::CV_ResizeTest() : CV_ImgWarpBaseTest( false )
217
{
218
}
219
220
221
void CV_ResizeTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
222
{
223
RNG& rng = ts->get_rng();
224
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
225
Size sz;
226
227
sz.width = (cvtest::randInt(rng) % sizes[INPUT][0].width) + 1;
228
sz.height = (cvtest::randInt(rng) % sizes[INPUT][0].height) + 1;
229
230
if( cvtest::randInt(rng) & 1 )
231
{
232
int xfactor = cvtest::randInt(rng) % 10 + 1;
233
int yfactor = cvtest::randInt(rng) % 10 + 1;
234
235
if( cvtest::randInt(rng) & 1 )
236
yfactor = xfactor;
237
238
sz.width = sizes[INPUT][0].width / xfactor;
239
sz.width = MAX(sz.width,1);
240
sz.height = sizes[INPUT][0].height / yfactor;
241
sz.height = MAX(sz.height,1);
242
sizes[INPUT][0].width = sz.width * xfactor;
243
sizes[INPUT][0].height = sz.height * yfactor;
244
}
245
246
if( cvtest::randInt(rng) & 1 )
247
sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sz;
248
else
249
{
250
sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = sizes[INPUT][0];
251
sizes[INPUT][0] = sz;
252
}
253
if( interpolation == 4 &&
254
(MIN(sizes[INPUT][0].width,sizes[INPUT_OUTPUT][0].width) < 4 ||
255
MIN(sizes[INPUT][0].height,sizes[INPUT_OUTPUT][0].height) < 4))
256
interpolation = 2;
257
}
258
259
260
void CV_ResizeTest::run_func()
261
{
262
cvResize( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], interpolation );
263
}
264
265
266
double CV_ResizeTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
267
{
268
int depth = test_mat[INPUT][0].depth();
269
return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 1e-1;
270
}
271
272
273
void CV_ResizeTest::prepare_to_validation( int /*test_case_idx*/ )
274
{
275
CvMat _src = cvMat(test_mat[INPUT][0]), _dst = cvMat(test_mat[REF_INPUT_OUTPUT][0]);
276
CvMat *src = &_src, *dst = &_dst;
277
int i, j, k;
278
CvMat* x_idx = cvCreateMat( 1, dst->cols, CV_32SC1 );
279
CvMat* y_idx = cvCreateMat( 1, dst->rows, CV_32SC1 );
280
int* x_tab = x_idx->data.i;
281
int elem_size = CV_ELEM_SIZE(src->type);
282
int drows = dst->rows, dcols = dst->cols;
283
284
if( interpolation == CV_INTER_NN )
285
{
286
for( j = 0; j < dcols; j++ )
287
{
288
int t = (j*src->cols*2 + MIN(src->cols,dcols) - 1)/(dcols*2);
289
t -= t >= src->cols;
290
x_idx->data.i[j] = t*elem_size;
291
}
292
293
for( j = 0; j < drows; j++ )
294
{
295
int t = (j*src->rows*2 + MIN(src->rows,drows) - 1)/(drows*2);
296
t -= t >= src->rows;
297
y_idx->data.i[j] = t;
298
}
299
}
300
else
301
{
302
double scale_x = (double)src->cols/dcols;
303
double scale_y = (double)src->rows/drows;
304
305
for( j = 0; j < dcols; j++ )
306
{
307
double f = ((j+0.5)*scale_x - 0.5);
308
i = cvRound(f);
309
x_idx->data.i[j] = (i < 0 ? 0 : i >= src->cols ? src->cols - 1 : i)*elem_size;
310
}
311
312
for( j = 0; j < drows; j++ )
313
{
314
double f = ((j+0.5)*scale_y - 0.5);
315
i = cvRound(f);
316
y_idx->data.i[j] = i < 0 ? 0 : i >= src->rows ? src->rows - 1 : i;
317
}
318
}
319
320
for( i = 0; i < drows; i++ )
321
{
322
uchar* dptr = dst->data.ptr + dst->step*i;
323
const uchar* sptr0 = src->data.ptr + src->step*y_idx->data.i[i];
324
325
for( j = 0; j < dcols; j++, dptr += elem_size )
326
{
327
const uchar* sptr = sptr0 + x_tab[j];
328
for( k = 0; k < elem_size; k++ )
329
dptr[k] = sptr[k];
330
}
331
}
332
333
cvReleaseMat( &x_idx );
334
cvReleaseMat( &y_idx );
335
}
336
337
class CV_ResizeExactTest : public CV_ResizeTest
338
{
339
public:
340
CV_ResizeExactTest();
341
342
protected:
343
void get_test_array_types_and_sizes(int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types);
344
};
345
346
347
CV_ResizeExactTest::CV_ResizeExactTest() : CV_ResizeTest()
348
{
349
max_interpolation = 1;
350
}
351
352
353
void CV_ResizeExactTest::get_test_array_types_and_sizes(int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types)
354
{
355
CV_ResizeTest::get_test_array_types_and_sizes(test_case_idx, sizes, types);
356
interpolation = INTER_LINEAR_EXACT;
357
if (CV_MAT_DEPTH(types[INPUT][0]) == CV_32F ||
358
CV_MAT_DEPTH(types[INPUT][0]) == CV_64F)
359
types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(CV_8U, CV_MAT_CN(types[INPUT][0]));
360
}
361
362
/////////////////////////
363
364
static void test_remap( const Mat& src, Mat& dst, const Mat& mapx, const Mat& mapy,
365
Mat* mask=0, int interpolation=CV_INTER_LINEAR )
366
{
367
int x, y, k;
368
int drows = dst.rows, dcols = dst.cols;
369
int srows = src.rows, scols = src.cols;
370
const uchar* sptr0 = src.ptr();
371
int depth = src.depth(), cn = src.channels();
372
int elem_size = (int)src.elemSize();
373
int step = (int)(src.step / CV_ELEM_SIZE(depth));
374
int delta;
375
376
if( interpolation != CV_INTER_CUBIC )
377
{
378
delta = 0;
379
scols -= 1; srows -= 1;
380
}
381
else
382
{
383
delta = 1;
384
scols = MAX(scols - 3, 0);
385
srows = MAX(srows - 3, 0);
386
}
387
388
int scols1 = MAX(scols - 2, 0);
389
int srows1 = MAX(srows - 2, 0);
390
391
if( mask )
392
*mask = Scalar::all(0);
393
394
for( y = 0; y < drows; y++ )
395
{
396
uchar* dptr = dst.ptr(y);
397
const float* mx = mapx.ptr<float>(y);
398
const float* my = mapy.ptr<float>(y);
399
uchar* m = mask ? mask->ptr(y) : 0;
400
401
for( x = 0; x < dcols; x++, dptr += elem_size )
402
{
403
float xs = mx[x];
404
float ys = my[x];
405
int ixs = cvFloor(xs);
406
int iys = cvFloor(ys);
407
408
if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 ||
409
(unsigned)(iys - delta - 1) >= (unsigned)srows1 )
410
{
411
if( m )
412
m[x] = 1;
413
if( (unsigned)(ixs - delta) >= (unsigned)scols ||
414
(unsigned)(iys - delta) >= (unsigned)srows )
415
continue;
416
}
417
418
xs -= ixs;
419
ys -= iys;
420
421
switch( depth )
422
{
423
case CV_8U:
424
{
425
const uchar* sptr = sptr0 + iys*step + ixs*cn;
426
for( k = 0; k < cn; k++ )
427
{
428
float v00 = sptr[k];
429
float v01 = sptr[cn + k];
430
float v10 = sptr[step + k];
431
float v11 = sptr[step + cn + k];
432
433
v00 = v00 + xs*(v01 - v00);
434
v10 = v10 + xs*(v11 - v10);
435
v00 = v00 + ys*(v10 - v00);
436
dptr[k] = (uchar)cvRound(v00);
437
}
438
}
439
break;
440
case CV_16U:
441
{
442
const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn;
443
for( k = 0; k < cn; k++ )
444
{
445
float v00 = sptr[k];
446
float v01 = sptr[cn + k];
447
float v10 = sptr[step + k];
448
float v11 = sptr[step + cn + k];
449
450
v00 = v00 + xs*(v01 - v00);
451
v10 = v10 + xs*(v11 - v10);
452
v00 = v00 + ys*(v10 - v00);
453
((ushort*)dptr)[k] = (ushort)cvRound(v00);
454
}
455
}
456
break;
457
case CV_32F:
458
{
459
const float* sptr = (const float*)sptr0 + iys*step + ixs*cn;
460
for( k = 0; k < cn; k++ )
461
{
462
float v00 = sptr[k];
463
float v01 = sptr[cn + k];
464
float v10 = sptr[step + k];
465
float v11 = sptr[step + cn + k];
466
467
v00 = v00 + xs*(v01 - v00);
468
v10 = v10 + xs*(v11 - v10);
469
v00 = v00 + ys*(v10 - v00);
470
((float*)dptr)[k] = (float)v00;
471
}
472
}
473
break;
474
default:
475
assert(0);
476
}
477
}
478
}
479
}
480
481
/////////////////////////
482
483
class CV_WarpAffineTest : public CV_ImgWarpBaseTest
484
{
485
public:
486
CV_WarpAffineTest();
487
488
protected:
489
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
490
void run_func();
491
int prepare_test_case( int test_case_idx );
492
void prepare_to_validation( int /*test_case_idx*/ );
493
double get_success_error_level( int test_case_idx, int i, int j );
494
};
495
496
497
CV_WarpAffineTest::CV_WarpAffineTest() : CV_ImgWarpBaseTest( true )
498
{
499
//spatial_scale_zoom = spatial_scale_decimate;
500
spatial_scale_decimate = spatial_scale_zoom;
501
}
502
503
504
void CV_WarpAffineTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
505
{
506
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
507
Size sz = sizes[INPUT][0];
508
// run for the second time to get output of a different size
509
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
510
sizes[INPUT][0] = sz;
511
sizes[INPUT][1] = Size( 3, 2 );
512
}
513
514
515
void CV_WarpAffineTest::run_func()
516
{
517
CvMat mtx = cvMat(test_mat[INPUT][1]);
518
cvWarpAffine( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx, interpolation );
519
}
520
521
522
double CV_WarpAffineTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
523
{
524
int depth = test_mat[INPUT][0].depth();
525
return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
526
}
527
528
529
int CV_WarpAffineTest::prepare_test_case( int test_case_idx )
530
{
531
RNG& rng = ts->get_rng();
532
int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
533
const Mat& src = test_mat[INPUT][0];
534
const Mat& dst = test_mat[INPUT_OUTPUT][0];
535
Mat& mat = test_mat[INPUT][1];
536
Point2f center;
537
double scale, angle;
538
539
if( code <= 0 )
540
return code;
541
542
double buffer[6];
543
Mat tmp( 2, 3, mat.type(), buffer );
544
545
center.x = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.cols);
546
center.y = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.rows);
547
angle = cvtest::randReal(rng)*360;
548
scale = ((double)dst.rows/src.rows + (double)dst.cols/src.cols)*0.5;
549
getRotationMatrix2D(center, angle, scale).convertTo(mat, mat.depth());
550
rng.fill( tmp, CV_RAND_NORMAL, Scalar::all(1.), Scalar::all(0.01) );
551
cv::max(tmp, 0.9, tmp);
552
cv::min(tmp, 1.1, tmp);
553
cv::multiply(tmp, mat, mat, 1.);
554
555
return code;
556
}
557
558
559
void CV_WarpAffineTest::prepare_to_validation( int /*test_case_idx*/ )
560
{
561
const Mat& src = test_mat[INPUT][0];
562
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
563
Mat& dst0 = test_mat[INPUT_OUTPUT][0];
564
Mat mapx(dst.size(), CV_32F), mapy(dst.size(), CV_32F);
565
double m[6];
566
Mat srcAb, dstAb( 2, 3, CV_64FC1, m );
567
568
//cvInvert( &tM, &M, CV_LU );
569
// [R|t] -> [R^-1 | -(R^-1)*t]
570
test_mat[INPUT][1].convertTo( srcAb, CV_64F );
571
Mat A = srcAb.colRange(0, 2);
572
Mat b = srcAb.col(2);
573
Mat invA = dstAb.colRange(0, 2);
574
Mat invAb = dstAb.col(2);
575
cv::invert(A, invA, CV_SVD);
576
cv::gemm(invA, b, -1, Mat(), 0, invAb);
577
578
for( int y = 0; y < dst.rows; y++ )
579
for( int x = 0; x < dst.cols; x++ )
580
{
581
mapx.at<float>(y, x) = (float)(x*m[0] + y*m[1] + m[2]);
582
mapy.at<float>(y, x) = (float)(x*m[3] + y*m[4] + m[5]);
583
}
584
585
Mat mask( dst.size(), CV_8U );
586
test_remap( src, dst, mapx, mapy, &mask );
587
dst.setTo(Scalar::all(0), mask);
588
dst0.setTo(Scalar::all(0), mask);
589
}
590
591
592
/////////////////////////
593
594
class CV_WarpPerspectiveTest : public CV_ImgWarpBaseTest
595
{
596
public:
597
CV_WarpPerspectiveTest();
598
599
protected:
600
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
601
void run_func();
602
int prepare_test_case( int test_case_idx );
603
void prepare_to_validation( int /*test_case_idx*/ );
604
double get_success_error_level( int test_case_idx, int i, int j );
605
};
606
607
608
CV_WarpPerspectiveTest::CV_WarpPerspectiveTest() : CV_ImgWarpBaseTest( true )
609
{
610
//spatial_scale_zoom = spatial_scale_decimate;
611
spatial_scale_decimate = spatial_scale_zoom;
612
}
613
614
615
void CV_WarpPerspectiveTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
616
{
617
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
618
Size sz = sizes[INPUT][0];
619
// run for the second time to get output of a different size
620
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
621
sizes[INPUT][0] = sz;
622
sizes[INPUT][1] = Size( 3, 3 );
623
}
624
625
626
void CV_WarpPerspectiveTest::run_func()
627
{
628
CvMat mtx = cvMat(test_mat[INPUT][1]);
629
cvWarpPerspective( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx, interpolation );
630
}
631
632
633
double CV_WarpPerspectiveTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
634
{
635
int depth = test_mat[INPUT][0].depth();
636
return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
637
}
638
639
640
int CV_WarpPerspectiveTest::prepare_test_case( int test_case_idx )
641
{
642
RNG& rng = ts->get_rng();
643
int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
644
const CvMat src = cvMat(test_mat[INPUT][0]);
645
const CvMat dst = cvMat(test_mat[INPUT_OUTPUT][0]);
646
Mat& mat = test_mat[INPUT][1];
647
Point2f s[4], d[4];
648
int i;
649
650
if( code <= 0 )
651
return code;
652
653
s[0] = Point2f(0,0);
654
d[0] = Point2f(0,0);
655
s[1] = Point2f(src.cols-1.f,0);
656
d[1] = Point2f(dst.cols-1.f,0);
657
s[2] = Point2f(src.cols-1.f,src.rows-1.f);
658
d[2] = Point2f(dst.cols-1.f,dst.rows-1.f);
659
s[3] = Point2f(0,src.rows-1.f);
660
d[3] = Point2f(0,dst.rows-1.f);
661
662
float bufer[16];
663
Mat tmp( 1, 16, CV_32FC1, bufer );
664
665
rng.fill( tmp, CV_RAND_NORMAL, Scalar::all(0.), Scalar::all(0.1) );
666
667
for( i = 0; i < 4; i++ )
668
{
669
s[i].x += bufer[i*4]*src.cols/2;
670
s[i].y += bufer[i*4+1]*src.rows/2;
671
d[i].x += bufer[i*4+2]*dst.cols/2;
672
d[i].y += bufer[i*4+3]*dst.rows/2;
673
}
674
675
cv::getPerspectiveTransform( s, d ).convertTo( mat, mat.depth() );
676
return code;
677
}
678
679
680
void CV_WarpPerspectiveTest::prepare_to_validation( int /*test_case_idx*/ )
681
{
682
Mat& src = test_mat[INPUT][0];
683
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
684
Mat& dst0 = test_mat[INPUT_OUTPUT][0];
685
Mat mapx(dst.size(), CV_32F), mapy(dst.size(), CV_32F);
686
double m[9];
687
Mat srcM, dstM(3, 3, CV_64F, m);
688
689
//cvInvert( &tM, &M, CV_LU );
690
// [R|t] -> [R^-1 | -(R^-1)*t]
691
test_mat[INPUT][1].convertTo( srcM, CV_64F );
692
cv::invert(srcM, dstM, CV_SVD);
693
694
for( int y = 0; y < dst.rows; y++ )
695
{
696
for( int x = 0; x < dst.cols; x++ )
697
{
698
double xs = x*m[0] + y*m[1] + m[2];
699
double ys = x*m[3] + y*m[4] + m[5];
700
double ds = x*m[6] + y*m[7] + m[8];
701
702
ds = ds ? 1./ds : 0;
703
xs *= ds;
704
ys *= ds;
705
706
mapx.at<float>(y, x) = (float)xs;
707
mapy.at<float>(y, x) = (float)ys;
708
}
709
}
710
711
Mat mask( dst.size(), CV_8U );
712
test_remap( src, dst, mapx, mapy, &mask );
713
dst.setTo(Scalar::all(0), mask);
714
dst0.setTo(Scalar::all(0), mask);
715
}
716
717
718
/////////////////////////
719
720
class CV_RemapTest : public CV_ImgWarpBaseTest
721
{
722
public:
723
CV_RemapTest();
724
725
protected:
726
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
727
void run_func();
728
int prepare_test_case( int test_case_idx );
729
void prepare_to_validation( int /*test_case_idx*/ );
730
double get_success_error_level( int test_case_idx, int i, int j );
731
void fill_array( int test_case_idx, int i, int j, Mat& arr );
732
};
733
734
735
CV_RemapTest::CV_RemapTest() : CV_ImgWarpBaseTest( false )
736
{
737
//spatial_scale_zoom = spatial_scale_decimate;
738
test_array[INPUT].push_back(NULL);
739
test_array[INPUT].push_back(NULL);
740
741
spatial_scale_decimate = spatial_scale_zoom;
742
}
743
744
745
void CV_RemapTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
746
{
747
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
748
types[INPUT][1] = types[INPUT][2] = CV_32FC1;
749
interpolation = CV_INTER_LINEAR;
750
}
751
752
753
void CV_RemapTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
754
{
755
if( i != INPUT )
756
CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr );
757
}
758
759
760
void CV_RemapTest::run_func()
761
{
762
cvRemap( test_array[INPUT][0], test_array[INPUT_OUTPUT][0],
763
test_array[INPUT][1], test_array[INPUT][2], interpolation );
764
}
765
766
767
double CV_RemapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
768
{
769
int depth = test_mat[INPUT][0].depth();
770
return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
771
}
772
773
774
int CV_RemapTest::prepare_test_case( int test_case_idx )
775
{
776
RNG& rng = ts->get_rng();
777
int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
778
const Mat& src = test_mat[INPUT][0];
779
double a[9] = {0,0,0,0,0,0,0,0,1}, k[4];
780
Mat _a( 3, 3, CV_64F, a );
781
Mat _k( 4, 1, CV_64F, k );
782
double sz = MAX(src.rows, src.cols);
783
784
if( code <= 0 )
785
return code;
786
787
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
788
a[2] = (src.cols - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
789
a[5] = (src.rows - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
790
a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
791
a[4] = aspect_ratio*a[0];
792
k[0] = cvtest::randReal(rng)*0.06 - 0.03;
793
k[1] = cvtest::randReal(rng)*0.06 - 0.03;
794
if( k[0]*k[1] > 0 )
795
k[1] = -k[1];
796
k[2] = cvtest::randReal(rng)*0.004 - 0.002;
797
k[3] = cvtest::randReal(rng)*0.004 - 0.002;
798
799
cvtest::initUndistortMap( _a, _k, test_mat[INPUT][1].size(), test_mat[INPUT][1], test_mat[INPUT][2] );
800
return code;
801
}
802
803
804
void CV_RemapTest::prepare_to_validation( int /*test_case_idx*/ )
805
{
806
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
807
Mat& dst0 = test_mat[INPUT_OUTPUT][0];
808
Mat mask( dst.size(), CV_8U );
809
test_remap(test_mat[INPUT][0], dst, test_mat[INPUT][1],
810
test_mat[INPUT][2], &mask, interpolation );
811
dst.setTo(Scalar::all(0), mask);
812
dst0.setTo(Scalar::all(0), mask);
813
}
814
815
////////////////////////////// GetRectSubPix /////////////////////////////////
816
817
static void
818
test_getQuadrangeSubPix( const Mat& src, Mat& dst, double* a )
819
{
820
int sstep = (int)(src.step / sizeof(float));
821
int scols = src.cols, srows = src.rows;
822
823
CV_Assert( src.depth() == CV_32F && src.type() == dst.type() );
824
825
int cn = dst.channels();
826
827
for( int y = 0; y < dst.rows; y++ )
828
for( int x = 0; x < dst.cols; x++ )
829
{
830
float* d = dst.ptr<float>(y) + x*cn;
831
float sx = (float)(a[0]*x + a[1]*y + a[2]);
832
float sy = (float)(a[3]*x + a[4]*y + a[5]);
833
int ix = cvFloor(sx), iy = cvFloor(sy);
834
int dx = cn, dy = sstep;
835
const float* s;
836
sx -= ix; sy -= iy;
837
838
if( (unsigned)ix >= (unsigned)(scols-1) )
839
ix = ix < 0 ? 0 : scols - 1, sx = 0, dx = 0;
840
if( (unsigned)iy >= (unsigned)(srows-1) )
841
iy = iy < 0 ? 0 : srows - 1, sy = 0, dy = 0;
842
843
s = src.ptr<float>(iy) + ix*cn;
844
for( int k = 0; k < cn; k++, s++ )
845
{
846
float t0 = s[0] + sx*(s[dx] - s[0]);
847
float t1 = s[dy] + sx*(s[dy + dx] - s[dy]);
848
d[k] = t0 + sy*(t1 - t0);
849
}
850
}
851
}
852
853
854
class CV_GetRectSubPixTest : public CV_ImgWarpBaseTest
855
{
856
public:
857
CV_GetRectSubPixTest();
858
859
protected:
860
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
861
void run_func();
862
int prepare_test_case( int test_case_idx );
863
void prepare_to_validation( int /*test_case_idx*/ );
864
double get_success_error_level( int test_case_idx, int i, int j );
865
void fill_array( int test_case_idx, int i, int j, Mat& arr );
866
867
CvPoint2D32f center;
868
bool test_cpp;
869
};
870
871
872
CV_GetRectSubPixTest::CV_GetRectSubPixTest() : CV_ImgWarpBaseTest( false )
873
{
874
//spatial_scale_zoom = spatial_scale_decimate;
875
spatial_scale_decimate = spatial_scale_zoom;
876
test_cpp = false;
877
}
878
879
880
void CV_GetRectSubPixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
881
{
882
RNG& rng = ts->get_rng();
883
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
884
int src_depth = cvtest::randInt(rng) % 2, dst_depth;
885
int cn = cvtest::randInt(rng) % 2 ? 3 : 1;
886
Size src_size, dst_size;
887
888
dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F;
889
if( src_depth < CV_32F && cvtest::randInt(rng) % 2 )
890
dst_depth = CV_32F;
891
892
types[INPUT][0] = CV_MAKETYPE(src_depth,cn);
893
types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn);
894
895
src_size = sizes[INPUT][0];
896
dst_size.width = cvRound(sqrt(cvtest::randReal(rng)*src_size.width) + 1);
897
dst_size.height = cvRound(sqrt(cvtest::randReal(rng)*src_size.height) + 1);
898
dst_size.width = MIN(dst_size.width,src_size.width);
899
dst_size.height = MIN(dst_size.width,src_size.height);
900
sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dst_size;
901
902
center.x = (float)(cvtest::randReal(rng)*src_size.width);
903
center.y = (float)(cvtest::randReal(rng)*src_size.height);
904
interpolation = CV_INTER_LINEAR;
905
906
test_cpp = (cvtest::randInt(rng) & 256) == 0;
907
}
908
909
910
void CV_GetRectSubPixTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
911
{
912
if( i != INPUT )
913
CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr );
914
}
915
916
917
void CV_GetRectSubPixTest::run_func()
918
{
919
if(!test_cpp)
920
cvGetRectSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], center );
921
else
922
{
923
cv::Mat _out = cv::cvarrToMat(test_array[INPUT_OUTPUT][0]);
924
cv::getRectSubPix( cv::cvarrToMat(test_array[INPUT][0]), _out.size(), center, _out, _out.type());
925
}
926
}
927
928
929
double CV_GetRectSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
930
{
931
int in_depth = test_mat[INPUT][0].depth();
932
int out_depth = test_mat[INPUT_OUTPUT][0].depth();
933
934
return in_depth >= CV_32F ? 1e-3 : out_depth >= CV_32F ? 1e-2 : 1;
935
}
936
937
938
int CV_GetRectSubPixTest::prepare_test_case( int test_case_idx )
939
{
940
return CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
941
}
942
943
944
void CV_GetRectSubPixTest::prepare_to_validation( int /*test_case_idx*/ )
945
{
946
Mat& src0 = test_mat[INPUT][0];
947
Mat& dst0 = test_mat[REF_INPUT_OUTPUT][0];
948
Mat src = src0, dst = dst0;
949
int ftype = CV_MAKETYPE(CV_32F,src0.channels());
950
double a[] = { 1, 0, center.x - dst.cols*0.5 + 0.5,
951
0, 1, center.y - dst.rows*0.5 + 0.5 };
952
if( src.depth() != CV_32F )
953
src0.convertTo(src, CV_32F);
954
955
if( dst.depth() != CV_32F )
956
dst.create(dst0.size(), ftype);
957
958
test_getQuadrangeSubPix( src, dst, a );
959
960
if( dst.data != dst0.data )
961
dst.convertTo(dst0, dst0.depth());
962
}
963
964
965
class CV_GetQuadSubPixTest : public CV_ImgWarpBaseTest
966
{
967
public:
968
CV_GetQuadSubPixTest();
969
970
protected:
971
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
972
void run_func();
973
int prepare_test_case( int test_case_idx );
974
void prepare_to_validation( int /*test_case_idx*/ );
975
double get_success_error_level( int test_case_idx, int i, int j );
976
};
977
978
979
CV_GetQuadSubPixTest::CV_GetQuadSubPixTest() : CV_ImgWarpBaseTest( true )
980
{
981
//spatial_scale_zoom = spatial_scale_decimate;
982
spatial_scale_decimate = spatial_scale_zoom;
983
}
984
985
986
void CV_GetQuadSubPixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
987
{
988
int min_size = 4;
989
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
990
Size sz = sizes[INPUT][0], dsz;
991
RNG& rng = ts->get_rng();
992
int msz, src_depth = cvtest::randInt(rng) % 2, dst_depth;
993
int cn = cvtest::randInt(rng) % 2 ? 3 : 1;
994
995
dst_depth = src_depth = src_depth == 0 ? CV_8U : CV_32F;
996
if( src_depth < CV_32F && cvtest::randInt(rng) % 2 )
997
dst_depth = CV_32F;
998
999
types[INPUT][0] = CV_MAKETYPE(src_depth,cn);
1000
types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(dst_depth,cn);
1001
1002
sz.width = MAX(sz.width,min_size);
1003
sz.height = MAX(sz.height,min_size);
1004
sizes[INPUT][0] = sz;
1005
msz = MIN( sz.width, sz.height );
1006
1007
dsz.width = cvRound(sqrt(cvtest::randReal(rng)*msz) + 1);
1008
dsz.height = cvRound(sqrt(cvtest::randReal(rng)*msz) + 1);
1009
dsz.width = MIN(dsz.width,msz);
1010
dsz.height = MIN(dsz.width,msz);
1011
dsz.width = MAX(dsz.width,min_size);
1012
dsz.height = MAX(dsz.height,min_size);
1013
sizes[INPUT_OUTPUT][0] = sizes[REF_INPUT_OUTPUT][0] = dsz;
1014
sizes[INPUT][1] = cvSize( 3, 2 );
1015
}
1016
1017
1018
void CV_GetQuadSubPixTest::run_func()
1019
{
1020
CvMat mtx = cvMat(test_mat[INPUT][1]);
1021
cvGetQuadrangleSubPix( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &mtx );
1022
}
1023
1024
1025
double CV_GetQuadSubPixTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1026
{
1027
int in_depth = test_mat[INPUT][0].depth();
1028
//int out_depth = test_mat[INPUT_OUTPUT][0].depth();
1029
1030
return in_depth >= CV_32F ? 1e-2 : 4;
1031
}
1032
1033
1034
int CV_GetQuadSubPixTest::prepare_test_case( int test_case_idx )
1035
{
1036
RNG& rng = ts->get_rng();
1037
int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1038
const Mat& src = test_mat[INPUT][0];
1039
Mat& mat = test_mat[INPUT][1];
1040
Point2f center;
1041
double scale, angle;
1042
1043
if( code <= 0 )
1044
return code;
1045
1046
double a[6];
1047
Mat A( 2, 3, CV_64FC1, a );
1048
1049
center.x = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.cols);
1050
center.y = (float)((cvtest::randReal(rng)*1.2 - 0.1)*src.rows);
1051
angle = cvtest::randReal(rng)*360;
1052
scale = cvtest::randReal(rng)*0.2 + 0.9;
1053
1054
// y = Ax + b -> x = A^-1(y - b) = A^-1*y - A^-1*b
1055
scale = 1./scale;
1056
angle = angle*(CV_PI/180.);
1057
a[0] = a[4] = cos(angle)*scale;
1058
a[1] = sin(angle)*scale;
1059
a[3] = -a[1];
1060
a[2] = center.x - a[0]*center.x - a[1]*center.y;
1061
a[5] = center.y - a[3]*center.x - a[4]*center.y;
1062
A.convertTo( mat, mat.depth() );
1063
1064
return code;
1065
}
1066
1067
1068
void CV_GetQuadSubPixTest::prepare_to_validation( int /*test_case_idx*/ )
1069
{
1070
Mat& src0 = test_mat[INPUT][0];
1071
Mat& dst0 = test_mat[REF_INPUT_OUTPUT][0];
1072
Mat src = src0, dst = dst0;
1073
int ftype = CV_MAKETYPE(CV_32F,src0.channels());
1074
double a[6], dx = (dst0.cols - 1)*0.5, dy = (dst0.rows - 1)*0.5;
1075
Mat A( 2, 3, CV_64F, a );
1076
1077
if( src.depth() != CV_32F )
1078
src0.convertTo(src, CV_32F);
1079
1080
if( dst.depth() != CV_32F )
1081
dst.create(dst0.size(), ftype);
1082
1083
test_mat[INPUT][1].convertTo( A, CV_64F );
1084
a[2] -= a[0]*dx + a[1]*dy;
1085
a[5] -= a[3]*dx + a[4]*dy;
1086
test_getQuadrangeSubPix( src, dst, a );
1087
1088
if( dst.data != dst0.data )
1089
dst.convertTo(dst0, dst0.depth());
1090
}
1091
1092
////////////////////////////// resizeArea /////////////////////////////////
1093
1094
template <typename T>
1095
static void check_resize_area(const Mat& expected, const Mat& actual, double tolerance = 1.0)
1096
{
1097
ASSERT_EQ(actual.type(), expected.type());
1098
ASSERT_EQ(actual.size(), expected.size());
1099
1100
Mat diff;
1101
absdiff(actual, expected, diff);
1102
1103
Mat one_channel_diff = diff; //.reshape(1);
1104
1105
Size dsize = actual.size();
1106
bool next = true;
1107
for (int dy = 0; dy < dsize.height && next; ++dy)
1108
{
1109
const T* eD = expected.ptr<T>(dy);
1110
const T* aD = actual.ptr<T>(dy);
1111
1112
for (int dx = 0; dx < dsize.width && next; ++dx)
1113
if (fabs(static_cast<double>(aD[dx] - eD[dx])) > tolerance)
1114
{
1115
cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Inf norm: %f\n", static_cast<float>(cvtest::norm(actual, expected, NORM_INF)));
1116
cvtest::TS::ptr()->printf(cvtest::TS::SUMMARY, "Error in : (%d, %d)\n", dx, dy);
1117
1118
const int radius = 3;
1119
int rmin = MAX(dy - radius, 0), rmax = MIN(dy + radius, dsize.height);
1120
int cmin = MAX(dx - radius, 0), cmax = MIN(dx + radius, dsize.width);
1121
1122
std::cout << "Abs diff:" << std::endl << diff << std::endl;
1123
std::cout << "actual result:\n" << actual(Range(rmin, rmax), Range(cmin, cmax)) << std::endl;
1124
std::cout << "expected result:\n" << expected(Range(rmin, rmax), Range(cmin, cmax)) << std::endl;
1125
1126
next = false;
1127
}
1128
}
1129
1130
ASSERT_EQ(0, cvtest::norm(one_channel_diff, cv::NORM_INF));
1131
}
1132
1133
///////////////////////////////////////////////////////////////////////////
1134
1135
TEST(Imgproc_cvWarpAffine, regression)
1136
{
1137
IplImage* src = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1);
1138
IplImage* dst = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1);
1139
1140
cvZero(src);
1141
1142
float m[6];
1143
CvMat M = cvMat( 2, 3, CV_32F, m );
1144
int w = src->width;
1145
int h = src->height;
1146
cv2DRotationMatrix(cvPoint2D32f(w*0.5f, h*0.5f), 45.0, 1.0, &M);
1147
cvWarpAffine(src, dst, &M);
1148
1149
cvReleaseImage(&src);
1150
cvReleaseImage(&dst);
1151
}
1152
1153
TEST(Imgproc_fitLine_vector_3d, regression)
1154
{
1155
std::vector<Point3f> points_vector;
1156
1157
Point3f p21(4,4,4);
1158
Point3f p22(8,8,8);
1159
1160
points_vector.push_back(p21);
1161
points_vector.push_back(p22);
1162
1163
std::vector<float> line;
1164
1165
cv::fitLine(points_vector, line, CV_DIST_L2, 0 ,0 ,0);
1166
1167
ASSERT_EQ(line.size(), (size_t)6);
1168
1169
}
1170
1171
TEST(Imgproc_fitLine_vector_2d, regression)
1172
{
1173
std::vector<Point2f> points_vector;
1174
1175
Point2f p21(4,4);
1176
Point2f p22(8,8);
1177
Point2f p23(16,16);
1178
1179
points_vector.push_back(p21);
1180
points_vector.push_back(p22);
1181
points_vector.push_back(p23);
1182
1183
std::vector<float> line;
1184
1185
cv::fitLine(points_vector, line, CV_DIST_L2, 0 ,0 ,0);
1186
1187
ASSERT_EQ(line.size(), (size_t)4);
1188
}
1189
1190
TEST(Imgproc_fitLine_Mat_2dC2, regression)
1191
{
1192
cv::Mat mat1 = Mat::zeros(3, 1, CV_32SC2);
1193
std::vector<float> line1;
1194
1195
cv::fitLine(mat1, line1, CV_DIST_L2, 0 ,0 ,0);
1196
1197
ASSERT_EQ(line1.size(), (size_t)4);
1198
}
1199
1200
TEST(Imgproc_fitLine_Mat_2dC1, regression)
1201
{
1202
cv::Matx<int, 3, 2> mat2;
1203
std::vector<float> line2;
1204
1205
cv::fitLine(mat2, line2, CV_DIST_L2, 0 ,0 ,0);
1206
1207
ASSERT_EQ(line2.size(), (size_t)4);
1208
}
1209
1210
TEST(Imgproc_fitLine_Mat_3dC3, regression)
1211
{
1212
cv::Mat mat1 = Mat::zeros(2, 1, CV_32SC3);
1213
std::vector<float> line1;
1214
1215
cv::fitLine(mat1, line1, CV_DIST_L2, 0 ,0 ,0);
1216
1217
ASSERT_EQ(line1.size(), (size_t)6);
1218
}
1219
1220
TEST(Imgproc_fitLine_Mat_3dC1, regression)
1221
{
1222
cv::Mat mat2 = Mat::zeros(2, 3, CV_32SC1);
1223
std::vector<float> line2;
1224
1225
cv::fitLine(mat2, line2, CV_DIST_L2, 0 ,0 ,0);
1226
1227
ASSERT_EQ(line2.size(), (size_t)6);
1228
}
1229
1230
TEST(Imgproc_resize_area, regression)
1231
{
1232
static ushort input_data[16 * 16] = {
1233
90, 94, 80, 3, 231, 2, 186, 245, 188, 165, 10, 19, 201, 169, 8, 228,
1234
86, 5, 203, 120, 136, 185, 24, 94, 81, 150, 163, 137, 88, 105, 132, 132,
1235
236, 48, 250, 218, 19, 52, 54, 221, 159, 112, 45, 11, 152, 153, 112, 134,
1236
78, 133, 136, 83, 65, 76, 82, 250, 9, 235, 148, 26, 236, 179, 200, 50,
1237
99, 51, 103, 142, 201, 65, 176, 33, 49, 226, 177, 109, 46, 21, 67, 130,
1238
54, 125, 107, 154, 145, 51, 199, 189, 161, 142, 231, 240, 139, 162, 240, 22,
1239
231, 86, 79, 106, 92, 47, 146, 156, 36, 207, 71, 33, 2, 244, 221, 71,
1240
44, 127, 71, 177, 75, 126, 68, 119, 200, 129, 191, 251, 6, 236, 247, 6,
1241
133, 175, 56, 239, 147, 221, 243, 154, 242, 82, 106, 99, 77, 158, 60, 229,
1242
2, 42, 24, 174, 27, 198, 14, 204, 246, 251, 141, 31, 114, 163, 29, 147,
1243
121, 53, 74, 31, 147, 189, 42, 98, 202, 17, 228, 123, 209, 40, 77, 49,
1244
112, 203, 30, 12, 205, 25, 19, 106, 145, 185, 163, 201, 237, 223, 247, 38,
1245
33, 105, 243, 117, 92, 179, 204, 248, 160, 90, 73, 126, 2, 41, 213, 204,
1246
6, 124, 195, 201, 230, 187, 210, 167, 48, 79, 123, 159, 145, 218, 105, 209,
1247
240, 152, 136, 235, 235, 164, 157, 9, 152, 38, 27, 209, 120, 77, 238, 196,
1248
240, 233, 10, 241, 90, 67, 12, 79, 0, 43, 58, 27, 83, 199, 190, 182};
1249
1250
static ushort expected_data[5 * 5] = {
1251
120, 100, 151, 101, 130,
1252
106, 115, 141, 130, 127,
1253
91, 136, 170, 114, 140,
1254
104, 122, 131, 147, 133,
1255
161, 163, 70, 107, 182
1256
};
1257
1258
cv::Mat src(16, 16, CV_16UC1, input_data);
1259
cv::Mat expected(5, 5, CV_16UC1, expected_data);
1260
cv::Mat actual(expected.size(), expected.type());
1261
1262
cv::resize(src, actual, cv::Size(), 0.3, 0.3, INTER_AREA);
1263
1264
check_resize_area<ushort>(expected, actual, 1.0);
1265
}
1266
1267
TEST(Imgproc_resize_area, regression_half_round)
1268
{
1269
static uchar input_data[32 * 32];
1270
for(int i = 0; i < 32 * 32; ++i)
1271
input_data[i] = (uchar)(i % 2 + 253 + i / (16 * 32));
1272
1273
static uchar expected_data[16 * 16];
1274
for(int i = 0; i < 16 * 16; ++i)
1275
expected_data[i] = (uchar)(254 + i / (16 * 8));
1276
1277
cv::Mat src(32, 32, CV_8UC1, input_data);
1278
cv::Mat expected(16, 16, CV_8UC1, expected_data);
1279
cv::Mat actual(expected.size(), expected.type());
1280
1281
cv::resize(src, actual, cv::Size(), 0.5, 0.5, INTER_AREA);
1282
1283
check_resize_area<uchar>(expected, actual, 0.5);
1284
}
1285
1286
TEST(Imgproc_resize_area, regression_quarter_round)
1287
{
1288
static uchar input_data[32 * 32];
1289
for(int i = 0; i < 32 * 32; ++i)
1290
input_data[i] = (uchar)(i % 2 + 253 + i / (16 * 32));
1291
1292
static uchar expected_data[8 * 8];
1293
for(int i = 0; i < 8 * 8; ++i)
1294
expected_data[i] = 254;
1295
1296
cv::Mat src(32, 32, CV_8UC1, input_data);
1297
cv::Mat expected(8, 8, CV_8UC1, expected_data);
1298
cv::Mat actual(expected.size(), expected.type());
1299
1300
cv::resize(src, actual, cv::Size(), 0.25, 0.25, INTER_AREA);
1301
1302
check_resize_area<uchar>(expected, actual, 0.5);
1303
}
1304
1305
1306
//////////////////////////////////////////////////////////////////////////
1307
1308
TEST(Imgproc_Resize, accuracy) { CV_ResizeTest test; test.safe_run(); }
1309
TEST(Imgproc_ResizeExact, accuracy) { CV_ResizeExactTest test; test.safe_run(); }
1310
TEST(Imgproc_WarpAffine, accuracy) { CV_WarpAffineTest test; test.safe_run(); }
1311
TEST(Imgproc_WarpPerspective, accuracy) { CV_WarpPerspectiveTest test; test.safe_run(); }
1312
TEST(Imgproc_Remap, accuracy) { CV_RemapTest test; test.safe_run(); }
1313
TEST(Imgproc_GetRectSubPix, accuracy) { CV_GetRectSubPixTest test; test.safe_run(); }
1314
TEST(Imgproc_GetQuadSubPix, accuracy) { CV_GetQuadSubPixTest test; test.safe_run(); }
1315
1316
//////////////////////////////////////////////////////////////////////////
1317
1318
template <typename T, typename WT>
1319
struct IntCast
1320
{
1321
T operator() (WT val) const
1322
{
1323
return cv::saturate_cast<T>(val >> 2);
1324
}
1325
};
1326
1327
template <typename T, typename WT>
1328
struct FltCast
1329
{
1330
T operator() (WT val) const
1331
{
1332
return cv::saturate_cast<T>(val * 0.25);
1333
}
1334
};
1335
1336
template <typename T, typename WT, int one, typename CastOp>
1337
void resizeArea(const cv::Mat & src, cv::Mat & dst)
1338
{
1339
int cn = src.channels();
1340
CastOp castOp;
1341
1342
for (int y = 0; y < dst.rows; ++y)
1343
{
1344
const T * sptr0 = src.ptr<T>(y << 1);
1345
const T * sptr1 = src.ptr<T>((y << 1) + 1);
1346
T * dptr = dst.ptr<T>(y);
1347
1348
for (int x = 0; x < dst.cols * cn; x += cn)
1349
{
1350
int x1 = x << 1;
1351
1352
for (int c = 0; c < cn; ++c)
1353
{
1354
WT sum = WT(sptr0[x1 + c]) + WT(sptr0[x1 + c + cn]);
1355
sum += WT(sptr1[x1 + c]) + WT(sptr1[x1 + c + cn]) + (WT)(one);
1356
1357
dptr[x + c] = castOp(sum);
1358
}
1359
}
1360
}
1361
}
1362
1363
TEST(Resize, Area_half)
1364
{
1365
const int size = 1000;
1366
int types[] = { CV_8UC1, CV_8UC4,
1367
CV_16UC1, CV_16UC4,
1368
CV_16SC1, CV_16SC3, CV_16SC4,
1369
CV_32FC1, CV_32FC4 };
1370
1371
cv::RNG rng(17);
1372
1373
for (int i = 0, _size = sizeof(types) / sizeof(types[0]); i < _size; ++i)
1374
{
1375
int type = types[i], depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
1376
const float eps = depth <= CV_32S ? 0 : 7e-5f;
1377
1378
SCOPED_TRACE(depth);
1379
SCOPED_TRACE(cn);
1380
1381
cv::Mat src(size, size, type), dst_actual(size >> 1, size >> 1, type),
1382
dst_reference(size >> 1, size >> 1, type);
1383
1384
rng.fill(src, cv::RNG::UNIFORM, -1000, 1000, true);
1385
1386
if (depth == CV_8U)
1387
resizeArea<uchar, ushort, 2, IntCast<uchar, ushort> >(src, dst_reference);
1388
else if (depth == CV_16U)
1389
resizeArea<ushort, uint, 2, IntCast<ushort, uint> >(src, dst_reference);
1390
else if (depth == CV_16S)
1391
resizeArea<short, int, 2, IntCast<short, int> >(src, dst_reference);
1392
else if (depth == CV_32F)
1393
resizeArea<float, float, 0, FltCast<float, float> >(src, dst_reference);
1394
else
1395
CV_Assert(0);
1396
1397
cv::resize(src, dst_actual, dst_actual.size(), 0, 0, cv::INTER_AREA);
1398
1399
ASSERT_GE(eps, cvtest::norm(dst_reference, dst_actual, cv::NORM_INF));
1400
}
1401
}
1402
1403
TEST(Imgproc_Warp, multichannel)
1404
{
1405
static const int inter_types[] = {INTER_NEAREST, INTER_AREA, INTER_CUBIC,
1406
INTER_LANCZOS4, INTER_LINEAR};
1407
static const int inter_n = sizeof(inter_types) / sizeof(int);
1408
1409
static const int border_types[] = {BORDER_CONSTANT, BORDER_DEFAULT,
1410
BORDER_REFLECT, BORDER_REPLICATE,
1411
BORDER_WRAP, BORDER_WRAP};
1412
static const int border_n = sizeof(border_types) / sizeof(int);
1413
1414
RNG& rng = theRNG();
1415
for( int iter = 0; iter < 100; iter++ )
1416
{
1417
int inter = inter_types[rng.uniform(0, inter_n)];
1418
int border = border_types[rng.uniform(0, border_n)];
1419
int width = rng.uniform(3, 333);
1420
int height = rng.uniform(3, 333);
1421
int cn = rng.uniform(1, 15);
1422
if(inter == INTER_CUBIC || inter == INTER_LANCZOS4)
1423
cn = rng.uniform(1, 5);
1424
Mat src(height, width, CV_8UC(cn)), dst;
1425
//randu(src, 0, 256);
1426
src.setTo(0.);
1427
1428
Mat rot = getRotationMatrix2D(Point2f(0.f, 0.f), 1.0, 1.0);
1429
warpAffine(src, dst, rot, src.size(), inter, border);
1430
ASSERT_EQ(0.0, cvtest::norm(dst, NORM_INF));
1431
Mat rot2 = Mat::eye(3, 3, rot.type());
1432
rot.copyTo(rot2.rowRange(0, 2));
1433
warpPerspective(src, dst, rot2, src.size(), inter, border);
1434
ASSERT_EQ(0.0, cvtest::norm(dst, NORM_INF));
1435
}
1436
}
1437
1438
TEST(Imgproc_GetAffineTransform, singularity)
1439
{
1440
Point2f A_sample[3];
1441
A_sample[0] = Point2f(8.f, 9.f);
1442
A_sample[1] = Point2f(40.f, 41.f);
1443
A_sample[2] = Point2f(47.f, 48.f);
1444
Point2f B_sample[3];
1445
B_sample[0] = Point2f(7.37465f, 11.8295f);
1446
B_sample[1] = Point2f(15.0113f, 12.8994f);
1447
B_sample[2] = Point2f(38.9943f, 9.56297f);
1448
Mat trans = getAffineTransform(A_sample, B_sample);
1449
ASSERT_EQ(0.0, cvtest::norm(trans, NORM_INF));
1450
}
1451
1452
TEST(Imgproc_Remap, DISABLED_memleak)
1453
{
1454
Mat src;
1455
const int N = 400;
1456
src.create(N, N, CV_8U);
1457
randu(src, 0, 256);
1458
Mat map_x, map_y, dst;
1459
dst.create( src.size(), src.type() );
1460
map_x.create( src.size(), CV_32FC1 );
1461
map_y.create( src.size(), CV_32FC1 );
1462
randu(map_x, 0., N+0.);
1463
randu(map_y, 0., N+0.);
1464
1465
for( int iter = 0; iter < 10000; iter++ )
1466
{
1467
if(iter % 100 == 0)
1468
{
1469
putchar('.');
1470
fflush(stdout);
1471
}
1472
remap(src, dst, map_x, map_y, CV_INTER_LINEAR);
1473
}
1474
}
1475
1476
//** @deprecated */
1477
TEST(Imgproc_linearPolar, identity)
1478
{
1479
const int N = 33;
1480
Mat in(N, N, CV_8UC3, Scalar(255, 0, 0));
1481
in(cv::Rect(N/3, N/3, N/3, N/3)).setTo(Scalar::all(255));
1482
cv::blur(in, in, Size(5, 5));
1483
cv::blur(in, in, Size(5, 5));
1484
1485
Mat src = in.clone();
1486
Mat dst;
1487
1488
Rect roi = Rect(0, 0, in.cols - ((N+19)/20), in.rows);
1489
1490
for (int i = 1; i <= 5; i++)
1491
{
1492
linearPolar(src, dst,
1493
Point2f((N-1) * 0.5f, (N-1) * 0.5f), N * 0.5f,
1494
CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR | CV_WARP_INVERSE_MAP);
1495
1496
linearPolar(dst, src,
1497
Point2f((N-1) * 0.5f, (N-1) * 0.5f), N * 0.5f,
1498
CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR);
1499
1500
double psnr = cvtest::PSNR(in(roi), src(roi));
1501
EXPECT_LE(25, psnr) << "iteration=" << i;
1502
}
1503
1504
#if 0
1505
Mat all(N*2+2,N*2+2, src.type(), Scalar(0,0,255));
1506
in.copyTo(all(Rect(0,0,N,N)));
1507
src.copyTo(all(Rect(0,N+1,N,N)));
1508
src.copyTo(all(Rect(N+1,0,N,N)));
1509
dst.copyTo(all(Rect(N+1,N+1,N,N)));
1510
imwrite("linearPolar.png", all);
1511
imshow("input", in); imshow("result", dst); imshow("restore", src); imshow("all", all);
1512
cv::waitKey();
1513
#endif
1514
}
1515
1516
//** @deprecated */
1517
TEST(Imgproc_logPolar, identity)
1518
{
1519
const int N = 33;
1520
Mat in(N, N, CV_8UC3, Scalar(255, 0, 0));
1521
in(cv::Rect(N/3, N/3, N/3, N/3)).setTo(Scalar::all(255));
1522
cv::blur(in, in, Size(5, 5));
1523
cv::blur(in, in, Size(5, 5));
1524
1525
Mat src = in.clone();
1526
Mat dst;
1527
1528
Rect roi = Rect(0, 0, in.cols - ((N+19)/20), in.rows);
1529
1530
double M = N/log(N * 0.5f);
1531
for (int i = 1; i <= 5; i++)
1532
{
1533
logPolar(src, dst,
1534
Point2f((N-1) * 0.5f, (N-1) * 0.5f), M,
1535
CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR | CV_WARP_INVERSE_MAP);
1536
1537
logPolar(dst, src,
1538
Point2f((N-1) * 0.5f, (N-1) * 0.5f), M,
1539
CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR);
1540
1541
double psnr = cvtest::PSNR(in(roi), src(roi));
1542
EXPECT_LE(25, psnr) << "iteration=" << i;
1543
}
1544
1545
#if 0
1546
Mat all(N*2+2,N*2+2, src.type(), Scalar(0,0,255));
1547
in.copyTo(all(Rect(0,0,N,N)));
1548
src.copyTo(all(Rect(0,N+1,N,N)));
1549
src.copyTo(all(Rect(N+1,0,N,N)));
1550
dst.copyTo(all(Rect(N+1,N+1,N,N)));
1551
imwrite("logPolar.png", all);
1552
imshow("input", in); imshow("result", dst); imshow("restore", src); imshow("all", all);
1553
cv::waitKey();
1554
#endif
1555
}
1556
1557
TEST(Imgproc_warpPolar, identity)
1558
{
1559
const int N = 33;
1560
Mat in(N, N, CV_8UC3, Scalar(255, 0, 0));
1561
in(cv::Rect(N / 3, N / 3, N / 3, N / 3)).setTo(Scalar::all(255));
1562
cv::blur(in, in, Size(5, 5));
1563
cv::blur(in, in, Size(5, 5));
1564
1565
Mat src = in.clone();
1566
Mat dst;
1567
1568
Rect roi = Rect(0, 0, in.cols - ((N + 19) / 20), in.rows);
1569
Point2f center = Point2f((N - 1) * 0.5f, (N - 1) * 0.5f);
1570
double radius = N * 0.5;
1571
int flags = CV_WARP_FILL_OUTLIERS | CV_INTER_LINEAR;
1572
// test linearPolar
1573
for (int ki = 1; ki <= 5; ki++)
1574
{
1575
warpPolar(src, dst, src.size(), center, radius, flags + WARP_POLAR_LINEAR + CV_WARP_INVERSE_MAP);
1576
warpPolar(dst, src, src.size(), center, radius, flags + WARP_POLAR_LINEAR);
1577
1578
double psnr = cv::PSNR(in(roi), src(roi));
1579
EXPECT_LE(25, psnr) << "iteration=" << ki;
1580
}
1581
// test logPolar
1582
src = in.clone();
1583
for (int ki = 1; ki <= 5; ki++)
1584
{
1585
warpPolar(src, dst, src.size(),center, radius, flags + WARP_POLAR_LOG + CV_WARP_INVERSE_MAP );
1586
warpPolar(dst, src, src.size(),center, radius, flags + WARP_POLAR_LOG);
1587
1588
double psnr = cv::PSNR(in(roi), src(roi));
1589
EXPECT_LE(25, psnr) << "iteration=" << ki;
1590
}
1591
1592
#if 0
1593
Mat all(N*2+2,N*2+2, src.type(), Scalar(0,0,255));
1594
in.copyTo(all(Rect(0,0,N,N)));
1595
src.copyTo(all(Rect(0,N+1,N,N)));
1596
src.copyTo(all(Rect(N+1,0,N,N)));
1597
dst.copyTo(all(Rect(N+1,N+1,N,N)));
1598
imwrite("linearPolar.png", all);
1599
imshow("input", in); imshow("result", dst); imshow("restore", src); imshow("all", all);
1600
cv::waitKey();
1601
#endif
1602
}
1603
1604
}} // namespace
1605
/* End of file. */
1606
1607