added licenses to some tests; updated new highgui tests
[profile/ivi/opencv.git] / modules / calib3d / test / test_homography.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
4 //\r
5 //  By downloading, copying, installing or using the software you agree to this license.\r
6 //  If you do not agree to this license, do not download, install,\r
7 //  copy or use the software.\r
8 //\r
9 //\r
10 //                           License Agreement\r
11 //                For Open Source Computer Vision Library\r
12 //\r
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.\r
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.\r
15 // Third party copyrights are property of their respective owners.\r
16 //\r
17 // Redistribution and use in source and binary forms, with or without modification,\r
18 // are permitted provided that the following conditions are met:\r
19 //\r
20 //   * Redistribution's of source code must retain the above copyright notice,\r
21 //     this list of conditions and the following disclaimer.\r
22 //\r
23 //   * Redistribution's in binary form must reproduce the above copyright notice,\r
24 //     this list of conditions and the following disclaimer in the documentation\r
25 //     and/or other materials provided with the distribution.\r
26 //\r
27 //   * The name of the copyright holders may not be used to endorse or promote products\r
28 //     derived from this software without specific prior written permission.\r
29 //\r
30 // This software is provided by the copyright holders and contributors "as is" and\r
31 // any express or implied warranties, including, but not limited to, the implied\r
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.\r
33 // In no event shall the Intel Corporation or contributors be liable for any direct,\r
34 // indirect, incidental, special, exemplary, or consequential damages\r
35 // (including, but not limited to, procurement of substitute goods or services;\r
36 // loss of use, data, or profits; or business interruption) however caused\r
37 // and on any theory of liability, whether in contract, strict liability,\r
38 // or tort (including negligence or otherwise) arising in any way out of\r
39 // the use of this software, even if advised of the possibility of such damage.\r
40 //\r
41 //M*/\r
42 \r
43 #include "test_precomp.hpp"\r
44 #include <time.h>\r
45 \r
46 #define CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE 1\r
47 #define CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF 2\r
48 #define CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF 3\r
49 #define CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK 4\r
50 #define CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF 5\r
51 \r
52 #define MESSAGE_MATRIX_SIZE "Homography matrix must have 3*3 sizes."\r
53 #define MESSAGE_MATRIX_DIFF "Accuracy of homography transformation matrix less than required."\r
54 #define MESSAGE_REPROJ_DIFF_1 "Reprojection error for current pair of points more than required."\r
55 #define MESSAGE_REPROJ_DIFF_2 "Reprojection error is not optimal."\r
56 #define MESSAGE_RANSAC_MASK_1 "Sizes of inliers/outliers mask are incorrect."\r
57 #define MESSAGE_RANSAC_MASK_2 "Mask mustn't have any outliers."\r
58 #define MESSAGE_RANSAC_MASK_3 "All values of mask must be 1 (true) or 0 (false)."\r
59 #define MESSAGE_RANSAC_MASK_4 "Mask of inliers/outliers is incorrect."\r
60 #define MESSAGE_RANSAC_MASK_5 "Inlier in original mask shouldn't be outlier in found mask."\r
61 #define MESSAGE_RANSAC_DIFF "Reprojection error for current pair of points more than required."\r
62 \r
63 #define MAX_COUNT_OF_POINTS 303\r
64 #define COUNT_NORM_TYPES 3\r
65 #define METHODS_COUNT 3\r
66 \r
67 size_t NORM_TYPE[COUNT_NORM_TYPES] = {cv::NORM_L1, cv::NORM_L2, cv::NORM_INF};\r
68 size_t METHOD[METHODS_COUNT] = {0, CV_RANSAC, CV_LMEDS};\r
69 \r
70 using namespace cv;\r
71 using namespace std;\r
72 \r
73 class CV_HomographyTest: public cvtest::ArrayTest\r
74 {\r
75 public:\r
76     CV_HomographyTest();\r
77     ~CV_HomographyTest();\r
78 \r
79     void run (int);\r
80 \r
81 protected:\r
82 \r
83     int method;\r
84     int image_size;\r
85     double reproj_threshold;\r
86     double sigma;\r
87 \r
88 private:\r
89         float max_diff, max_2diff;\r
90         bool check_matrix_size(const cv::Mat& H);\r
91         bool check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff);\r
92     int check_ransac_mask_1(const Mat& src, const Mat& mask);\r
93         int check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask);\r
94 \r
95         void print_information_1(int j, int N, int method, const Mat& H);\r
96         void print_information_2(int j, int N, int method, const Mat& H, const Mat& H_res, int k, double diff);\r
97         void print_information_3(int j, int N, const Mat& mask);\r
98         void print_information_4(int method, int j, int N, int k, int l, double diff);\r
99         void print_information_5(int method, int j, int N, int l, double diff);\r
100         void print_information_6(int j, int N, int k, double diff, bool value);\r
101         void print_information_7(int j, int N, int k, double diff, bool original_value, bool found_value);\r
102         void print_information_8(int j, int N, int k, int l, double diff);\r
103 };\r
104 \r
105 CV_HomographyTest::CV_HomographyTest() : max_diff(1e-2), max_2diff(2e-2)\r
106 {\r
107     method = 0;\r
108     image_size = 1e+2;\r
109     reproj_threshold = 3.0;\r
110     sigma = 0.01;\r
111 }\r
112 \r
113 CV_HomographyTest::~CV_HomographyTest() {}\r
114 \r
115 bool CV_HomographyTest::check_matrix_size(const cv::Mat& H) \r
116 {\r
117     return (H.rows == 3) && (H.cols == 3);\r
118 }\r
119 \r
120 bool CV_HomographyTest::check_matrix_diff(const cv::Mat& original, const cv::Mat& found, const int norm_type, double &diff)\r
121 {\r
122     diff = cv::norm(original, found, norm_type);\r
123     return diff <= max_diff;\r
124 }\r
125 \r
126 int CV_HomographyTest::check_ransac_mask_1(const Mat& src, const Mat& mask)\r
127 {\r
128     if (!(mask.cols == 1) && (mask.rows == src.cols)) return 1;\r
129     if (countNonZero(mask) < mask.rows) return 2;\r
130     for (int i = 0; i < mask.rows; ++i) if (mask.at<uchar>(i, 0) > 1) return 3;\r
131     return 0;\r
132 }\r
133 \r
134 int CV_HomographyTest::check_ransac_mask_2(const Mat& original_mask, const Mat& found_mask)\r
135 {\r
136     if (!(found_mask.cols == 1) && (found_mask.rows == original_mask.rows)) return 1;\r
137     for (int i = 0; i < found_mask.rows; ++i) if (found_mask.at<uchar>(i, 0) > 1) return 2;\r
138     return 0;\r
139 }\r
140 \r
141 void CV_HomographyTest::print_information_1(int j, int N, int method, const Mat& H)\r
142 {\r
143     cout << endl; cout << "Checking for homography matrix sizes..." << endl; cout << endl;\r
144     cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else  cout << "vector <Point2f>";\r
145     cout << "   Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;\r
146     cout << "Count of points: " << N << endl; cout << endl;\r
147     cout << "Method: "; if (method == 0) cout << 0; else if (method == 8) cout << "RANSAC"; else cout << "LMEDS"; cout << endl;\r
148     cout << "Homography matrix:" << endl; cout << endl;\r
149     cout << H << endl; cout << endl;\r
150     cout << "Number of rows: " << H.rows << "   Number of cols: " << H.cols << endl; cout << endl;\r
151 }\r
152 \r
153 void CV_HomographyTest::print_information_2(int j, int N, int method, const Mat& H, const Mat& H_res, int k, double diff)\r
154 {\r
155     cout << endl; cout << "Checking for accuracy of homography matrix computing..." << endl; cout << endl;\r
156     cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else  cout << "vector <Point2f>";\r
157     cout << "   Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;\r
158     cout << "Count of points: " << N << endl; cout << endl;\r
159     cout << "Method: "; if (method == 0) cout << 0; else if (method == 8) cout << "RANSAC"; else cout << "LMEDS"; cout << endl;\r
160     cout << "Original matrix:" << endl; cout << endl;\r
161     cout << H << endl; cout << endl;\r
162     cout << "Found matrix:" << endl; cout << endl;\r
163     cout << H_res << endl; cout << endl;\r
164     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;\r
165     cout << "Difference between matrices: " << diff << endl;\r
166     cout << "Maximum allowed difference: " << max_diff << endl; cout << endl;\r
167 }\r
168 \r
169 void CV_HomographyTest::print_information_3(int j, int N, const Mat& mask)\r
170 {\r
171     cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;\r
172     cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else  cout << "vector <Point2f>";\r
173     cout << "   Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;\r
174     cout << "Count of points: " << N << endl; cout << endl;\r
175     cout << "Method: RANSAC" << endl;\r
176     cout << "Found mask:" << endl; cout << endl;\r
177     cout << mask << endl; cout << endl;\r
178     cout << "Number of rows: " << mask.rows << "   Number of cols: " << mask.cols << endl; cout << endl;\r
179 }\r
180 \r
181 void CV_HomographyTest::print_information_4(int method, int j, int N, int k, int l, double diff)\r
182 {\r
183     cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;\r
184     cout << "Method: "; if (method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;\r
185     cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else  cout << "vector <Point2f>";\r
186     cout << "   Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;\r
187     cout << "Sigma of normal noise: " << sigma << endl;\r
188     cout << "Count of points: " << N << endl;\r
189     cout << "Number of point: " << k << endl;\r
190     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;\r
191     cout << "Difference with noise of point: " << diff << endl;\r
192     cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;\r
193 }\r
194 \r
195 void CV_HomographyTest::print_information_5(int method, int j, int N, int l, double diff)\r
196\r
197     cout << endl; cout << "Checking for accuracy of reprojection error computing..." << endl; cout << endl;\r
198     cout << "Method: "; if (method == 0) cout << 0 << endl; else cout << "CV_LMEDS" << endl;\r
199     cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else  cout << "vector <Point2f>";\r
200     cout << "   Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;\r
201     cout << "Sigma of normal noise: " << sigma << endl;\r
202     cout << "Count of points: " << N << endl;\r
203     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;\r
204     cout << "Difference with noise of points: " << diff << endl;\r
205     cout << "Maxumum allowed difference: " << max_diff << endl; cout << endl;\r
206 }\r
207 \r
208 void CV_HomographyTest::print_information_6(int j, int N, int k, double diff, bool value)\r
209 {\r
210     cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;\r
211     cout << "Method: RANSAC" << endl;\r
212     cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else  cout << "vector <Point2f>";\r
213     cout << "   Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;\r
214     cout << "Count of points: " << N << "   " << endl;\r
215     cout << "Number of point: " << k << "   " << endl;\r
216     cout << "Reprojection error for this point: " << diff << "   " << endl;\r
217     cout << "Reprojection error threshold: " << reproj_threshold << "   " << endl;\r
218     cout << "Value of found mask: "<< value << endl; cout << endl;\r
219 }\r
220 \r
221 void CV_HomographyTest::print_information_7(int j, int N, int k, double diff, bool original_value, bool found_value)\r
222 {\r
223     cout << endl; cout << "Checking for inliers/outliers mask..." << endl; cout << endl;\r
224     cout << "Method: RANSAC" << endl;\r
225     cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else  cout << "vector <Point2f>";\r
226     cout << "   Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;\r
227     cout << "Count of points: " << N << "   " << endl;\r
228     cout << "Number of point: " << k << "   " << endl;\r
229     cout << "Reprojection error for this point: " << diff << "   " << endl;\r
230     cout << "Reprojection error threshold: " << reproj_threshold << "   " << endl;\r
231     cout << "Value of original mask: "<< original_value << "   Value of found mask: " << found_value << endl; cout << endl;\r
232 }\r
233 \r
234 void CV_HomographyTest::print_information_8(int j, int N, int k, int l, double diff)\r
235 {\r
236     cout << endl; cout << "Checking for reprojection error of inlier..." << endl; cout << endl;\r
237     cout << "Method: RANSAC" << endl;\r
238     cout << "Sigma of normal noise: " << sigma << endl;\r
239     cout << "Type of srcPoints: "; if ((j>-1) && (j<2)) cout << "Mat of CV_32FC2"; else  cout << "vector <Point2f>";\r
240     cout << "   Type of dstPoints: "; if (j % 2 == 0) cout << "Mat of CV_32FC2"; else cout << "vector <Point2f>"; cout << endl;\r
241     cout << "Count of points: " << N << "   " << endl;\r
242     cout << "Number of point: " << k << "   " << endl;\r
243     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;\r
244     cout << "Difference with noise of point: " << diff << endl;\r
245     cout << "Maxumum allowed difference: " << max_2diff << endl; cout << endl;\r
246 }\r
247 \r
248 void CV_HomographyTest::run(int)\r
249 {\r
250     for (size_t N = 4; N <= MAX_COUNT_OF_POINTS; ++N)\r
251     {\r
252         RNG& rng = ts->get_rng();\r
253 \r
254         float *src_data = new float [2*N];\r
255 \r
256         for (size_t i = 0; i < N; ++i)\r
257         {\r
258             src_data[2*i] = (float)cvtest::randReal(rng)*image_size;\r
259             src_data[2*i+1] = (float)cvtest::randReal(rng)*image_size;\r
260         }\r
261 \r
262         cv::Mat src_mat_2f(1, N, CV_32FC2, src_data),\r
263         src_mat_2d(2, N, CV_32F, src_data),\r
264         src_mat_3d(3, N, CV_32F);\r
265         cv::Mat dst_mat_2f, dst_mat_2d, dst_mat_3d;\r
266 \r
267         vector <Point2f> src_vec, dst_vec;\r
268 \r
269         for (size_t i = 0; i < N; ++i)\r
270         {\r
271             float *tmp = src_mat_2d.ptr<float>()+2*i;\r
272             src_mat_3d.at<float>(0, i) = tmp[0];\r
273             src_mat_3d.at<float>(1, i) = tmp[1];\r
274             src_mat_3d.at<float>(2, i) = 1.0f;\r
275 \r
276             src_vec.push_back(Point2f(tmp[0], tmp[1]));\r
277         }\r
278 \r
279         double fi = cvtest::randReal(rng)*2*CV_PI;\r
280 \r
281         double t_x = cvtest::randReal(rng)*sqrt(image_size*1.0),\r
282         t_y = cvtest::randReal(rng)*sqrt(image_size*1.0);\r
283 \r
284         double Hdata[9] = { cos(fi), -sin(fi), t_x,\r
285                             sin(fi),  cos(fi), t_y,\r
286                             0.0f,     0.0f, 1.0f };\r
287 \r
288         cv::Mat H_64(3, 3, CV_64F, Hdata), H_32;\r
289 \r
290         H_64.convertTo(H_32, CV_32F);\r
291 \r
292         dst_mat_3d = H_32*src_mat_3d;\r
293 \r
294         dst_mat_2d.create(2, N, CV_32F); dst_mat_2f.create(1, N, CV_32FC2);\r
295 \r
296         for (size_t i = 0; i < N; ++i)\r
297         {\r
298             float *tmp_2f = dst_mat_2f.ptr<float>()+2*i;\r
299             tmp_2f[0] = dst_mat_2d.at<float>(0, i) = dst_mat_3d.at<float>(0, i) /= dst_mat_3d.at<float>(2, i);\r
300             tmp_2f[1] = dst_mat_2d.at<float>(1, i) = dst_mat_3d.at<float>(1, i) /= dst_mat_3d.at<float>(2, i);\r
301             dst_mat_3d.at<float>(2, i) = 1.0f;\r
302 \r
303             dst_vec.push_back(Point2f(tmp_2f[0], tmp_2f[1]));\r
304         }\r
305 \r
306         for (size_t i = 0; i < METHODS_COUNT; ++i)\r
307         {\r
308             method = METHOD[i];\r
309             switch (method)\r
310             {\r
311             case 0:\r
312             case CV_LMEDS:\r
313                 {\r
314                     Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, method),\r
315                                          cv::findHomography(src_mat_2f, dst_vec, method),\r
316                                          cv::findHomography(src_vec, dst_mat_2f, method),\r
317                                          cv::findHomography(src_vec, dst_vec, method) };\r
318 \r
319                     for (size_t j = 0; j < 4; ++j)\r
320                     {\r
321 \r
322                         if (!check_matrix_size(H_res_64[j]))\r
323                         {\r
324                             print_information_1(j, N, method, H_res_64[j]);\r
325                             CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);\r
326                             return;\r
327                         }\r
328 \r
329                         double diff;\r
330 \r
331                         for (size_t k = 0; k < COUNT_NORM_TYPES; ++k)\r
332                             if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))\r
333                             {\r
334                             print_information_2(j, N, method, H_64, H_res_64[j], k, diff);\r
335                             CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);\r
336                             return;\r
337                         }\r
338                     }\r
339 \r
340                     continue;\r
341                 }\r
342             case CV_RANSAC:\r
343                 {\r
344                     cv::Mat mask [4]; double diff;\r
345 \r
346                     Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, CV_RANSAC, reproj_threshold, mask[0]),\r
347                                          cv::findHomography(src_mat_2f, dst_vec, CV_RANSAC, reproj_threshold, mask[1]),\r
348                                          cv::findHomography(src_vec, dst_mat_2f, CV_RANSAC, reproj_threshold, mask[2]),\r
349                                          cv::findHomography(src_vec, dst_vec, CV_RANSAC, reproj_threshold, mask[3]) };\r
350 \r
351                     for (size_t j = 0; j < 4; ++j)\r
352                     {\r
353 \r
354                         if (!check_matrix_size(H_res_64[j]))\r
355                         {\r
356                             print_information_1(j, N, method, H_res_64[j]);\r
357                             CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);\r
358                             return;\r
359                         }\r
360 \r
361                         for (size_t k = 0; k < COUNT_NORM_TYPES; ++k)\r
362                             if (!check_matrix_diff(H_64, H_res_64[j], NORM_TYPE[k], diff))\r
363                             {\r
364                             print_information_2(j, N, method, H_64, H_res_64[j], k, diff);\r
365                             CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_DIFF, MESSAGE_MATRIX_DIFF);\r
366                             return;\r
367                         }\r
368 \r
369                         int code = check_ransac_mask_1(src_mat_2f, mask[j]);\r
370 \r
371                         if (code)\r
372                         {\r
373                             print_information_3(j, N, mask[j]);\r
374                                                         \r
375                             switch (code)\r
376                             {\r
377                             case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }\r
378                             case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_2); break; }\r
379                             case 3: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }\r
380 \r
381                             default: break;\r
382                             }\r
383                                                         \r
384                             return;\r
385                         }\r
386 \r
387                     }\r
388 \r
389                     continue;\r
390                 }\r
391 \r
392             default: continue;\r
393             }\r
394         }\r
395 \r
396         Mat noise_2f(1, N, CV_32FC2);\r
397         rng.fill(noise_2f, RNG::NORMAL, Scalar::all(0), Scalar::all(sigma));\r
398 \r
399         cv::Mat mask(N, 1, CV_8UC1);\r
400 \r
401         for (size_t i = 0; i < N; ++i)\r
402         {\r
403             float *a = noise_2f.ptr<float>()+2*i, *_2f = dst_mat_2f.ptr<float>()+2*i;\r
404             _2f[0] += a[0]; _2f[1] += a[1];\r
405             mask.at<bool>(i, 0) = !(sqrt(a[0]*a[0]+a[1]*a[1]) > reproj_threshold);\r
406         }\r
407 \r
408         for (size_t i = 0; i < METHODS_COUNT; ++i)\r
409         {\r
410             method = METHOD[i];\r
411             switch (method)\r
412             {\r
413             case 0:\r
414             case CV_LMEDS:\r
415                                 {\r
416                     Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f),\r
417                                          cv::findHomography(src_mat_2f, dst_vec),\r
418                                          cv::findHomography(src_vec, dst_mat_2f),\r
419                                          cv::findHomography(src_vec, dst_vec) };\r
420 \r
421                     for (size_t j = 0; j < 4; ++j)\r
422                     {\r
423 \r
424                         if (!check_matrix_size(H_res_64[j]))\r
425                         {\r
426                             print_information_1(j, N, method, H_res_64[j]);\r
427                             CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);\r
428                             return;\r
429                         }\r
430 \r
431                         Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);\r
432 \r
433                         cv::Mat dst_res_3d(3, N, CV_32F), noise_2d(2, N, CV_32F);\r
434 \r
435                         for (size_t k = 0; k < N; ++k)\r
436                         {\r
437 \r
438                             Mat tmp_mat_3d = H_res_32*src_mat_3d.col(k);\r
439 \r
440                             dst_res_3d.at<float>(0, k) = tmp_mat_3d.at<float>(0, 0) /= tmp_mat_3d.at<float>(2, 0);\r
441                             dst_res_3d.at<float>(1, k) = tmp_mat_3d.at<float>(1, 0) /= tmp_mat_3d.at<float>(2, 0);\r
442                             dst_res_3d.at<float>(2, k) = tmp_mat_3d.at<float>(2, 0) = 1.0f;\r
443 \r
444                             float *a = noise_2f.ptr<float>()+2*k;\r
445                             noise_2d.at<float>(0, k) = a[0]; noise_2d.at<float>(1, k) = a[1];\r
446 \r
447                             for (size_t l = 0; l < COUNT_NORM_TYPES; ++l)\r
448                                 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)\r
449                                 {\r
450                                 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]));\r
451                                 CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_1);\r
452                                 return;\r
453                             }\r
454 \r
455                         }\r
456 \r
457                         for (size_t l = 0; l < COUNT_NORM_TYPES; ++l)\r
458                             if (cv::norm(dst_res_3d, dst_mat_3d, NORM_TYPE[l]) - cv::norm(noise_2d, NORM_TYPE[l]) > max_diff)\r
459                             {\r
460                             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]));\r
461                             CV_Error(CALIB3D_HOMOGRAPHY_ERROR_REPROJ_DIFF, MESSAGE_REPROJ_DIFF_2);\r
462                             return;\r
463                         }\r
464 \r
465                     }\r
466 \r
467                     continue;\r
468                                 }\r
469             case CV_RANSAC:\r
470                 {\r
471                     cv::Mat mask_res [4];\r
472 \r
473                     Mat H_res_64 [4] = { cv::findHomography(src_mat_2f, dst_mat_2f, CV_RANSAC, reproj_threshold, mask_res[0]),\r
474                                          cv::findHomography(src_mat_2f, dst_vec, CV_RANSAC, reproj_threshold, mask_res[1]),\r
475                                          cv::findHomography(src_vec, dst_mat_2f, CV_RANSAC, reproj_threshold, mask_res[2]),\r
476                                          cv::findHomography(src_vec, dst_vec, CV_RANSAC, reproj_threshold, mask_res[3]) };\r
477 \r
478                     for (size_t j = 0; j < 4; ++j)\r
479                     {\r
480 \r
481                         if (!check_matrix_size(H_res_64[j]))\r
482                         {\r
483                             print_information_1(j, N, method, H_res_64[j]);\r
484                             CV_Error(CALIB3D_HOMOGRAPHY_ERROR_MATRIX_SIZE, MESSAGE_MATRIX_SIZE);\r
485                             return;\r
486                         }\r
487 \r
488                         int code = check_ransac_mask_2(mask, mask_res[j]);\r
489 \r
490                         if (code)\r
491                         {\r
492                             print_information_3(j, N, mask_res[j]);\r
493 \r
494                             switch (code)\r
495                             {\r
496                             case 1: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_1); break; }\r
497                             case 2: { CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_3); break; }\r
498 \r
499                             default: break;\r
500                             }\r
501 \r
502                             return;\r
503                         }\r
504 \r
505                         cv::Mat H_res_32; H_res_64[j].convertTo(H_res_32, CV_32F);\r
506 \r
507                         cv::Mat dst_res_3d = H_res_32*src_mat_3d;\r
508 \r
509                         for (size_t k = 0; k < N; ++k)\r
510                         {\r
511                             dst_res_3d.at<float>(0, k) /= dst_res_3d.at<float>(2, k);\r
512                             dst_res_3d.at<float>(1, k) /= dst_res_3d.at<float>(2, k);\r
513                             dst_res_3d.at<float>(2, k) = 1.0f;\r
514 \r
515                             float *p = dst_mat_2f.ptr<float>()+2*k;\r
516 \r
517                             dst_mat_3d.at<float>(0, k) = p[0];\r
518                             dst_mat_3d.at<float>(1, k) = p[1];\r
519 \r
520                             double diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_L2);\r
521 \r
522                             if (mask_res[j].at<bool>(k, 0) != (diff <= reproj_threshold))\r
523                             {\r
524                                 print_information_6(j, N, k, diff, mask_res[j].at<bool>(k, 0));\r
525                                 CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_4);\r
526                                 return;\r
527                             }\r
528 \r
529                             if (mask.at<bool>(k, 0) && !mask_res[j].at<bool>(k, 0))\r
530                             {\r
531                                 print_information_7(j, N, k, diff, mask.at<bool>(k, 0), mask_res[j].at<bool>(k, 0));\r
532                                 CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_MASK, MESSAGE_RANSAC_MASK_5);\r
533                                 return;\r
534                             }\r
535 \r
536                             if (mask_res[j].at<bool>(k, 0))\r
537                             {\r
538                                 float *a = noise_2f.ptr<float>()+2*k;\r
539                                 dst_mat_3d.at<float>(0, k) -= a[0];\r
540                                 dst_mat_3d.at<float>(1, k) -= a[1];\r
541 \r
542                                 cv::Mat noise_2d(2, 1, CV_32F);\r
543                                 noise_2d.at<float>(0, 0) = a[0]; noise_2d.at<float>(1, 0) = a[1];\r
544 \r
545                                 for (size_t l = 0; l < COUNT_NORM_TYPES; ++l)\r
546                                 {\r
547                                     diff = cv::norm(dst_res_3d.col(k), dst_mat_3d.col(k), NORM_TYPE[l]);\r
548 \r
549                                     if (diff - cv::norm(noise_2d, NORM_TYPE[l]) > max_2diff)\r
550                                     {\r
551                                         print_information_8(j, N, k, l, diff - cv::norm(noise_2d, NORM_TYPE[l]));\r
552                                         CV_Error(CALIB3D_HOMOGRAPHY_ERROR_RANSAC_DIFF, MESSAGE_RANSAC_DIFF);\r
553                                         return;\r
554                                     }\r
555                                 }\r
556                             }\r
557                         }\r
558                     }\r
559                                         \r
560                     continue;\r
561                 }\r
562 \r
563             default: continue;\r
564             }\r
565         }\r
566     }\r
567 }\r
568 \r
569 TEST(Calib3d_Homography, accuracy) { CV_HomographyTest test; test.safe_run(); }\r