Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/calib3d/test/test_undistort.cpp
16337 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
// License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15
// Third party copyrights are property of their respective owners.
16
//
17
// Redistribution and use in source and binary forms, with or without modification,
18
// are permitted provided that the following conditions are met:
19
//
20
// * Redistribution's of source code must retain the above copyright notice,
21
// this list of conditions and the following disclaimer.
22
//
23
// * Redistribution's in binary form must reproduce the above copyright notice,
24
// this list of conditions and the following disclaimer in the documentation
25
// and/or other materials provided with the distribution.
26
//
27
// * The name of the copyright holders may not be used to endorse or promote products
28
// derived from this software without specific prior written permission.
29
//
30
// This software is provided by the copyright holders and contributors "as is" and
31
// any express or implied warranties, including, but not limited to, the implied
32
// warranties of merchantability and fitness for a particular purpose are disclaimed.
33
// In no event shall the Intel Corporation or contributors be liable for any direct,
34
// indirect, incidental, special, exemplary, or consequential damages
35
// (including, but not limited to, procurement of substitute goods or services;
36
// loss of use, data, or profits; or business interruption) however caused
37
// and on any theory of liability, whether in contract, strict liability,
38
// or tort (including negligence or otherwise) arising in any way out of
39
// the use of this software, even if advised of the possibility of such damage.
40
//
41
//M*/
42
43
#include "test_precomp.hpp"
44
#include "opencv2/imgproc/imgproc_c.h"
45
#include "opencv2/calib3d/calib3d_c.h"
46
47
namespace opencv_test { namespace {
48
49
class CV_DefaultNewCameraMatrixTest : public cvtest::ArrayTest
50
{
51
public:
52
CV_DefaultNewCameraMatrixTest();
53
protected:
54
int prepare_test_case (int test_case_idx);
55
void prepare_to_validation( int test_case_idx );
56
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
57
void run_func();
58
59
private:
60
cv::Size img_size;
61
cv::Mat camera_mat;
62
cv::Mat new_camera_mat;
63
64
int matrix_type;
65
66
bool center_principal_point;
67
68
static const int MAX_X = 2048;
69
static const int MAX_Y = 2048;
70
//static const int MAX_VAL = 10000;
71
};
72
73
CV_DefaultNewCameraMatrixTest::CV_DefaultNewCameraMatrixTest()
74
{
75
test_array[INPUT].push_back(NULL);
76
test_array[OUTPUT].push_back(NULL);
77
test_array[REF_OUTPUT].push_back(NULL);
78
79
matrix_type = 0;
80
center_principal_point = false;
81
}
82
83
void CV_DefaultNewCameraMatrixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
84
{
85
cvtest::ArrayTest::get_test_array_types_and_sizes(test_case_idx,sizes,types);
86
RNG& rng = ts->get_rng();
87
matrix_type = types[INPUT][0] = types[OUTPUT][0]= types[REF_OUTPUT][0] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
88
sizes[INPUT][0] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(3,3);
89
}
90
91
int CV_DefaultNewCameraMatrixTest::prepare_test_case(int test_case_idx)
92
{
93
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
94
95
if (code <= 0)
96
return code;
97
98
RNG& rng = ts->get_rng();
99
100
img_size.width = cvtest::randInt(rng) % MAX_X + 1;
101
img_size.height = cvtest::randInt(rng) % MAX_Y + 1;
102
103
center_principal_point = ((cvtest::randInt(rng) % 2)!=0);
104
105
// Generating camera_mat matrix
106
double sz = MAX(img_size.width, img_size.height);
107
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
108
double a[9] = {0,0,0,0,0,0,0,0,1};
109
Mat _a(3,3,CV_64F,a);
110
a[2] = (img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
111
a[5] = (img_size.height - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
112
a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
113
a[4] = aspect_ratio*a[0];
114
115
Mat& _a0 = test_mat[INPUT][0];
116
cvtest::convert(_a, _a0, _a0.type());
117
camera_mat = _a0;
118
119
return code;
120
121
}
122
123
void CV_DefaultNewCameraMatrixTest::run_func()
124
{
125
new_camera_mat = cv::getDefaultNewCameraMatrix(camera_mat,img_size,center_principal_point);
126
}
127
128
void CV_DefaultNewCameraMatrixTest::prepare_to_validation( int /*test_case_idx*/ )
129
{
130
const Mat& src = test_mat[INPUT][0];
131
Mat& dst = test_mat[REF_OUTPUT][0];
132
Mat& test_output = test_mat[OUTPUT][0];
133
Mat& output = new_camera_mat;
134
cvtest::convert( output, test_output, test_output.type() );
135
if (!center_principal_point)
136
{
137
cvtest::copy(src, dst);
138
}
139
else
140
{
141
double a[9] = {0,0,0,0,0,0,0,0,1};
142
Mat _a(3,3,CV_64F,a);
143
if (matrix_type == CV_64F)
144
{
145
a[0] = src.at<double>(0,0);
146
a[4] = src.at<double>(1,1);
147
}
148
else
149
{
150
a[0] = src.at<float>(0,0);
151
a[4] = src.at<float>(1,1);
152
}
153
a[2] = (img_size.width - 1)*0.5;
154
a[5] = (img_size.height - 1)*0.5;
155
cvtest::convert( _a, dst, dst.type() );
156
}
157
}
158
159
//---------
160
161
class CV_UndistortPointsTest : public cvtest::ArrayTest
162
{
163
public:
164
CV_UndistortPointsTest();
165
protected:
166
int prepare_test_case (int test_case_idx);
167
void prepare_to_validation( int test_case_idx );
168
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
169
double get_success_error_level( int test_case_idx, int i, int j );
170
void run_func();
171
void distortPoints(const CvMat* _src, CvMat* _dst, const CvMat* _cameraMatrix,
172
const CvMat* _distCoeffs, const CvMat* matR, const CvMat* matP);
173
174
private:
175
bool useCPlus;
176
bool useDstMat;
177
static const int N_POINTS = 10;
178
static const int MAX_X = 2048;
179
static const int MAX_Y = 2048;
180
181
bool zero_new_cam;
182
bool zero_distortion;
183
bool zero_R;
184
185
cv::Size img_size;
186
cv::Mat dst_points_mat;
187
188
cv::Mat camera_mat;
189
cv::Mat R;
190
cv::Mat P;
191
cv::Mat distortion_coeffs;
192
cv::Mat src_points;
193
std::vector<cv::Point2f> dst_points;
194
};
195
196
CV_UndistortPointsTest::CV_UndistortPointsTest()
197
{
198
test_array[INPUT].push_back(NULL); // points matrix
199
test_array[INPUT].push_back(NULL); // camera matrix
200
test_array[INPUT].push_back(NULL); // distortion coeffs
201
test_array[INPUT].push_back(NULL); // R matrix
202
test_array[INPUT].push_back(NULL); // P matrix
203
test_array[OUTPUT].push_back(NULL); // distorted dst points
204
test_array[TEMP].push_back(NULL); // dst points
205
test_array[REF_OUTPUT].push_back(NULL);
206
207
useCPlus = useDstMat = false;
208
zero_new_cam = zero_distortion = zero_R = false;
209
}
210
211
void CV_UndistortPointsTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
212
{
213
cvtest::ArrayTest::get_test_array_types_and_sizes(test_case_idx,sizes,types);
214
RNG& rng = ts->get_rng();
215
useCPlus = ((cvtest::randInt(rng) % 2)!=0);
216
//useCPlus = 0;
217
if (useCPlus)
218
{
219
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0]= CV_32FC2;
220
}
221
else
222
{
223
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0]= cvtest::randInt(rng)%2 ? CV_64FC2 : CV_32FC2;
224
}
225
types[INPUT][1] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
226
types[INPUT][2] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
227
types[INPUT][3] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
228
types[INPUT][4] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
229
230
sizes[INPUT][0] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sizes[TEMP][0]= cvtest::randInt(rng)%2 ? cvSize(1,N_POINTS) : cvSize(N_POINTS,1);
231
sizes[INPUT][1] = sizes[INPUT][3] = cvSize(3,3);
232
sizes[INPUT][4] = cvtest::randInt(rng)%2 ? cvSize(3,3) : cvSize(4,3);
233
234
if (cvtest::randInt(rng)%2)
235
{
236
if (cvtest::randInt(rng)%2)
237
{
238
sizes[INPUT][2] = cvSize(1,4);
239
}
240
else
241
{
242
sizes[INPUT][2] = cvSize(1,5);
243
}
244
}
245
else
246
{
247
if (cvtest::randInt(rng)%2)
248
{
249
sizes[INPUT][2] = cvSize(4,1);
250
}
251
else
252
{
253
sizes[INPUT][2] = cvSize(5,1);
254
}
255
}
256
}
257
258
int CV_UndistortPointsTest::prepare_test_case(int test_case_idx)
259
{
260
RNG& rng = ts->get_rng();
261
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
262
263
if (code <= 0)
264
return code;
265
266
useDstMat = (cvtest::randInt(rng) % 2) == 0;
267
268
img_size.width = cvtest::randInt(rng) % MAX_X + 1;
269
img_size.height = cvtest::randInt(rng) % MAX_Y + 1;
270
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
271
double cam[9] = {0,0,0,0,0,0,0,0,1};
272
vector<double> dist(dist_size);
273
vector<double> proj(test_mat[INPUT][4].cols * test_mat[INPUT][4].rows);
274
vector<Point2d> points(N_POINTS);
275
276
Mat _camera(3,3,CV_64F,cam);
277
Mat _distort(test_mat[INPUT][2].rows,test_mat[INPUT][2].cols,CV_64F,&dist[0]);
278
Mat _proj(test_mat[INPUT][4].size(), CV_64F, &proj[0]);
279
Mat _points(test_mat[INPUT][0].size(), CV_64FC2, &points[0]);
280
281
_proj = Scalar::all(0);
282
283
//Generating points
284
for( int i = 0; i < N_POINTS; i++ )
285
{
286
points[i].x = cvtest::randReal(rng)*img_size.width;
287
points[i].y = cvtest::randReal(rng)*img_size.height;
288
}
289
290
//Generating camera matrix
291
double sz = MAX(img_size.width,img_size.height);
292
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
293
cam[2] = (img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
294
cam[5] = (img_size.height - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
295
cam[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
296
cam[4] = aspect_ratio*cam[0];
297
298
//Generating distortion coeffs
299
dist[0] = cvtest::randReal(rng)*0.06 - 0.03;
300
dist[1] = cvtest::randReal(rng)*0.06 - 0.03;
301
if( dist[0]*dist[1] > 0 )
302
dist[1] = -dist[1];
303
if( cvtest::randInt(rng)%4 != 0 )
304
{
305
dist[2] = cvtest::randReal(rng)*0.004 - 0.002;
306
dist[3] = cvtest::randReal(rng)*0.004 - 0.002;
307
if (dist_size > 4)
308
dist[4] = cvtest::randReal(rng)*0.004 - 0.002;
309
}
310
else
311
{
312
dist[2] = dist[3] = 0;
313
if (dist_size > 4)
314
dist[4] = 0;
315
}
316
317
//Generating P matrix (projection)
318
if( test_mat[INPUT][4].cols != 4 )
319
{
320
proj[8] = 1;
321
if (cvtest::randInt(rng)%2 == 0) // use identity new camera matrix
322
{
323
proj[0] = 1;
324
proj[4] = 1;
325
}
326
else
327
{
328
proj[0] = cam[0] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[0]; //10%
329
proj[4] = cam[4] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[4]; //10%
330
proj[2] = cam[2] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.width; //15%
331
proj[5] = cam[5] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.height; //15%
332
}
333
}
334
else
335
{
336
proj[10] = 1;
337
proj[0] = cam[0] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[0]; //10%
338
proj[5] = cam[4] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[4]; //10%
339
proj[2] = cam[2] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.width; //15%
340
proj[6] = cam[5] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.height; //15%
341
342
proj[3] = (img_size.height + img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
343
proj[7] = (img_size.height + img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
344
proj[11] = (img_size.height + img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
345
}
346
347
//Generating R matrix
348
Mat _rot(3,3,CV_64F);
349
Mat rotation(1,3,CV_64F);
350
rotation.at<double>(0) = CV_PI*(cvtest::randReal(rng) - (double)0.5); // phi
351
rotation.at<double>(1) = CV_PI*(cvtest::randReal(rng) - (double)0.5); // ksi
352
rotation.at<double>(2) = CV_PI*(cvtest::randReal(rng) - (double)0.5); //khi
353
cvtest::Rodrigues(rotation, _rot);
354
355
//copying data
356
//src_points = &_points;
357
_points.convertTo(test_mat[INPUT][0], test_mat[INPUT][0].type());
358
_camera.convertTo(test_mat[INPUT][1], test_mat[INPUT][1].type());
359
_distort.convertTo(test_mat[INPUT][2], test_mat[INPUT][2].type());
360
_rot.convertTo(test_mat[INPUT][3], test_mat[INPUT][3].type());
361
_proj.convertTo(test_mat[INPUT][4], test_mat[INPUT][4].type());
362
363
zero_distortion = (cvtest::randInt(rng)%2) == 0 ? false : true;
364
zero_new_cam = (cvtest::randInt(rng)%2) == 0 ? false : true;
365
zero_R = (cvtest::randInt(rng)%2) == 0 ? false : true;
366
367
if (useCPlus)
368
{
369
_points.convertTo(src_points, CV_32F);
370
371
camera_mat = test_mat[INPUT][1];
372
distortion_coeffs = test_mat[INPUT][2];
373
R = test_mat[INPUT][3];
374
P = test_mat[INPUT][4];
375
}
376
377
return code;
378
}
379
380
void CV_UndistortPointsTest::prepare_to_validation(int /*test_case_idx*/)
381
{
382
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
383
double cam[9] = {0,0,0,0,0,0,0,0,1};
384
double rot[9] = {1,0,0,0,1,0,0,0,1};
385
386
double* dist = new double[dist_size ];
387
double* proj = new double[test_mat[INPUT][4].cols * test_mat[INPUT][4].rows];
388
double* points = new double[N_POINTS*2];
389
double* r_points = new double[N_POINTS*2];
390
//Run reference calculations
391
CvMat ref_points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,r_points);
392
CvMat _camera = cvMat(3,3,CV_64F,cam);
393
CvMat _rot = cvMat(3,3,CV_64F,rot);
394
CvMat _distort = cvMat(test_mat[INPUT][2].rows,test_mat[INPUT][2].cols,CV_64F,dist);
395
CvMat _proj = cvMat(test_mat[INPUT][4].rows,test_mat[INPUT][4].cols,CV_64F,proj);
396
CvMat _points= cvMat(test_mat[TEMP][0].rows,test_mat[TEMP][0].cols,CV_64FC2,points);
397
398
Mat __camera = cvarrToMat(&_camera);
399
Mat __distort = cvarrToMat(&_distort);
400
Mat __rot = cvarrToMat(&_rot);
401
Mat __proj = cvarrToMat(&_proj);
402
Mat __points = cvarrToMat(&_points);
403
Mat _ref_points = cvarrToMat(&ref_points);
404
405
cvtest::convert(test_mat[INPUT][1], __camera, __camera.type());
406
cvtest::convert(test_mat[INPUT][2], __distort, __distort.type());
407
cvtest::convert(test_mat[INPUT][3], __rot, __rot.type());
408
cvtest::convert(test_mat[INPUT][4], __proj, __proj.type());
409
410
if (useCPlus)
411
{
412
if (useDstMat)
413
{
414
CvMat temp = cvMat(dst_points_mat);
415
for (int i=0;i<N_POINTS*2;i++)
416
{
417
points[i] = temp.data.fl[i];
418
}
419
}
420
else
421
{
422
for (int i=0;i<N_POINTS;i++)
423
{
424
points[2*i] = dst_points[i].x;
425
points[2*i+1] = dst_points[i].y;
426
}
427
}
428
}
429
else
430
{
431
cvtest::convert(test_mat[TEMP][0],__points, __points.type());
432
}
433
434
CvMat* input2 = zero_distortion ? 0 : &_distort;
435
CvMat* input3 = zero_R ? 0 : &_rot;
436
CvMat* input4 = zero_new_cam ? 0 : &_proj;
437
distortPoints(&_points,&ref_points,&_camera,input2,input3,input4);
438
439
Mat& dst = test_mat[REF_OUTPUT][0];
440
cvtest::convert(_ref_points, dst, dst.type());
441
442
cvtest::copy(test_mat[INPUT][0], test_mat[OUTPUT][0]);
443
444
delete[] dist;
445
delete[] proj;
446
delete[] points;
447
delete[] r_points;
448
}
449
450
void CV_UndistortPointsTest::run_func()
451
{
452
453
if (useCPlus)
454
{
455
cv::Mat input2,input3,input4;
456
input2 = zero_distortion ? cv::Mat() : cv::Mat(test_mat[INPUT][2]);
457
input3 = zero_R ? cv::Mat() : cv::Mat(test_mat[INPUT][3]);
458
input4 = zero_new_cam ? cv::Mat() : cv::Mat(test_mat[INPUT][4]);
459
460
if (useDstMat)
461
{
462
//cv::undistortPoints(src_points,dst_points_mat,camera_mat,distortion_coeffs,R,P);
463
cv::undistortPoints(src_points,dst_points_mat,camera_mat,input2,input3,input4);
464
}
465
else
466
{
467
//cv::undistortPoints(src_points,dst_points,camera_mat,distortion_coeffs,R,P);
468
cv::undistortPoints(src_points,dst_points,camera_mat,input2,input3,input4);
469
}
470
}
471
else
472
{
473
CvMat _input0 = cvMat(test_mat[INPUT][0]), _input1 = cvMat(test_mat[INPUT][1]), _input2, _input3, _input4;
474
CvMat _output = cvMat(test_mat[TEMP][0]);
475
if(!zero_distortion)
476
_input2 = cvMat(test_mat[INPUT][2]);
477
if(!zero_R)
478
_input3 = cvMat(test_mat[INPUT][3]);
479
if(!zero_new_cam)
480
_input4 = cvMat(test_mat[INPUT][4]);
481
cvUndistortPoints(&_input0, &_output, &_input1,
482
zero_distortion ? 0 : &_input2,
483
zero_R ? 0 : &_input3,
484
zero_new_cam ? 0 : &_input4);
485
}
486
}
487
488
void CV_UndistortPointsTest::distortPoints(const CvMat* _src, CvMat* _dst, const CvMat* _cameraMatrix,
489
const CvMat* _distCoeffs,
490
const CvMat* matR, const CvMat* matP)
491
{
492
double a[9];
493
494
CvMat* __P;
495
if ((!matP)||(matP->cols == 3))
496
__P = cvCreateMat(3,3,CV_64F);
497
else
498
__P = cvCreateMat(3,4,CV_64F);
499
if (matP)
500
{
501
cvtest::convert(cvarrToMat(matP), cvarrToMat(__P), -1);
502
}
503
else
504
{
505
cvZero(__P);
506
__P->data.db[0] = 1;
507
__P->data.db[4] = 1;
508
__P->data.db[8] = 1;
509
}
510
CvMat* __R = cvCreateMat(3,3,CV_64F);
511
if (matR)
512
{
513
cvCopy(matR,__R);
514
}
515
else
516
{
517
cvZero(__R);
518
__R->data.db[0] = 1;
519
__R->data.db[4] = 1;
520
__R->data.db[8] = 1;
521
}
522
for (int i=0;i<N_POINTS;i++)
523
{
524
int movement = __P->cols > 3 ? 1 : 0;
525
double x = (_src->data.db[2*i]-__P->data.db[2])/__P->data.db[0];
526
double y = (_src->data.db[2*i+1]-__P->data.db[5+movement])/__P->data.db[4+movement];
527
CvMat inverse = cvMat(3,3,CV_64F,a);
528
cvInvert(__R,&inverse);
529
double w1 = x*inverse.data.db[6]+y*inverse.data.db[7]+inverse.data.db[8];
530
double _x = (x*inverse.data.db[0]+y*inverse.data.db[1]+inverse.data.db[2])/w1;
531
double _y = (x*inverse.data.db[3]+y*inverse.data.db[4]+inverse.data.db[5])/w1;
532
533
//Distortions
534
535
double __x = _x;
536
double __y = _y;
537
if (_distCoeffs)
538
{
539
double r2 = _x*_x+_y*_y;
540
541
__x = _x*(1+_distCoeffs->data.db[0]*r2+_distCoeffs->data.db[1]*r2*r2)+
542
2*_distCoeffs->data.db[2]*_x*_y+_distCoeffs->data.db[3]*(r2+2*_x*_x);
543
__y = _y*(1+_distCoeffs->data.db[0]*r2+_distCoeffs->data.db[1]*r2*r2)+
544
2*_distCoeffs->data.db[3]*_x*_y+_distCoeffs->data.db[2]*(r2+2*_y*_y);
545
if ((_distCoeffs->cols > 4) || (_distCoeffs->rows > 4))
546
{
547
__x+=_x*_distCoeffs->data.db[4]*r2*r2*r2;
548
__y+=_y*_distCoeffs->data.db[4]*r2*r2*r2;
549
}
550
}
551
552
553
_dst->data.db[2*i] = __x*_cameraMatrix->data.db[0]+_cameraMatrix->data.db[2];
554
_dst->data.db[2*i+1] = __y*_cameraMatrix->data.db[4]+_cameraMatrix->data.db[5];
555
556
}
557
558
cvReleaseMat(&__R);
559
cvReleaseMat(&__P);
560
561
}
562
563
564
double CV_UndistortPointsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
565
{
566
return 5e-2;
567
}
568
569
//------------------------------------------------------
570
571
class CV_InitUndistortRectifyMapTest : public cvtest::ArrayTest
572
{
573
public:
574
CV_InitUndistortRectifyMapTest();
575
protected:
576
int prepare_test_case (int test_case_idx);
577
void prepare_to_validation( int test_case_idx );
578
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
579
double get_success_error_level( int test_case_idx, int i, int j );
580
void run_func();
581
582
private:
583
bool useCPlus;
584
static const int N_POINTS = 100;
585
static const int MAX_X = 2048;
586
static const int MAX_Y = 2048;
587
bool zero_new_cam;
588
bool zero_distortion;
589
bool zero_R;
590
591
592
cv::Size img_size;
593
594
cv::Mat camera_mat;
595
cv::Mat R;
596
cv::Mat new_camera_mat;
597
cv::Mat distortion_coeffs;
598
cv::Mat mapx;
599
cv::Mat mapy;
600
CvMat* _mapx;
601
CvMat* _mapy;
602
int mat_type;
603
};
604
605
CV_InitUndistortRectifyMapTest::CV_InitUndistortRectifyMapTest()
606
{
607
test_array[INPUT].push_back(NULL); // test points matrix
608
test_array[INPUT].push_back(NULL); // camera matrix
609
test_array[INPUT].push_back(NULL); // distortion coeffs
610
test_array[INPUT].push_back(NULL); // R matrix
611
test_array[INPUT].push_back(NULL); // new camera matrix
612
test_array[OUTPUT].push_back(NULL); // distorted dst points
613
test_array[REF_OUTPUT].push_back(NULL);
614
615
useCPlus = false;
616
zero_distortion = zero_new_cam = zero_R = false;
617
_mapx = _mapy = NULL;
618
mat_type = 0;
619
}
620
621
void CV_InitUndistortRectifyMapTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
622
{
623
cvtest::ArrayTest::get_test_array_types_and_sizes(test_case_idx,sizes,types);
624
RNG& rng = ts->get_rng();
625
useCPlus = ((cvtest::randInt(rng) % 2)!=0);
626
//useCPlus = 0;
627
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC2;
628
629
types[INPUT][1] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
630
types[INPUT][2] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
631
types[INPUT][3] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
632
types[INPUT][4] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
633
634
sizes[INPUT][0] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(N_POINTS,1);
635
sizes[INPUT][1] = sizes[INPUT][3] = cvSize(3,3);
636
sizes[INPUT][4] = cvSize(3,3);
637
638
if (cvtest::randInt(rng)%2)
639
{
640
if (cvtest::randInt(rng)%2)
641
{
642
sizes[INPUT][2] = cvSize(1,4);
643
}
644
else
645
{
646
sizes[INPUT][2] = cvSize(1,5);
647
}
648
}
649
else
650
{
651
if (cvtest::randInt(rng)%2)
652
{
653
sizes[INPUT][2] = cvSize(4,1);
654
}
655
else
656
{
657
sizes[INPUT][2] = cvSize(5,1);
658
}
659
}
660
}
661
662
663
int CV_InitUndistortRectifyMapTest::prepare_test_case(int test_case_idx)
664
{
665
RNG& rng = ts->get_rng();
666
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
667
668
if (code <= 0)
669
return code;
670
671
img_size.width = cvtest::randInt(rng) % MAX_X + 1;
672
img_size.height = cvtest::randInt(rng) % MAX_Y + 1;
673
674
if (useCPlus)
675
{
676
mat_type = (cvtest::randInt(rng) % 2) == 0 ? CV_32FC1 : CV_16SC2;
677
if ((cvtest::randInt(rng) % 4) == 0)
678
mat_type = -1;
679
if ((cvtest::randInt(rng) % 4) == 0)
680
mat_type = CV_32FC2;
681
_mapx = 0;
682
_mapy = 0;
683
}
684
else
685
{
686
int typex = (cvtest::randInt(rng) % 2) == 0 ? CV_32FC1 : CV_16SC2;
687
//typex = CV_32FC1; ///!!!!!!!!!!!!!!!!
688
int typey = (typex == CV_32FC1) ? CV_32FC1 : CV_16UC1;
689
690
_mapx = cvCreateMat(img_size.height,img_size.width,typex);
691
_mapy = cvCreateMat(img_size.height,img_size.width,typey);
692
693
694
}
695
696
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
697
double cam[9] = {0,0,0,0,0,0,0,0,1};
698
vector<double> dist(dist_size);
699
vector<double> new_cam(test_mat[INPUT][4].cols * test_mat[INPUT][4].rows);
700
vector<Point2d> points(N_POINTS);
701
702
Mat _camera(3,3,CV_64F,cam);
703
Mat _distort(test_mat[INPUT][2].size(),CV_64F,&dist[0]);
704
Mat _new_cam(test_mat[INPUT][4].size(),CV_64F,&new_cam[0]);
705
Mat _points(test_mat[INPUT][0].size(),CV_64FC2, &points[0]);
706
707
//Generating points
708
for (int i=0;i<N_POINTS;i++)
709
{
710
points[i].x = cvtest::randReal(rng)*img_size.width;
711
points[i].y = cvtest::randReal(rng)*img_size.height;
712
}
713
714
//Generating camera matrix
715
double sz = MAX(img_size.width,img_size.height);
716
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
717
cam[2] = (img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
718
cam[5] = (img_size.height - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
719
cam[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
720
cam[4] = aspect_ratio*cam[0];
721
722
//Generating distortion coeffs
723
dist[0] = cvtest::randReal(rng)*0.06 - 0.03;
724
dist[1] = cvtest::randReal(rng)*0.06 - 0.03;
725
if( dist[0]*dist[1] > 0 )
726
dist[1] = -dist[1];
727
if( cvtest::randInt(rng)%4 != 0 )
728
{
729
dist[2] = cvtest::randReal(rng)*0.004 - 0.002;
730
dist[3] = cvtest::randReal(rng)*0.004 - 0.002;
731
if (dist_size > 4)
732
dist[4] = cvtest::randReal(rng)*0.004 - 0.002;
733
}
734
else
735
{
736
dist[2] = dist[3] = 0;
737
if (dist_size > 4)
738
dist[4] = 0;
739
}
740
741
//Generating new camera matrix
742
_new_cam = Scalar::all(0);
743
new_cam[8] = 1;
744
745
//new_cam[0] = cam[0];
746
//new_cam[4] = cam[4];
747
//new_cam[2] = cam[2];
748
//new_cam[5] = cam[5];
749
750
new_cam[0] = cam[0] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[0]; //10%
751
new_cam[4] = cam[4] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[4]; //10%
752
new_cam[2] = cam[2] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.width; //15%
753
new_cam[5] = cam[5] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.height; //15%
754
755
756
//Generating R matrix
757
Mat _rot(3,3,CV_64F);
758
Mat rotation(1,3,CV_64F);
759
rotation.at<double>(0) = CV_PI/8*(cvtest::randReal(rng) - (double)0.5); // phi
760
rotation.at<double>(1) = CV_PI/8*(cvtest::randReal(rng) - (double)0.5); // ksi
761
rotation.at<double>(2) = CV_PI/3*(cvtest::randReal(rng) - (double)0.5); //khi
762
cvtest::Rodrigues(rotation, _rot);
763
764
//cvSetIdentity(_rot);
765
//copying data
766
cvtest::convert( _points, test_mat[INPUT][0], test_mat[INPUT][0].type());
767
cvtest::convert( _camera, test_mat[INPUT][1], test_mat[INPUT][1].type());
768
cvtest::convert( _distort, test_mat[INPUT][2], test_mat[INPUT][2].type());
769
cvtest::convert( _rot, test_mat[INPUT][3], test_mat[INPUT][3].type());
770
cvtest::convert( _new_cam, test_mat[INPUT][4], test_mat[INPUT][4].type());
771
772
zero_distortion = (cvtest::randInt(rng)%2) == 0 ? false : true;
773
zero_new_cam = (cvtest::randInt(rng)%2) == 0 ? false : true;
774
zero_R = (cvtest::randInt(rng)%2) == 0 ? false : true;
775
776
if (useCPlus)
777
{
778
camera_mat = test_mat[INPUT][1];
779
distortion_coeffs = test_mat[INPUT][2];
780
R = test_mat[INPUT][3];
781
new_camera_mat = test_mat[INPUT][4];
782
}
783
784
return code;
785
}
786
787
void CV_InitUndistortRectifyMapTest::prepare_to_validation(int/* test_case_idx*/)
788
{
789
#if 0
790
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
791
double cam[9] = {0,0,0,0,0,0,0,0,1};
792
double rot[9] = {1,0,0,0,1,0,0,0,1};
793
vector<double> dist(dist_size);
794
vector<double> new_cam(test_mat[INPUT][4].cols * test_mat[INPUT][4].rows);
795
vector<Point2d> points(N_POINTS);
796
vector<Point2d> r_points(N_POINTS);
797
//Run reference calculations
798
Mat ref_points(test_mat[INPUT][0].size(),CV_64FC2,&r_points[0]);
799
Mat _camera(3,3,CV_64F,cam);
800
Mat _rot(3,3,CV_64F,rot);
801
Mat _distort(test_mat[INPUT][2].size(),CV_64F,&dist[0]);
802
Mat _new_cam(test_mat[INPUT][4].size(),CV_64F,&new_cam[0]);
803
Mat _points(test_mat[INPUT][0].size(),CV_64FC2,&points[0]);
804
805
cvtest::convert(test_mat[INPUT][1],_camera,_camera.type());
806
cvtest::convert(test_mat[INPUT][2],_distort,_distort.type());
807
cvtest::convert(test_mat[INPUT][3],_rot,_rot.type());
808
cvtest::convert(test_mat[INPUT][4],_new_cam,_new_cam.type());
809
810
//Applying precalculated undistort rectify map
811
if (!useCPlus)
812
{
813
mapx = cv::Mat(_mapx);
814
mapy = cv::Mat(_mapy);
815
}
816
cv::Mat map1,map2;
817
cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1);
818
CvMat _map1 = map1;
819
CvMat _map2 = map2;
820
const Point2d* sptr = (const Point2d*)test_mat[INPUT][0].data;
821
for( int i = 0;i < N_POINTS; i++ )
822
{
823
int u = saturate_cast<int>(sptr[i].x);
824
int v = saturate_cast<int>(sptr[i].y);
825
points[i].x = _map1.data.fl[v*_map1.cols + u];
826
points[i].y = _map2.data.fl[v*_map2.cols + u];
827
}
828
829
//---
830
831
cv::undistortPoints(_points, ref_points, _camera,
832
zero_distortion ? Mat() : _distort,
833
zero_R ? Mat::eye(3,3,CV_64F) : _rot,
834
zero_new_cam ? _camera : _new_cam);
835
//cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam);
836
cvtest::convert(ref_points, test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].type());
837
cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]);
838
839
cvReleaseMat(&_mapx);
840
cvReleaseMat(&_mapy);
841
#else
842
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
843
double cam[9] = {0,0,0,0,0,0,0,0,1};
844
double rot[9] = {1,0,0,0,1,0,0,0,1};
845
double* dist = new double[dist_size ];
846
double* new_cam = new double[test_mat[INPUT][4].cols * test_mat[INPUT][4].rows];
847
double* points = new double[N_POINTS*2];
848
double* r_points = new double[N_POINTS*2];
849
//Run reference calculations
850
CvMat ref_points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,r_points);
851
CvMat _camera = cvMat(3,3,CV_64F,cam);
852
CvMat _rot = cvMat(3,3,CV_64F,rot);
853
CvMat _distort = cvMat(test_mat[INPUT][2].rows,test_mat[INPUT][2].cols,CV_64F,dist);
854
CvMat _new_cam = cvMat(test_mat[INPUT][4].rows,test_mat[INPUT][4].cols,CV_64F,new_cam);
855
CvMat _points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,points);
856
857
CvMat _input1 = cvMat(test_mat[INPUT][1]);
858
CvMat _input2 = cvMat(test_mat[INPUT][2]);
859
CvMat _input3 = cvMat(test_mat[INPUT][3]);
860
CvMat _input4 = cvMat(test_mat[INPUT][4]);
861
862
cvtest::convert(cvarrToMat(&_input1), cvarrToMat(&_camera), -1);
863
cvtest::convert(cvarrToMat(&_input2), cvarrToMat(&_distort), -1);
864
cvtest::convert(cvarrToMat(&_input3), cvarrToMat(&_rot), -1);
865
cvtest::convert(cvarrToMat(&_input4), cvarrToMat(&_new_cam), -1);
866
867
//Applying precalculated undistort rectify map
868
if (!useCPlus)
869
{
870
mapx = cv::cvarrToMat(_mapx);
871
mapy = cv::cvarrToMat(_mapy);
872
}
873
cv::Mat map1,map2;
874
cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1);
875
CvMat _map1 = cvMat(map1);
876
CvMat _map2 = cvMat(map2);
877
for (int i=0;i<N_POINTS;i++)
878
{
879
double u = test_mat[INPUT][0].ptr<double>()[2*i];
880
double v = test_mat[INPUT][0].ptr<double>()[2*i+1];
881
_points.data.db[2*i] = (double)_map1.data.fl[(int)v*_map1.cols+(int)u];
882
_points.data.db[2*i+1] = (double)_map2.data.fl[(int)v*_map2.cols+(int)u];
883
}
884
885
//---
886
887
cvUndistortPoints(&_points,&ref_points,&_camera,
888
zero_distortion ? 0 : &_distort, zero_R ? 0 : &_rot, zero_new_cam ? &_camera : &_new_cam);
889
//cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam);
890
CvMat dst = cvMat(test_mat[REF_OUTPUT][0]);
891
cvtest::convert(cvarrToMat(&ref_points), cvarrToMat(&dst), -1);
892
893
cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]);
894
895
delete[] dist;
896
delete[] new_cam;
897
delete[] points;
898
delete[] r_points;
899
cvReleaseMat(&_mapx);
900
cvReleaseMat(&_mapy);
901
#endif
902
}
903
904
void CV_InitUndistortRectifyMapTest::run_func()
905
{
906
if (useCPlus)
907
{
908
cv::Mat input2,input3,input4;
909
input2 = zero_distortion ? cv::Mat() : test_mat[INPUT][2];
910
input3 = zero_R ? cv::Mat() : test_mat[INPUT][3];
911
input4 = zero_new_cam ? cv::Mat() : test_mat[INPUT][4];
912
cv::initUndistortRectifyMap(camera_mat,input2,input3,input4,img_size,mat_type,mapx,mapy);
913
}
914
else
915
{
916
CvMat input1 = cvMat(test_mat[INPUT][1]), input2, input3, input4;
917
if( !zero_distortion )
918
input2 = cvMat(test_mat[INPUT][2]);
919
if( !zero_R )
920
input3 = cvMat(test_mat[INPUT][3]);
921
if( !zero_new_cam )
922
input4 = cvMat(test_mat[INPUT][4]);
923
cvInitUndistortRectifyMap(&input1,
924
zero_distortion ? 0 : &input2,
925
zero_R ? 0 : &input3,
926
zero_new_cam ? 0 : &input4,
927
_mapx,_mapy);
928
}
929
}
930
931
double CV_InitUndistortRectifyMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
932
{
933
return 8;
934
}
935
936
//////////////////////////////////////////////////////////////////////////////////////////////////////
937
938
TEST(Calib3d_DefaultNewCameraMatrix, accuracy) { CV_DefaultNewCameraMatrixTest test; test.safe_run(); }
939
TEST(Calib3d_UndistortPoints, accuracy) { CV_UndistortPointsTest test; test.safe_run(); }
940
TEST(Calib3d_InitUndistortRectifyMap, accuracy) { CV_InitUndistortRectifyMapTest test; test.safe_run(); }
941
942
////////////////////////////// undistort /////////////////////////////////
943
944
static void test_remap( const Mat& src, Mat& dst, const Mat& mapx, const Mat& mapy,
945
Mat* mask=0, int interpolation=CV_INTER_LINEAR )
946
{
947
int x, y, k;
948
int drows = dst.rows, dcols = dst.cols;
949
int srows = src.rows, scols = src.cols;
950
const uchar* sptr0 = src.ptr();
951
int depth = src.depth(), cn = src.channels();
952
int elem_size = (int)src.elemSize();
953
int step = (int)(src.step / CV_ELEM_SIZE(depth));
954
int delta;
955
956
if( interpolation != CV_INTER_CUBIC )
957
{
958
delta = 0;
959
scols -= 1; srows -= 1;
960
}
961
else
962
{
963
delta = 1;
964
scols = MAX(scols - 3, 0);
965
srows = MAX(srows - 3, 0);
966
}
967
968
int scols1 = MAX(scols - 2, 0);
969
int srows1 = MAX(srows - 2, 0);
970
971
if( mask )
972
*mask = Scalar::all(0);
973
974
for( y = 0; y < drows; y++ )
975
{
976
uchar* dptr = dst.ptr(y);
977
const float* mx = mapx.ptr<float>(y);
978
const float* my = mapy.ptr<float>(y);
979
uchar* m = mask ? mask->ptr(y) : 0;
980
981
for( x = 0; x < dcols; x++, dptr += elem_size )
982
{
983
float xs = mx[x];
984
float ys = my[x];
985
int ixs = cvFloor(xs);
986
int iys = cvFloor(ys);
987
988
if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 ||
989
(unsigned)(iys - delta - 1) >= (unsigned)srows1 )
990
{
991
if( m )
992
m[x] = 1;
993
if( (unsigned)(ixs - delta) >= (unsigned)scols ||
994
(unsigned)(iys - delta) >= (unsigned)srows )
995
continue;
996
}
997
998
xs -= ixs;
999
ys -= iys;
1000
1001
switch( depth )
1002
{
1003
case CV_8U:
1004
{
1005
const uchar* sptr = sptr0 + iys*step + ixs*cn;
1006
for( k = 0; k < cn; k++ )
1007
{
1008
float v00 = sptr[k];
1009
float v01 = sptr[cn + k];
1010
float v10 = sptr[step + k];
1011
float v11 = sptr[step + cn + k];
1012
1013
v00 = v00 + xs*(v01 - v00);
1014
v10 = v10 + xs*(v11 - v10);
1015
v00 = v00 + ys*(v10 - v00);
1016
dptr[k] = (uchar)cvRound(v00);
1017
}
1018
}
1019
break;
1020
case CV_16U:
1021
{
1022
const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn;
1023
for( k = 0; k < cn; k++ )
1024
{
1025
float v00 = sptr[k];
1026
float v01 = sptr[cn + k];
1027
float v10 = sptr[step + k];
1028
float v11 = sptr[step + cn + k];
1029
1030
v00 = v00 + xs*(v01 - v00);
1031
v10 = v10 + xs*(v11 - v10);
1032
v00 = v00 + ys*(v10 - v00);
1033
((ushort*)dptr)[k] = (ushort)cvRound(v00);
1034
}
1035
}
1036
break;
1037
case CV_32F:
1038
{
1039
const float* sptr = (const float*)sptr0 + iys*step + ixs*cn;
1040
for( k = 0; k < cn; k++ )
1041
{
1042
float v00 = sptr[k];
1043
float v01 = sptr[cn + k];
1044
float v10 = sptr[step + k];
1045
float v11 = sptr[step + cn + k];
1046
1047
v00 = v00 + xs*(v01 - v00);
1048
v10 = v10 + xs*(v11 - v10);
1049
v00 = v00 + ys*(v10 - v00);
1050
((float*)dptr)[k] = (float)v00;
1051
}
1052
}
1053
break;
1054
default:
1055
assert(0);
1056
}
1057
}
1058
}
1059
}
1060
1061
class CV_ImgWarpBaseTest : public cvtest::ArrayTest
1062
{
1063
public:
1064
CV_ImgWarpBaseTest( bool warp_matrix );
1065
1066
protected:
1067
int read_params( CvFileStorage* fs );
1068
int prepare_test_case( int test_case_idx );
1069
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1070
void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
1071
void fill_array( int test_case_idx, int i, int j, Mat& arr );
1072
1073
int interpolation;
1074
int max_interpolation;
1075
double spatial_scale_zoom, spatial_scale_decimate;
1076
};
1077
1078
1079
CV_ImgWarpBaseTest::CV_ImgWarpBaseTest( bool warp_matrix )
1080
{
1081
test_array[INPUT].push_back(NULL);
1082
if( warp_matrix )
1083
test_array[INPUT].push_back(NULL);
1084
test_array[INPUT_OUTPUT].push_back(NULL);
1085
test_array[REF_INPUT_OUTPUT].push_back(NULL);
1086
max_interpolation = 5;
1087
interpolation = 0;
1088
element_wise_relative_error = false;
1089
spatial_scale_zoom = 0.01;
1090
spatial_scale_decimate = 0.005;
1091
}
1092
1093
1094
int CV_ImgWarpBaseTest::read_params( CvFileStorage* fs )
1095
{
1096
int code = cvtest::ArrayTest::read_params( fs );
1097
return code;
1098
}
1099
1100
1101
void CV_ImgWarpBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
1102
{
1103
cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
1104
if( CV_MAT_DEPTH(type) == CV_32F )
1105
{
1106
low = Scalar::all(-10.);
1107
high = Scalar::all(10);
1108
}
1109
}
1110
1111
1112
void CV_ImgWarpBaseTest::get_test_array_types_and_sizes( int test_case_idx,
1113
vector<vector<Size> >& sizes, vector<vector<int> >& types )
1114
{
1115
RNG& rng = ts->get_rng();
1116
int depth = cvtest::randInt(rng) % 3;
1117
int cn = cvtest::randInt(rng) % 3 + 1;
1118
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1119
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F;
1120
cn += cn == 2;
1121
1122
types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
1123
if( test_array[INPUT].size() > 1 )
1124
types[INPUT][1] = cvtest::randInt(rng) & 1 ? CV_32FC1 : CV_64FC1;
1125
1126
interpolation = cvtest::randInt(rng) % max_interpolation;
1127
}
1128
1129
1130
void CV_ImgWarpBaseTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
1131
{
1132
if( i != INPUT || j != 0 )
1133
cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
1134
}
1135
1136
int CV_ImgWarpBaseTest::prepare_test_case( int test_case_idx )
1137
{
1138
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
1139
Mat& img = test_mat[INPUT][0];
1140
int i, j, cols = img.cols;
1141
int type = img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
1142
double scale = depth == CV_16U ? 1000. : 255.*0.5;
1143
double space_scale = spatial_scale_decimate;
1144
vector<float> buffer(img.cols*cn);
1145
1146
if( code <= 0 )
1147
return code;
1148
1149
if( test_mat[INPUT_OUTPUT][0].cols >= img.cols &&
1150
test_mat[INPUT_OUTPUT][0].rows >= img.rows )
1151
space_scale = spatial_scale_zoom;
1152
1153
for( i = 0; i < img.rows; i++ )
1154
{
1155
uchar* ptr = img.ptr(i);
1156
switch( cn )
1157
{
1158
case 1:
1159
for( j = 0; j < cols; j++ )
1160
buffer[j] = (float)((sin((i+1)*space_scale)*sin((j+1)*space_scale)+1.)*scale);
1161
break;
1162
case 2:
1163
for( j = 0; j < cols; j++ )
1164
{
1165
buffer[j*2] = (float)((sin((i+1)*space_scale)+1.)*scale);
1166
buffer[j*2+1] = (float)((sin((i+j)*space_scale)+1.)*scale);
1167
}
1168
break;
1169
case 3:
1170
for( j = 0; j < cols; j++ )
1171
{
1172
buffer[j*3] = (float)((sin((i+1)*space_scale)+1.)*scale);
1173
buffer[j*3+1] = (float)((sin(j*space_scale)+1.)*scale);
1174
buffer[j*3+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
1175
}
1176
break;
1177
case 4:
1178
for( j = 0; j < cols; j++ )
1179
{
1180
buffer[j*4] = (float)((sin((i+1)*space_scale)+1.)*scale);
1181
buffer[j*4+1] = (float)((sin(j*space_scale)+1.)*scale);
1182
buffer[j*4+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
1183
buffer[j*4+3] = (float)((sin((i-j)*space_scale)+1.)*scale);
1184
}
1185
break;
1186
default:
1187
assert(0);
1188
}
1189
1190
/*switch( depth )
1191
{
1192
case CV_8U:
1193
for( j = 0; j < cols*cn; j++ )
1194
ptr[j] = (uchar)cvRound(buffer[j]);
1195
break;
1196
case CV_16U:
1197
for( j = 0; j < cols*cn; j++ )
1198
((ushort*)ptr)[j] = (ushort)cvRound(buffer[j]);
1199
break;
1200
case CV_32F:
1201
for( j = 0; j < cols*cn; j++ )
1202
((float*)ptr)[j] = (float)buffer[j];
1203
break;
1204
default:
1205
assert(0);
1206
}*/
1207
cv::Mat src(1, cols*cn, CV_32F, &buffer[0]);
1208
cv::Mat dst(1, cols*cn, depth, ptr);
1209
src.convertTo(dst, dst.type());
1210
}
1211
1212
return code;
1213
}
1214
1215
1216
class CV_UndistortTest : public CV_ImgWarpBaseTest
1217
{
1218
public:
1219
CV_UndistortTest();
1220
1221
protected:
1222
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1223
void run_func();
1224
int prepare_test_case( int test_case_idx );
1225
void prepare_to_validation( int /*test_case_idx*/ );
1226
double get_success_error_level( int test_case_idx, int i, int j );
1227
void fill_array( int test_case_idx, int i, int j, Mat& arr );
1228
1229
private:
1230
bool useCPlus;
1231
cv::Mat input0;
1232
cv::Mat input1;
1233
cv::Mat input2;
1234
cv::Mat input_new_cam;
1235
cv::Mat input_output;
1236
1237
bool zero_new_cam;
1238
bool zero_distortion;
1239
};
1240
1241
1242
CV_UndistortTest::CV_UndistortTest() : CV_ImgWarpBaseTest( false )
1243
{
1244
//spatial_scale_zoom = spatial_scale_decimate;
1245
test_array[INPUT].push_back(NULL);
1246
test_array[INPUT].push_back(NULL);
1247
test_array[INPUT].push_back(NULL);
1248
1249
spatial_scale_decimate = spatial_scale_zoom;
1250
}
1251
1252
1253
void CV_UndistortTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1254
{
1255
RNG& rng = ts->get_rng();
1256
CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1257
int type = types[INPUT][0];
1258
type = CV_MAKETYPE( CV_8U, CV_MAT_CN(type) );
1259
types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = type;
1260
types[INPUT][1] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
1261
types[INPUT][2] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
1262
sizes[INPUT][1] = cvSize(3,3);
1263
sizes[INPUT][2] = cvtest::randInt(rng)%2 ? cvSize(4,1) : cvSize(1,4);
1264
types[INPUT][3] = types[INPUT][1];
1265
sizes[INPUT][3] = sizes[INPUT][1];
1266
interpolation = CV_INTER_LINEAR;
1267
}
1268
1269
1270
void CV_UndistortTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
1271
{
1272
if( i != INPUT )
1273
CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr );
1274
}
1275
1276
1277
void CV_UndistortTest::run_func()
1278
{
1279
if (!useCPlus)
1280
{
1281
CvMat a = cvMat(test_mat[INPUT][1]), k = cvMat(test_mat[INPUT][2]);
1282
cvUndistort2( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], &a, &k);
1283
}
1284
else
1285
{
1286
if (zero_distortion)
1287
{
1288
cv::undistort(input0,input_output,input1,cv::Mat());
1289
}
1290
else
1291
{
1292
cv::undistort(input0,input_output,input1,input2);
1293
}
1294
}
1295
}
1296
1297
1298
double CV_UndistortTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1299
{
1300
int depth = test_mat[INPUT][0].depth();
1301
return depth == CV_8U ? 16 : depth == CV_16U ? 1024 : 5e-2;
1302
}
1303
1304
1305
int CV_UndistortTest::prepare_test_case( int test_case_idx )
1306
{
1307
RNG& rng = ts->get_rng();
1308
int code = CV_ImgWarpBaseTest::prepare_test_case( test_case_idx );
1309
1310
const Mat& src = test_mat[INPUT][0];
1311
double k[4], a[9] = {0,0,0,0,0,0,0,0,1};
1312
double new_cam[9] = {0,0,0,0,0,0,0,0,1};
1313
double sz = MAX(src.rows, src.cols);
1314
1315
Mat& _new_cam0 = test_mat[INPUT][3];
1316
Mat _new_cam(test_mat[INPUT][3].rows,test_mat[INPUT][3].cols,CV_64F,new_cam);
1317
Mat& _a0 = test_mat[INPUT][1];
1318
Mat _a(3,3,CV_64F,a);
1319
Mat& _k0 = test_mat[INPUT][2];
1320
Mat _k(_k0.rows,_k0.cols, CV_MAKETYPE(CV_64F,_k0.channels()),k);
1321
1322
if( code <= 0 )
1323
return code;
1324
1325
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
1326
a[2] = (src.cols - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
1327
a[5] = (src.rows - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
1328
a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
1329
a[4] = aspect_ratio*a[0];
1330
k[0] = cvtest::randReal(rng)*0.06 - 0.03;
1331
k[1] = cvtest::randReal(rng)*0.06 - 0.03;
1332
if( k[0]*k[1] > 0 )
1333
k[1] = -k[1];
1334
if( cvtest::randInt(rng)%4 != 0 )
1335
{
1336
k[2] = cvtest::randReal(rng)*0.004 - 0.002;
1337
k[3] = cvtest::randReal(rng)*0.004 - 0.002;
1338
}
1339
else
1340
k[2] = k[3] = 0;
1341
1342
new_cam[0] = a[0] + (cvtest::randReal(rng) - (double)0.5)*0.2*a[0]; //10%
1343
new_cam[4] = a[4] + (cvtest::randReal(rng) - (double)0.5)*0.2*a[4]; //10%
1344
new_cam[2] = a[2] + (cvtest::randReal(rng) - (double)0.5)*0.3*test_mat[INPUT][0].rows; //15%
1345
new_cam[5] = a[5] + (cvtest::randReal(rng) - (double)0.5)*0.3*test_mat[INPUT][0].cols; //15%
1346
1347
_a.convertTo(_a0, _a0.depth());
1348
1349
zero_distortion = (cvtest::randInt(rng)%2) == 0 ? false : true;
1350
_k.convertTo(_k0, _k0.depth());
1351
1352
zero_new_cam = (cvtest::randInt(rng)%2) == 0 ? false : true;
1353
_new_cam.convertTo(_new_cam0, _new_cam0.depth());
1354
1355
//Testing C++ code
1356
useCPlus = ((cvtest::randInt(rng) % 2)!=0);
1357
if (useCPlus)
1358
{
1359
input0 = test_mat[INPUT][0];
1360
input1 = test_mat[INPUT][1];
1361
input2 = test_mat[INPUT][2];
1362
input_new_cam = test_mat[INPUT][3];
1363
}
1364
1365
return code;
1366
}
1367
1368
1369
void CV_UndistortTest::prepare_to_validation( int /*test_case_idx*/ )
1370
{
1371
if (useCPlus)
1372
{
1373
Mat& output = test_mat[INPUT_OUTPUT][0];
1374
input_output.convertTo(output, output.type());
1375
}
1376
Mat& src = test_mat[INPUT][0];
1377
Mat& dst = test_mat[REF_INPUT_OUTPUT][0];
1378
Mat& dst0 = test_mat[INPUT_OUTPUT][0];
1379
Mat mapx, mapy;
1380
cvtest::initUndistortMap( test_mat[INPUT][1], test_mat[INPUT][2], dst.size(), mapx, mapy );
1381
Mat mask( dst.size(), CV_8U );
1382
test_remap( src, dst, mapx, mapy, &mask, interpolation );
1383
dst.setTo(Scalar::all(0), mask);
1384
dst0.setTo(Scalar::all(0), mask);
1385
}
1386
1387
1388
class CV_UndistortMapTest : public cvtest::ArrayTest
1389
{
1390
public:
1391
CV_UndistortMapTest();
1392
1393
protected:
1394
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
1395
void run_func();
1396
int prepare_test_case( int test_case_idx );
1397
void prepare_to_validation( int /*test_case_idx*/ );
1398
double get_success_error_level( int test_case_idx, int i, int j );
1399
void fill_array( int test_case_idx, int i, int j, Mat& arr );
1400
1401
private:
1402
bool dualChannel;
1403
};
1404
1405
1406
CV_UndistortMapTest::CV_UndistortMapTest()
1407
{
1408
test_array[INPUT].push_back(NULL);
1409
test_array[INPUT].push_back(NULL);
1410
test_array[OUTPUT].push_back(NULL);
1411
test_array[OUTPUT].push_back(NULL);
1412
test_array[REF_OUTPUT].push_back(NULL);
1413
test_array[REF_OUTPUT].push_back(NULL);
1414
1415
element_wise_relative_error = false;
1416
}
1417
1418
1419
void CV_UndistortMapTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
1420
{
1421
RNG& rng = ts->get_rng();
1422
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
1423
int depth = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
1424
1425
Size sz = sizes[OUTPUT][0];
1426
types[INPUT][0] = types[INPUT][1] = depth;
1427
dualChannel = cvtest::randInt(rng)%2 == 0;
1428
types[OUTPUT][0] = types[OUTPUT][1] =
1429
types[REF_OUTPUT][0] = types[REF_OUTPUT][1] = dualChannel ? CV_32FC2 : CV_32F;
1430
sizes[INPUT][0] = cvSize(3,3);
1431
sizes[INPUT][1] = cvtest::randInt(rng)%2 ? cvSize(4,1) : cvSize(1,4);
1432
1433
sz.width = MAX(sz.width,16);
1434
sz.height = MAX(sz.height,16);
1435
sizes[OUTPUT][0] = sizes[OUTPUT][1] =
1436
sizes[REF_OUTPUT][0] = sizes[REF_OUTPUT][1] = sz;
1437
}
1438
1439
1440
void CV_UndistortMapTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
1441
{
1442
if( i != INPUT )
1443
cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
1444
}
1445
1446
1447
void CV_UndistortMapTest::run_func()
1448
{
1449
CvMat a = cvMat(test_mat[INPUT][0]), k = cvMat(test_mat[INPUT][1]);
1450
1451
if (!dualChannel )
1452
cvInitUndistortMap( &a, &k, test_array[OUTPUT][0], test_array[OUTPUT][1] );
1453
else
1454
cvInitUndistortMap( &a, &k, test_array[OUTPUT][0], 0 );
1455
}
1456
1457
1458
double CV_UndistortMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
1459
{
1460
return 1e-3;
1461
}
1462
1463
1464
int CV_UndistortMapTest::prepare_test_case( int test_case_idx )
1465
{
1466
RNG& rng = ts->get_rng();
1467
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
1468
const Mat& mapx = test_mat[OUTPUT][0];
1469
double k[4], a[9] = {0,0,0,0,0,0,0,0,1};
1470
double sz = MAX(mapx.rows, mapx.cols);
1471
Mat& _a0 = test_mat[INPUT][0], &_k0 = test_mat[INPUT][1];
1472
Mat _a(3,3,CV_64F,a);
1473
Mat _k(_k0.rows,_k0.cols, CV_MAKETYPE(CV_64F,_k0.channels()),k);
1474
1475
if( code <= 0 )
1476
return code;
1477
1478
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
1479
a[2] = (mapx.cols - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
1480
a[5] = (mapx.rows - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
1481
a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
1482
a[4] = aspect_ratio*a[0];
1483
k[0] = cvtest::randReal(rng)*0.06 - 0.03;
1484
k[1] = cvtest::randReal(rng)*0.06 - 0.03;
1485
if( k[0]*k[1] > 0 )
1486
k[1] = -k[1];
1487
k[2] = cvtest::randReal(rng)*0.004 - 0.002;
1488
k[3] = cvtest::randReal(rng)*0.004 - 0.002;
1489
1490
_a.convertTo(_a0, _a0.depth());
1491
_k.convertTo(_k0, _k0.depth());
1492
1493
if (dualChannel)
1494
{
1495
test_mat[REF_OUTPUT][1] = Scalar::all(0);
1496
test_mat[OUTPUT][1] = Scalar::all(0);
1497
}
1498
1499
return code;
1500
}
1501
1502
1503
void CV_UndistortMapTest::prepare_to_validation( int )
1504
{
1505
Mat mapx, mapy;
1506
cvtest::initUndistortMap( test_mat[INPUT][0], test_mat[INPUT][1], test_mat[REF_OUTPUT][0].size(), mapx, mapy );
1507
if( !dualChannel )
1508
{
1509
mapx.copyTo(test_mat[REF_OUTPUT][0]);
1510
mapy.copyTo(test_mat[REF_OUTPUT][1]);
1511
}
1512
else
1513
{
1514
Mat p[2] = {mapx, mapy};
1515
cv::merge(p, 2, test_mat[REF_OUTPUT][0]);
1516
}
1517
}
1518
1519
TEST(Calib3d_Undistort, accuracy) { CV_UndistortTest test; test.safe_run(); }
1520
TEST(Calib3d_InitUndistortMap, accuracy) { CV_UndistortMapTest test; test.safe_run(); }
1521
1522
}} // namespace
1523
1524