Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/calib3d/test/test_homography.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
// Copyright (C) 2015, Itseez Inc., all rights reserved.
16
// Third party copyrights are property of their respective owners.
17
//
18
// Redistribution and use in source and binary forms, with or without modification,
19
// are permitted provided that the following conditions are met:
20
//
21
// * Redistribution's of source code must retain the above copyright notice,
22
// this list of conditions and the following disclaimer.
23
//
24
// * Redistribution's in binary form must reproduce the above copyright notice,
25
// this list of conditions and the following disclaimer in the documentation
26
// and/or other materials provided with the distribution.
27
//
28
// * The name of the copyright holders may not be used to endorse or promote products
29
// derived from this software without specific prior written permission.
30
//
31
// This software is provided by the copyright holders and contributors "as is" and
32
// any express or implied warranties, including, but not limited to, the implied
33
// warranties of merchantability and fitness for a particular purpose are disclaimed.
34
// In no event shall the Intel Corporation or contributors be liable for any direct,
35
// indirect, incidental, special, exemplary, or consequential damages
36
// (including, but not limited to, procurement of substitute goods or services;
37
// loss of use, data, or profits; or business interruption) however caused
38
// and on any theory of liability, whether in contract, strict liability,
39
// or tort (including negligence or otherwise) arising in any way out of
40
// the use of this software, even if advised of the possibility of such damage.
41
//
42
//M*/
43
44
#include "test_precomp.hpp"
45
46
namespace opencv_test { namespace {
47
48
#define CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE 1
49
#define CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF 2
50
#define CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF 3
51
#define CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK 4
52
#define CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF 5
53
54
#define MESSAGE_MATRIX_SIZE "Homography matrix must have 3*3 sizes."
55
#define MESSAGE_MATRIX_DIFF "Accuracy of homography transformation matrix less than required."
56
#define MESSAGE_REPROJ_DIFF_1 "Reprojection error for current pair of points more than required."
57
#define MESSAGE_REPROJ_DIFF_2 "Reprojection error is not optimal."
58
#define MESSAGE_RANSAC_MASK_1 "Sizes of inliers/outliers mask are incorrect."
59
#define MESSAGE_RANSAC_MASK_2 "Mask mustn't have any outliers."
60
#define MESSAGE_RANSAC_MASK_3 "All values of mask must be 1 (true) or 0 (false)."
61
#define MESSAGE_RANSAC_MASK_4 "Mask of inliers/outliers is incorrect."
62
#define MESSAGE_RANSAC_MASK_5 "Inlier in original mask shouldn't be outlier in found mask."
63
#define MESSAGE_RANSAC_DIFF "Reprojection error for current pair of points more than required."
64
65
#define MAX_COUNT_OF_POINTS 303
66
#define COUNT_NORM_TYPES 3
67
#define METHODS_COUNT 4
68
69
int NORM_TYPE[COUNT_NORM_TYPES] = {cv::NORM_L1, cv::NORM_L2, cv::NORM_INF};
70
int METHOD[METHODS_COUNT] = {0, cv::RANSAC, cv::LMEDS, cv::RHO};
71
72
using namespace cv;
73
using namespace std;
74
75
class CV_HomographyTest: public cvtest::ArrayTest
76
{
77
public:
78
CV_HomographyTest();
79
~CV_HomographyTest();
80
81
void run (int);
82
83
protected:
84
85
int method;
86
int image_size;
87
double reproj_threshold;
88
double sigma;
89
90
private:
91
float max_diff, max_2diff;
92
bool check_matrix_size(const cv::Mat& H);
93
bool check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff);
94
int check_ransac_mask_1(const Mat& src, const Mat& mask);
95
int check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask);
96
97
void print_information_1(int j, int N, int method, const Mat& H);
98
void print_information_2(int j, int N, int method, const Mat& H, const Mat& H_res, int k, double diff);
99
void print_information_3(int method, int j, int N, const Mat& mask);
100
void print_information_4(int method, int j, int N, int k, int l, double diff);
101
void print_information_5(int method, int j, int N, int l, double diff);
102
void print_information_6(int method, int j, int N, int k, double diff, bool value);
103
void print_information_7(int method, int j, int N, int k, double diff, bool original_value, bool found_value);
104
void print_information_8(int method, int j, int N, int k, int l, double diff);
105
};
106
107
CV_HomographyTest::CV_HomographyTest() : max_diff(1e-2f), max_2diff(2e-2f)
108
{
109
method = 0;
110
image_size = 100;
111
reproj_threshold = 3.0;
112
sigma = 0.01;
113
}
114
115
CV_HomographyTest::~CV_HomographyTest() {}
116
117
bool CV_HomographyTest::check_matrix_size(const cv::Mat& H)
118
{
119
return (H.rows == 3) && (H.cols == 3);
120
}
121
122
bool CV_HomographyTest::check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff)
123
{
124
diff = cvtest::norm(original, found, norm_type);
125
return diff <= max_diff;
126
}
127
128
int CV_HomographyTest::check_ransac_mask_1(const Mat& src, const Mat& mask)
129
{
130
if (!(mask.cols == 1) && (mask.rows == src.cols)) return 1;
131
if (countNonZero(mask) < mask.rows) return 2;
132
for (int i = 0; i < mask.rows; ++i) if (mask.at<uchar>(i, 0) > 1) return 3;
133
return 0;
134
}
135
136
int CV_HomographyTest::check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask)
137
{
138
if (!(found_mask.cols == 1) && (found_mask.rows == original_mask.rows)) return 1;
139
for (int i = 0; i < found_mask.rows; ++i) if (found_mask.at<uchar>(i, 0) > 1) return 2;
140
return 0;
141
}
142
143
void CV_HomographyTest::print_information_1(int j, int N, int _method, const Mat& H)
144
{
145
cout << endl; cout << "Checking for homography matrix sizes..." << endl; cout << endl;
146
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
147
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
148
cout << "Count of points: " << N << endl; cout << endl;
149
cout << "Method: "; if (_method == 0) cout << 0; else if (_method == 8) cout << "RANSAC"; else if (_method == cv::RHO) cout << "RHO"; else cout << "LMEDS"; cout << endl;
150
cout << "Homography matrix:" << endl; cout << endl;
151
cout << H << endl; cout << endl;
152
cout << "Number of rows: " << H.rows << " Number of cols: " << H.cols << endl; cout << endl;
153
}
154
155
void CV_HomographyTest::print_information_2(int j, int N, int _method, const Mat& H, const Mat& H_res, int k, double diff)
156
{
157
cout << endl; cout << "Checking for accuracy of homography matrix computing..." << endl; cout << endl;
158
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
159
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
160
cout << "Count of points: " << N << endl; cout << endl;
161
cout << "Method: "; if (_method == 0) cout << 0; else if (_method == 8) cout << "RANSAC"; else if (_method == cv::RHO) cout << "RHO"; else cout << "LMEDS"; cout << endl;
162
cout << "Original matrix:" << endl; cout << endl;
163
cout << H << endl; cout << endl;
164
cout << "Found matrix:" << endl; cout << endl;
165
cout << H_res << endl; cout << endl;
166
cout << "Norm type using in criteria: "; if (NORM_TYPE[k] == 1) cout << "INF"; else if (NORM_TYPE[k] == 2) cout << "L1"; else cout << "L2"; cout << endl;
167
cout << "Difference between matrices: " << diff << endl;
168
cout << "Maximum allowed difference: " << max_diff << endl; cout << endl;
169
}
170
171
void CV_HomographyTest::print_information_3(int _method, int j, int N, const Mat& mask)
172
{
173
cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;
174
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
175
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
176
cout << "Count of points: " << N << endl; cout << endl;
177
cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl;
178
cout << "Found mask:" << endl; cout << endl;
179
cout << mask << endl; cout << endl;
180
cout << "Number of rows: " << mask.rows << " Number of cols: " << mask.cols << endl; cout << endl;
181
}
182
183
void CV_HomographyTest::print_information_4(int _method, int j, int N, int k, int l, double diff)
184
{
185
cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;
186
cout << "Method: "; if (_method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;
187
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
188
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
189
cout << "Sigma of normal noise: " << sigma << endl;
190
cout << "Count of points: " << N << endl;
191
cout << "Number of point: " << k << endl;
192
cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
193
cout << "Difference with noise of point: " << diff << endl;
194
cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;
195
}
196
197
void CV_HomographyTest::print_information_5(int _method, int j, int N, int l, double diff)
198
{
199
cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;
200
cout << "Method: "; if (_method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;
201
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
202
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
203
cout << "Sigma of normal noise: " << sigma << endl;
204
cout << "Count of points: " << N << endl;
205
cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
206
cout << "Difference with noise of points: " << diff << endl;
207
cout << "Maxumum allowed difference: " << max_diff << endl; cout << endl;
208
}
209
210
void CV_HomographyTest::print_information_6(int _method, int j, int N, int k, double diff, bool value)
211
{
212
cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;
213
cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl;
214
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
215
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
216
cout << "Count of points: " << N << " " << endl;
217
cout << "Number of point: " << k << " " << endl;
218
cout << "Reprojection error for this point: " << diff << " " << endl;
219
cout << "Reprojection error threshold: " << reproj_threshold << " " << endl;
220
cout << "Value of found mask: "<< value << endl; cout << endl;
221
}
222
223
void CV_HomographyTest::print_information_7(int _method, int j, int N, int k, double diff, bool original_value, bool found_value)
224
{
225
cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;
226
cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl;
227
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
228
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
229
cout << "Count of points: " << N << " " << endl;
230
cout << "Number of point: " << k << " " << endl;
231
cout << "Reprojection error for this point: " << diff << " " << endl;
232
cout << "Reprojection error threshold: " << reproj_threshold << " " << endl;
233
cout << "Value of original mask: "<< original_value << " Value of found mask: " << found_value << endl; cout << endl;
234
}
235
236
void CV_HomographyTest::print_information_8(int _method, int j, int N, int k, int l, double diff)
237
{
238
cout << endl; cout << "Checking for reprojection error of inlier..." << endl; cout << endl;
239
cout << "Method: "; if (_method == RANSAC) cout << "RANSAC" << endl; else if (_method == cv::RHO) cout << "RHO" << endl; else cout << _method << endl;
240
cout << "Sigma of normal noise: " << sigma << endl;
241
cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>";
242
cout << " Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;
243
cout << "Count of points: " << N << " " << endl;
244
cout << "Number of point: " << k << " " << endl;
245
cout << "Norm type using in criteria: "; if (NORM_TYPE[l] == 1) cout << "INF"; else if (NORM_TYPE[l] == 2) cout << "L1"; else cout << "L2"; cout << endl;
246
cout << "Difference with noise of point: " << diff << endl;
247
cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;
248
}
249
250
void CV_HomographyTest::run(int)
251
{
252
for (int N = 4; N <= MAX_COUNT_OF_POINTS; ++N)
253
{
254
RNG& rng = ts->get_rng();
255
256
float *src_data = new float [2*N];
257
258
for (int i = 0; i < N; ++i)
259
{
260
src_data[2*i] = (float)cvtest::randReal(rng)*image_size;
261
src_data[2*i+1] = (float)cvtest::randReal(rng)*image_size;
262
}
263
264
cv::Mat src_mat_2f(1, N, CV_32FC2, src_data),
265
src_mat_2d(2, N, CV_32F, src_data),
266
src_mat_3d(3, N, CV_32F);
267
cv::Mat dst_mat_2f, dst_mat_2d, dst_mat_3d;
268
269
vector <Point2f> src_vec, dst_vec;
270
271
for (int i = 0; i < N; ++i)
272
{
273
float *tmp = src_mat_2d.ptr<float>()+2*i;
274
src_mat_3d.at<float>(0, i) = tmp[0];
275
src_mat_3d.at<float>(1, i) = tmp[1];
276
src_mat_3d.at<float>(2, i) = 1.0f;
277
278
src_vec.push_back(Point2f(tmp[0], tmp[1]));
279
}
280
281
double fi = cvtest::randReal(rng)*2*CV_PI;
282
283
double t_x = cvtest::randReal(rng)*sqrt(image_size*1.0),
284
t_y = cvtest::randReal(rng)*sqrt(image_size*1.0);
285
286
double Hdata[9] = { cos(fi), -sin(fi), t_x,
287
sin(fi), cos(fi), t_y,
288
0.0f, 0.0f, 1.0f };
289
290
cv::Mat H_64(3, 3, CV_64F, Hdata), H_32;
291
292
H_64.convertTo(H_32, CV_32F);
293
294
dst_mat_3d = H_32*src_mat_3d;
295
296
dst_mat_2d.create(2, N, CV_32F); dst_mat_2f.create(1, N, CV_32FC2);
297
298
for (int i = 0; i < N; ++i)
299
{
300
float *tmp_2f = dst_mat_2f.ptr<float>()+2*i;
301
tmp_2f[0] = dst_mat_2d.at<float>(0, i) = dst_mat_3d.at<float>(0, i) /= dst_mat_3d.at<float>(2, i);
302
tmp_2f[1] = dst_mat_2d.at<float>(1, i) = dst_mat_3d.at<float>(1, i) /= dst_mat_3d.at<float>(2, i);
303
dst_mat_3d.at<float>(2, i) = 1.0f;
304
305
dst_vec.push_back(Point2f(tmp_2f[0], tmp_2f[1]));
306
}
307
308
for (int i = 0; i < METHODS_COUNT; ++i)
309
{
310
method = METHOD[i];
311
switch (method)
312
{
313
case 0:
314
case LMEDS:
315
{
316
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method),
317
cv::findHomography(src_mat_2f, dst_vec, method),
318
cv::findHomography(src_vec, dst_mat_2f, method),
319
cv::findHomography(src_vec, dst_vec, method) };
320
321
for (int j = 0; j < 4; ++j)
322
{
323
324
if (!check_matrix_size(H_res_64[j]))
325
{
326
print_information_1(j, N, method, H_res_64[j]);
327
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
328
return;
329
}
330
331
double diff;
332
333
for (int k = 0; k < COUNT_NORM_TYPES; ++k)
334
if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))
335
{
336
print_information_2(j, N, method, H_64, H_res_64[j], k, diff);
337
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);
338
return;
339
}
340
}
341
342
continue;
343
}
344
case cv::RHO:
345
case RANSAC:
346
{
347
cv::Mat mask [4]; double diff;
348
349
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method, reproj_threshold, mask[0]),
350
cv::findHomography(src_mat_2f, dst_vec, method, reproj_threshold, mask[1]),
351
cv::findHomography(src_vec, dst_mat_2f, method, reproj_threshold, mask[2]),
352
cv::findHomography(src_vec, dst_vec, method, reproj_threshold, mask[3]) };
353
354
for (int j = 0; j < 4; ++j)
355
{
356
357
if (!check_matrix_size(H_res_64[j]))
358
{
359
print_information_1(j, N, method, H_res_64[j]);
360
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
361
return;
362
}
363
364
for (int k = 0; k < COUNT_NORM_TYPES; ++k)
365
if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))
366
{
367
print_information_2(j, N, method, H_64, H_res_64[j], k, diff);
368
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);
369
return;
370
}
371
372
int code = check_ransac_mask_1(src_mat_2f, mask[j]);
373
374
if (code)
375
{
376
print_information_3(method, j, N, mask[j]);
377
378
switch (code)
379
{
380
case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }
381
case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_2); break; }
382
case 3: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }
383
384
default: break;
385
}
386
387
return;
388
}
389
390
}
391
392
continue;
393
}
394
395
default: continue;
396
}
397
}
398
399
Mat noise_2f(1, N, CV_32FC2);
400
rng.fill(noise_2f, RNG::NORMAL, Scalar::all(0), Scalar::all(sigma));
401
402
cv::Mat mask(N, 1, CV_8UC1);
403
404
for (int i = 0; i < N; ++i)
405
{
406
float *a = noise_2f.ptr<float>()+2*i, *_2f = dst_mat_2f.ptr<float>()+2*i;
407
_2f[0] += a[0]; _2f[1] += a[1];
408
mask.at<bool>(i, 0) = !(sqrt(a[0]*a[0]+a[1]*a[1]) > reproj_threshold);
409
}
410
411
for (int i = 0; i < METHODS_COUNT; ++i)
412
{
413
method = METHOD[i];
414
switch (method)
415
{
416
case 0:
417
case LMEDS:
418
{
419
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f),
420
cv::findHomography(src_mat_2f, dst_vec),
421
cv::findHomography(src_vec, dst_mat_2f),
422
cv::findHomography(src_vec, dst_vec) };
423
424
for (int j = 0; j < 4; ++j)
425
{
426
427
if (!check_matrix_size(H_res_64[j]))
428
{
429
print_information_1(j, N, method, H_res_64[j]);
430
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
431
return;
432
}
433
434
Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);
435
436
cv::Mat dst_res_3d(3, N, CV_32F), noise_2d(2, N, CV_32F);
437
438
for (int k = 0; k < N; ++k)
439
{
440
441
Mat tmp_mat_3d = H_res_32*src_mat_3d.col(k);
442
443
dst_res_3d.at<float>(0, k) = tmp_mat_3d.at<float>(0, 0) /= tmp_mat_3d.at<float>(2, 0);
444
dst_res_3d.at<float>(1, k) = tmp_mat_3d.at<float>(1, 0) /= tmp_mat_3d.at<float>(2, 0);
445
dst_res_3d.at<float>(2, k) = tmp_mat_3d.at<float>(2, 0) = 1.0f;
446
447
float *a = noise_2f.ptr<float>()+2*k;
448
noise_2d.at<float>(0, k) = a[0]; noise_2d.at<float>(1, k) = a[1];
449
450
for (int l = 0; l < COUNT_NORM_TYPES; ++l)
451
if (cv::norm(tmp_mat_3d, dst_mat_3d.col(k), NORM_TYPE[l]) - cv::norm(noise_2d.col(k), NORM_TYPE[l]) > max_2diff)
452
{
453
print_information_4(method, j, N, k, l, cv::norm(tmp_mat_3d, dst_mat_3d.col(k), NORM_TYPE[l]) - cv::norm(noise_2d.col(k), NORM_TYPE[l]));
454
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_1);
455
return;
456
}
457
458
}
459
460
for (int l = 0; l < COUNT_NORM_TYPES; ++l)
461
if (cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]) > max_diff)
462
{
463
print_information_5(method, j, N, l, cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]));
464
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_2);
465
return;
466
}
467
468
}
469
470
continue;
471
}
472
case cv::RHO:
473
case RANSAC:
474
{
475
cv::Mat mask_res [4];
476
477
Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method, reproj_threshold, mask_res[0]),
478
cv::findHomography(src_mat_2f, dst_vec, method, reproj_threshold, mask_res[1]),
479
cv::findHomography(src_vec, dst_mat_2f, method, reproj_threshold, mask_res[2]),
480
cv::findHomography(src_vec, dst_vec, method, reproj_threshold, mask_res[3]) };
481
482
for (int j = 0; j < 4; ++j)
483
{
484
if (!check_matrix_size(H_res_64[j]))
485
{
486
print_information_1(j, N, method, H_res_64[j]);
487
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);
488
return;
489
}
490
491
int code = check_ransac_mask_2(mask, mask_res[j]);
492
493
if (code)
494
{
495
print_information_3(method, j, N, mask_res[j]);
496
497
switch (code)
498
{
499
case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }
500
case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }
501
502
default: break;
503
}
504
505
return;
506
}
507
508
cv::Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);
509
510
cv::Mat dst_res_3d = H_res_32*src_mat_3d;
511
512
for (int k = 0; k < N; ++k)
513
{
514
dst_res_3d.at<float>(0, k) /= dst_res_3d.at<float>(2, k);
515
dst_res_3d.at<float>(1, k) /= dst_res_3d.at<float>(2, k);
516
dst_res_3d.at<float>(2, k) = 1.0f;
517
518
float *p = dst_mat_2f.ptr<float>()+2*k;
519
520
dst_mat_3d.at<float>(0, k) = p[0];
521
dst_mat_3d.at<float>(1, k) = p[1];
522
523
double diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_L2);
524
525
if (mask_res[j].at<bool>(k, 0) != (diff <= reproj_threshold))
526
{
527
print_information_6(method, j, N, k, diff, mask_res[j].at<bool>(k, 0));
528
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_4);
529
return;
530
}
531
532
if (mask.at<bool>(k, 0) && !mask_res[j].at<bool>(k, 0))
533
{
534
print_information_7(method, j, N, k, diff, mask.at<bool>(k, 0), mask_res[j].at<bool>(k, 0));
535
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_5);
536
return;
537
}
538
539
if (mask_res[j].at<bool>(k, 0))
540
{
541
float *a = noise_2f.ptr<float>()+2*k;
542
dst_mat_3d.at<float>(0, k) -= a[0];
543
dst_mat_3d.at<float>(1, k) -= a[1];
544
545
cv::Mat noise_2d(2, 1, CV_32F);
546
noise_2d.at<float>(0, 0) = a[0]; noise_2d.at<float>(1, 0) = a[1];
547
548
for (int l = 0; l < COUNT_NORM_TYPES; ++l)
549
{
550
diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_TYPE[l]);
551
552
if (diff - cv::norm(noise_2d, NORM_TYPE[l]) > max_2diff)
553
{
554
print_information_8(method, j, N, k, l, diff - cv::norm(noise_2d, NORM_TYPE[l]));
555
CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF, MESSAGE_RANSAC_DIFF);
556
return;
557
}
558
}
559
}
560
}
561
}
562
563
continue;
564
}
565
566
default: continue;
567
}
568
}
569
570
delete[]src_data;
571
src_data = NULL;
572
}
573
}
574
575
TEST(Calib3d_Homography, accuracy) { CV_HomographyTest test; test.safe_run(); }
576
577
TEST(Calib3d_Homography, EKcase)
578
{
579
float pt1data[] =
580
{
581
2.80073029e+002f, 2.39591217e+002f, 2.21912201e+002f, 2.59783997e+002f,
582
2.16053192e+002f, 2.78826569e+002f, 2.22782532e+002f, 2.82330383e+002f,
583
2.09924820e+002f, 2.89122559e+002f, 2.11077698e+002f, 2.89384674e+002f,
584
2.25287689e+002f, 2.88795532e+002f, 2.11180801e+002f, 2.89653503e+002f,
585
2.24126404e+002f, 2.90466064e+002f, 2.10914429e+002f, 2.90886963e+002f,
586
2.23439362e+002f, 2.91657715e+002f, 2.24809387e+002f, 2.91891602e+002f,
587
2.09809082e+002f, 2.92891113e+002f, 2.08771164e+002f, 2.93093231e+002f,
588
2.23160095e+002f, 2.93259460e+002f, 2.07874023e+002f, 2.93989990e+002f,
589
2.08963638e+002f, 2.94209839e+002f, 2.23963165e+002f, 2.94479645e+002f,
590
2.23241791e+002f, 2.94887817e+002f, 2.09438782e+002f, 2.95233337e+002f,
591
2.08901886e+002f, 2.95762878e+002f, 2.21867981e+002f, 2.95747711e+002f,
592
2.24195511e+002f, 2.98270905e+002f, 2.09331345e+002f, 3.05958191e+002f,
593
2.24727875e+002f, 3.07186035e+002f, 2.26718842e+002f, 3.08095795e+002f,
594
2.25363953e+002f, 3.08200226e+002f, 2.19897797e+002f, 3.13845093e+002f,
595
2.25013474e+002f, 3.15558777e+002f
596
};
597
598
float pt2data[] =
599
{
600
1.84072723e+002f, 1.43591202e+002f, 1.25912483e+002f, 1.63783859e+002f,
601
2.06439407e+002f, 2.20573929e+002f, 1.43801437e+002f, 1.80703903e+002f,
602
9.77904129e+000f, 2.49660202e+002f, 1.38458405e+001f, 2.14502701e+002f,
603
1.50636337e+002f, 2.15597183e+002f, 6.43103180e+001f, 2.51667648e+002f,
604
1.54952499e+002f, 2.20780014e+002f, 1.26638412e+002f, 2.43040924e+002f,
605
3.67568909e+002f, 1.83624954e+001f, 1.60657944e+002f, 2.21794052e+002f,
606
-1.29507828e+000f, 3.32472443e+002f, 8.51442242e+000f, 4.15561554e+002f,
607
1.27161377e+002f, 1.97260361e+002f, 5.40714645e+000f, 4.90978302e+002f,
608
2.25571690e+001f, 3.96912415e+002f, 2.95664978e+002f, 7.36064959e+000f,
609
1.27241104e+002f, 1.98887573e+002f, -1.25569367e+000f, 3.87713226e+002f,
610
1.04194012e+001f, 4.31495758e+002f, 1.25868874e+002f, 1.99751617e+002f,
611
1.28195480e+002f, 2.02270355e+002f, 2.23436356e+002f, 1.80489182e+002f,
612
1.28727692e+002f, 2.11185410e+002f, 2.03336639e+002f, 2.52182083e+002f,
613
1.29366486e+002f, 2.12201904e+002f, 1.23897598e+002f, 2.17847351e+002f,
614
1.29015259e+002f, 2.19560623e+002f
615
};
616
617
int npoints = (int)(sizeof(pt1data)/sizeof(pt1data[0])/2);
618
619
Mat p1(1, npoints, CV_32FC2, pt1data);
620
Mat p2(1, npoints, CV_32FC2, pt2data);
621
Mat mask;
622
623
Mat h = findHomography(p1, p2, RANSAC, 0.01, mask);
624
ASSERT_TRUE(!h.empty());
625
626
cv::transpose(mask, mask);
627
Mat p3, mask2;
628
int ninliers = countNonZero(mask);
629
Mat nmask[] = { mask, mask };
630
merge(nmask, 2, mask2);
631
perspectiveTransform(p1, p3, h);
632
mask2 = mask2.reshape(1);
633
p2 = p2.reshape(1);
634
p3 = p3.reshape(1);
635
double err = cvtest::norm(p2, p3, NORM_INF, mask2);
636
637
printf("ninliers: %d, inliers err: %.2g\n", ninliers, err);
638
ASSERT_GE(ninliers, 10);
639
ASSERT_LE(err, 0.01);
640
}
641
642
TEST(Calib3d_Homography, fromImages)
643
{
644
Mat img_1 = imread(cvtest::TS::ptr()->get_data_path() + "cv/optflow/image1.png", 0);
645
Mat img_2 = imread(cvtest::TS::ptr()->get_data_path() + "cv/optflow/image2.png", 0);
646
Ptr<ORB> orb = ORB::create();
647
vector<KeyPoint> keypoints_1, keypoints_2;
648
Mat descriptors_1, descriptors_2;
649
orb->detectAndCompute( img_1, Mat(), keypoints_1, descriptors_1, false );
650
orb->detectAndCompute( img_2, Mat(), keypoints_2, descriptors_2, false );
651
652
//-- Step 3: Matching descriptor vectors using Brute Force matcher
653
BFMatcher matcher(NORM_HAMMING,false);
654
std::vector< DMatch > matches;
655
matcher.match( descriptors_1, descriptors_2, matches );
656
657
double max_dist = 0; double min_dist = 100;
658
//-- Quick calculation of max and min distances between keypoints
659
for( int i = 0; i < descriptors_1.rows; i++ )
660
{
661
double dist = matches[i].distance;
662
if( dist < min_dist ) min_dist = dist;
663
if( dist > max_dist ) max_dist = dist;
664
}
665
666
//-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
667
std::vector< DMatch > good_matches;
668
for( int i = 0; i < descriptors_1.rows; i++ )
669
{
670
if( matches[i].distance <= 100 )
671
good_matches.push_back( matches[i]);
672
}
673
674
//-- Localize the model
675
std::vector<Point2f> pointframe1;
676
std::vector<Point2f> pointframe2;
677
for( int i = 0; i < (int)good_matches.size(); i++ )
678
{
679
//-- Get the keypoints from the good matches
680
pointframe1.push_back( keypoints_1[ good_matches[i].queryIdx ].pt );
681
pointframe2.push_back( keypoints_2[ good_matches[i].trainIdx ].pt );
682
}
683
684
Mat H0, H1, inliers0, inliers1;
685
double min_t0 = DBL_MAX, min_t1 = DBL_MAX;
686
for( int i = 0; i < 10; i++ )
687
{
688
double t = (double)getTickCount();
689
H0 = findHomography( pointframe1, pointframe2, RANSAC, 3.0, inliers0 );
690
t = (double)getTickCount() - t;
691
min_t0 = std::min(min_t0, t);
692
}
693
int ninliers0 = countNonZero(inliers0);
694
for( int i = 0; i < 10; i++ )
695
{
696
double t = (double)getTickCount();
697
H1 = findHomography( pointframe1, pointframe2, RHO, 3.0, inliers1 );
698
t = (double)getTickCount() - t;
699
min_t1 = std::min(min_t1, t);
700
}
701
int ninliers1 = countNonZero(inliers1);
702
double freq = getTickFrequency();
703
printf("nfeatures1 = %d, nfeatures2=%d, matches=%d, ninliers(RANSAC)=%d, "
704
"time(RANSAC)=%.2fmsec, ninliers(RHO)=%d, time(RHO)=%.2fmsec\n",
705
(int)keypoints_1.size(), (int)keypoints_2.size(),
706
(int)good_matches.size(), ninliers0, min_t0*1000./freq, ninliers1, min_t1*1000./freq);
707
708
ASSERT_TRUE(!H0.empty());
709
ASSERT_GE(ninliers0, 80);
710
ASSERT_TRUE(!H1.empty());
711
ASSERT_GE(ninliers1, 80);
712
}
713
714
}} // namespace
715
716