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, Intel Corporation, all rights reserved.
14 // Copyright (C) 2013, OpenCV Foundation, 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 /****************************************************************************************\
44 * Exhaustive Linearization for Robust Camera Pose and Focal Length Estimation.
45 * Contributed by Edgar Riba
46 \****************************************************************************************/
47
48 #include "precomp.hpp"
49 #include "upnp.h"
50 #include <limits>
51
52 using namespace std;
53 using namespace cv;
54
upnp(const Mat & cameraMatrix,const Mat & opoints,const Mat & ipoints)55 upnp::upnp(const Mat& cameraMatrix, const Mat& opoints, const Mat& ipoints)
56 {
57 if (cameraMatrix.depth() == CV_32F)
58 init_camera_parameters<float>(cameraMatrix);
59 else
60 init_camera_parameters<double>(cameraMatrix);
61
62 number_of_correspondences = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F));
63
64 pws.resize(3 * number_of_correspondences);
65 us.resize(2 * number_of_correspondences);
66
67 if (opoints.depth() == ipoints.depth())
68 {
69 if (opoints.depth() == CV_32F)
70 init_points<Point3f,Point2f>(opoints, ipoints);
71 else
72 init_points<Point3d,Point2d>(opoints, ipoints);
73 }
74 else if (opoints.depth() == CV_32F)
75 init_points<Point3f,Point2d>(opoints, ipoints);
76 else
77 init_points<Point3d,Point2f>(opoints, ipoints);
78
79 alphas.resize(4 * number_of_correspondences);
80 pcs.resize(3 * number_of_correspondences);
81
82 max_nr = 0;
83 A1 = NULL;
84 A2 = NULL;
85 }
86
~upnp()87 upnp::~upnp()
88 {
89 if (A1)
90 delete[] A1;
91 if (A2)
92 delete[] A2;
93 }
94
compute_pose(Mat & R,Mat & t)95 double upnp::compute_pose(Mat& R, Mat& t)
96 {
97 choose_control_points();
98 compute_alphas();
99
100 Mat * M = new Mat(2 * number_of_correspondences, 12, CV_64F);
101
102 for(int i = 0; i < number_of_correspondences; i++)
103 {
104 fill_M(M, 2 * i, &alphas[0] + 4 * i, us[2 * i], us[2 * i + 1]);
105 }
106
107 double mtm[12 * 12], d[12], ut[12 * 12], vt[12 * 12];
108 Mat MtM = Mat(12, 12, CV_64F, mtm);
109 Mat D = Mat(12, 1, CV_64F, d);
110 Mat Ut = Mat(12, 12, CV_64F, ut);
111 Mat Vt = Mat(12, 12, CV_64F, vt);
112
113 MtM = M->t() * (*M);
114 SVD::compute(MtM, D, Ut, Vt, SVD::MODIFY_A | SVD::FULL_UV);
115 Mat(Ut.t()).copyTo(Ut);
116 M->release();
117
118 double l_6x12[6 * 12], rho[6];
119 Mat L_6x12 = Mat(6, 12, CV_64F, l_6x12);
120 Mat Rho = Mat(6, 1, CV_64F, rho);
121
122 compute_L_6x12(ut, l_6x12);
123 compute_rho(rho);
124
125 double Betas[3][4], Efs[3][1], rep_errors[3];
126 double Rs[3][3][3], ts[3][3];
127
128 find_betas_and_focal_approx_1(&Ut, &Rho, Betas[1], Efs[1]);
129 gauss_newton(&L_6x12, &Rho, Betas[1], Efs[1]);
130 rep_errors[1] = compute_R_and_t(ut, Betas[1], Rs[1], ts[1]);
131
132 find_betas_and_focal_approx_2(&Ut, &Rho, Betas[2], Efs[2]);
133 gauss_newton(&L_6x12, &Rho, Betas[2], Efs[2]);
134 rep_errors[2] = compute_R_and_t(ut, Betas[2], Rs[2], ts[2]);
135
136 int N = 1;
137 if (rep_errors[2] < rep_errors[1]) N = 2;
138
139 Mat(3, 1, CV_64F, ts[N]).copyTo(t);
140 Mat(3, 3, CV_64F, Rs[N]).copyTo(R);
141 fu = fv = Efs[N][0];
142
143 return fu;
144 }
145
copy_R_and_t(const double R_src[3][3],const double t_src[3],double R_dst[3][3],double t_dst[3])146 void upnp::copy_R_and_t(const double R_src[3][3], const double t_src[3],
147 double R_dst[3][3], double t_dst[3])
148 {
149 for(int i = 0; i < 3; i++) {
150 for(int j = 0; j < 3; j++)
151 R_dst[i][j] = R_src[i][j];
152 t_dst[i] = t_src[i];
153 }
154 }
155
estimate_R_and_t(double R[3][3],double t[3])156 void upnp::estimate_R_and_t(double R[3][3], double t[3])
157 {
158 double pc0[3], pw0[3];
159
160 pc0[0] = pc0[1] = pc0[2] = 0.0;
161 pw0[0] = pw0[1] = pw0[2] = 0.0;
162
163 for(int i = 0; i < number_of_correspondences; i++) {
164 const double * pc = &pcs[3 * i];
165 const double * pw = &pws[3 * i];
166
167 for(int j = 0; j < 3; j++) {
168 pc0[j] += pc[j];
169 pw0[j] += pw[j];
170 }
171 }
172 for(int j = 0; j < 3; j++) {
173 pc0[j] /= number_of_correspondences;
174 pw0[j] /= number_of_correspondences;
175 }
176
177 double abt[3 * 3], abt_d[3], abt_u[3 * 3], abt_v[3 * 3];
178 Mat ABt = Mat(3, 3, CV_64F, abt);
179 Mat ABt_D = Mat(3, 1, CV_64F, abt_d);
180 Mat ABt_U = Mat(3, 3, CV_64F, abt_u);
181 Mat ABt_V = Mat(3, 3, CV_64F, abt_v);
182
183 ABt.setTo(0.0);
184 for(int i = 0; i < number_of_correspondences; i++) {
185 double * pc = &pcs[3 * i];
186 double * pw = &pws[3 * i];
187
188 for(int j = 0; j < 3; j++) {
189 abt[3 * j ] += (pc[j] - pc0[j]) * (pw[0] - pw0[0]);
190 abt[3 * j + 1] += (pc[j] - pc0[j]) * (pw[1] - pw0[1]);
191 abt[3 * j + 2] += (pc[j] - pc0[j]) * (pw[2] - pw0[2]);
192 }
193 }
194
195 SVD::compute(ABt, ABt_D, ABt_U, ABt_V, SVD::MODIFY_A);
196 Mat(ABt_V.t()).copyTo(ABt_V);
197
198 for(int i = 0; i < 3; i++)
199 for(int j = 0; j < 3; j++)
200 R[i][j] = dot(abt_u + 3 * i, abt_v + 3 * j);
201
202 const double det =
203 R[0][0] * R[1][1] * R[2][2] + R[0][1] * R[1][2] * R[2][0] + R[0][2] * R[1][0] * R[2][1] -
204 R[0][2] * R[1][1] * R[2][0] - R[0][1] * R[1][0] * R[2][2] - R[0][0] * R[1][2] * R[2][1];
205
206 if (det < 0) {
207 R[2][0] = -R[2][0];
208 R[2][1] = -R[2][1];
209 R[2][2] = -R[2][2];
210 }
211
212 t[0] = pc0[0] - dot(R[0], pw0);
213 t[1] = pc0[1] - dot(R[1], pw0);
214 t[2] = pc0[2] - dot(R[2], pw0);
215 }
216
solve_for_sign(void)217 void upnp::solve_for_sign(void)
218 {
219 if (pcs[2] < 0.0) {
220 for(int i = 0; i < 4; i++)
221 for(int j = 0; j < 3; j++)
222 ccs[i][j] = -ccs[i][j];
223
224 for(int i = 0; i < number_of_correspondences; i++) {
225 pcs[3 * i ] = -pcs[3 * i];
226 pcs[3 * i + 1] = -pcs[3 * i + 1];
227 pcs[3 * i + 2] = -pcs[3 * i + 2];
228 }
229 }
230 }
231
compute_R_and_t(const double * ut,const double * betas,double R[3][3],double t[3])232 double upnp::compute_R_and_t(const double * ut, const double * betas,
233 double R[3][3], double t[3])
234 {
235 compute_ccs(betas, ut);
236 compute_pcs();
237
238 solve_for_sign();
239
240 estimate_R_and_t(R, t);
241
242 return reprojection_error(R, t);
243 }
244
reprojection_error(const double R[3][3],const double t[3])245 double upnp::reprojection_error(const double R[3][3], const double t[3])
246 {
247 double sum2 = 0.0;
248
249 for(int i = 0; i < number_of_correspondences; i++) {
250 double * pw = &pws[3 * i];
251 double Xc = dot(R[0], pw) + t[0];
252 double Yc = dot(R[1], pw) + t[1];
253 double inv_Zc = 1.0 / (dot(R[2], pw) + t[2]);
254 double ue = uc + fu * Xc * inv_Zc;
255 double ve = vc + fv * Yc * inv_Zc;
256 double u = us[2 * i], v = us[2 * i + 1];
257
258 sum2 += sqrt( (u - ue) * (u - ue) + (v - ve) * (v - ve) );
259 }
260
261 return sum2 / number_of_correspondences;
262 }
263
choose_control_points()264 void upnp::choose_control_points()
265 {
266 for (int i = 0; i < 4; ++i)
267 cws[i][0] = cws[i][1] = cws[i][2] = 0.0;
268 cws[0][0] = cws[1][1] = cws[2][2] = 1.0;
269 }
270
compute_alphas()271 void upnp::compute_alphas()
272 {
273 Mat CC = Mat(4, 3, CV_64F, &cws);
274 Mat PC = Mat(number_of_correspondences, 3, CV_64F, &pws[0]);
275 Mat ALPHAS = Mat(number_of_correspondences, 4, CV_64F, &alphas[0]);
276
277 Mat CC_ = CC.clone().t();
278 Mat PC_ = PC.clone().t();
279
280 Mat row14 = Mat::ones(1, 4, CV_64F);
281 Mat row1n = Mat::ones(1, number_of_correspondences, CV_64F);
282
283 CC_.push_back(row14);
284 PC_.push_back(row1n);
285
286 ALPHAS = Mat( CC_.inv() * PC_ ).t();
287 }
288
fill_M(Mat * M,const int row,const double * as,const double u,const double v)289 void upnp::fill_M(Mat * M, const int row, const double * as, const double u, const double v)
290 {
291 double * M1 = M->ptr<double>(row);
292 double * M2 = M1 + 12;
293
294 for(int i = 0; i < 4; i++) {
295 M1[3 * i ] = as[i] * fu;
296 M1[3 * i + 1] = 0.0;
297 M1[3 * i + 2] = as[i] * (uc - u);
298
299 M2[3 * i ] = 0.0;
300 M2[3 * i + 1] = as[i] * fv;
301 M2[3 * i + 2] = as[i] * (vc - v);
302 }
303 }
304
compute_ccs(const double * betas,const double * ut)305 void upnp::compute_ccs(const double * betas, const double * ut)
306 {
307 for(int i = 0; i < 4; ++i)
308 ccs[i][0] = ccs[i][1] = ccs[i][2] = 0.0;
309
310 int N = 4;
311 for(int i = 0; i < N; ++i) {
312 const double * v = ut + 12 * (9 + i);
313 for(int j = 0; j < 4; ++j)
314 for(int k = 0; k < 3; ++k)
315 ccs[j][k] += betas[i] * v[3 * j + k];
316 }
317
318 for (int i = 0; i < 4; ++i) ccs[i][2] *= fu;
319 }
320
compute_pcs(void)321 void upnp::compute_pcs(void)
322 {
323 for(int i = 0; i < number_of_correspondences; i++) {
324 double * a = &alphas[0] + 4 * i;
325 double * pc = &pcs[0] + 3 * i;
326
327 for(int j = 0; j < 3; j++)
328 pc[j] = a[0] * ccs[0][j] + a[1] * ccs[1][j] + a[2] * ccs[2][j] + a[3] * ccs[3][j];
329 }
330 }
331
find_betas_and_focal_approx_1(Mat * Ut,Mat * Rho,double * betas,double * efs)332 void upnp::find_betas_and_focal_approx_1(Mat * Ut, Mat * Rho, double * betas, double * efs)
333 {
334 Mat Kmf1 = Mat(12, 1, CV_64F, Ut->ptr<double>(11));
335 Mat dsq = Mat(6, 1, CV_64F, Rho->ptr<double>(0));
336
337 Mat D = compute_constraint_distance_2param_6eq_2unk_f_unk( Kmf1 );
338 Mat Dt = D.t();
339
340 Mat A = Dt * D;
341 Mat b = Dt * dsq;
342
343 Mat x = Mat(2, 1, CV_64F);
344 solve(A, b, x);
345
346 betas[0] = sqrt( abs( x.at<double>(0) ) );
347 betas[1] = betas[2] = betas[3] = 0.0;
348
349 efs[0] = sqrt( abs( x.at<double>(1) ) ) / betas[0];
350 }
351
find_betas_and_focal_approx_2(Mat * Ut,Mat * Rho,double * betas,double * efs)352 void upnp::find_betas_and_focal_approx_2(Mat * Ut, Mat * Rho, double * betas, double * efs)
353 {
354 double u[12*12];
355 Mat U = Mat(12, 12, CV_64F, u);
356 Ut->copyTo(U);
357
358 Mat Kmf1 = Mat(12, 1, CV_64F, Ut->ptr<double>(10));
359 Mat Kmf2 = Mat(12, 1, CV_64F, Ut->ptr<double>(11));
360 Mat dsq = Mat(6, 1, CV_64F, Rho->ptr<double>(0));
361
362 Mat D = compute_constraint_distance_3param_6eq_6unk_f_unk( Kmf1, Kmf2 );
363
364 Mat A = D;
365 Mat b = dsq;
366
367 double x[6];
368 Mat X = Mat(6, 1, CV_64F, x);
369
370 solve(A, b, X, DECOMP_QR);
371
372 double solutions[18][3];
373 generate_all_possible_solutions_for_f_unk(x, solutions);
374
375 // find solution with minimum reprojection error
376 double min_error = std::numeric_limits<double>::max();
377 int min_sol = 0;
378 for (int i = 0; i < 18; ++i) {
379
380 betas[3] = solutions[i][0];
381 betas[2] = solutions[i][1];
382 betas[1] = betas[0] = 0.0;
383 fu = fv = solutions[i][2];
384
385 double Rs[3][3], ts[3];
386 double error_i = compute_R_and_t( u, betas, Rs, ts);
387
388 if( error_i < min_error)
389 {
390 min_error = error_i;
391 min_sol = i;
392 }
393 }
394
395 betas[0] = solutions[min_sol][0];
396 betas[1] = solutions[min_sol][1];
397 betas[2] = betas[3] = 0.0;
398
399 efs[0] = solutions[min_sol][2];
400 }
401
compute_constraint_distance_2param_6eq_2unk_f_unk(const Mat & M1)402 Mat upnp::compute_constraint_distance_2param_6eq_2unk_f_unk(const Mat& M1)
403 {
404 Mat P = Mat(6, 2, CV_64F);
405
406 double m[13];
407 for (int i = 1; i < 13; ++i) m[i] = *M1.ptr<double>(i-1);
408
409 double t1 = pow( m[4], 2 );
410 double t4 = pow( m[1], 2 );
411 double t5 = pow( m[5], 2 );
412 double t8 = pow( m[2], 2 );
413 double t10 = pow( m[6], 2 );
414 double t13 = pow( m[3], 2 );
415 double t15 = pow( m[7], 2 );
416 double t18 = pow( m[8], 2 );
417 double t22 = pow( m[9], 2 );
418 double t26 = pow( m[10], 2 );
419 double t29 = pow( m[11], 2 );
420 double t33 = pow( m[12], 2 );
421
422 *P.ptr<double>(0,0) = t1 - 2 * m[4] * m[1] + t4 + t5 - 2 * m[5] * m[2] + t8;
423 *P.ptr<double>(0,1) = t10 - 2 * m[6] * m[3] + t13;
424 *P.ptr<double>(1,0) = t15 - 2 * m[7] * m[1] + t4 + t18 - 2 * m[8] * m[2] + t8;
425 *P.ptr<double>(1,1) = t22 - 2 * m[9] * m[3] + t13;
426 *P.ptr<double>(2,0) = t26 - 2 * m[10] * m[1] + t4 + t29 - 2 * m[11] * m[2] + t8;
427 *P.ptr<double>(2,1) = t33 - 2 * m[12] * m[3] + t13;
428 *P.ptr<double>(3,0) = t15 - 2 * m[7] * m[4] + t1 + t18 - 2 * m[8] * m[5] + t5;
429 *P.ptr<double>(3,1) = t22 - 2 * m[9] * m[6] + t10;
430 *P.ptr<double>(4,0) = t26 - 2 * m[10] * m[4] + t1 + t29 - 2 * m[11] * m[5] + t5;
431 *P.ptr<double>(4,1) = t33 - 2 * m[12] * m[6] + t10;
432 *P.ptr<double>(5,0) = t26 - 2 * m[10] * m[7] + t15 + t29 - 2 * m[11] * m[8] + t18;
433 *P.ptr<double>(5,1) = t33 - 2 * m[12] * m[9] + t22;
434
435 return P;
436 }
437
compute_constraint_distance_3param_6eq_6unk_f_unk(const Mat & M1,const Mat & M2)438 Mat upnp::compute_constraint_distance_3param_6eq_6unk_f_unk(const Mat& M1, const Mat& M2)
439 {
440 Mat P = Mat(6, 6, CV_64F);
441
442 double m[3][13];
443 for (int i = 1; i < 13; ++i)
444 {
445 m[1][i] = *M1.ptr<double>(i-1);
446 m[2][i] = *M2.ptr<double>(i-1);
447 }
448
449 double t1 = pow( m[1][4], 2 );
450 double t2 = pow( m[1][1], 2 );
451 double t7 = pow( m[1][5], 2 );
452 double t8 = pow( m[1][2], 2 );
453 double t11 = m[1][1] * m[2][1];
454 double t12 = m[1][5] * m[2][5];
455 double t15 = m[1][2] * m[2][2];
456 double t16 = m[1][4] * m[2][4];
457 double t19 = pow( m[2][4], 2 );
458 double t22 = pow( m[2][2], 2 );
459 double t23 = pow( m[2][1], 2 );
460 double t24 = pow( m[2][5], 2 );
461 double t28 = pow( m[1][6], 2 );
462 double t29 = pow( m[1][3], 2 );
463 double t34 = pow( m[1][3], 2 );
464 double t36 = m[1][6] * m[2][6];
465 double t40 = pow( m[2][6], 2 );
466 double t41 = pow( m[2][3], 2 );
467 double t47 = pow( m[1][7], 2 );
468 double t48 = pow( m[1][8], 2 );
469 double t52 = m[1][7] * m[2][7];
470 double t55 = m[1][8] * m[2][8];
471 double t59 = pow( m[2][8], 2 );
472 double t62 = pow( m[2][7], 2 );
473 double t64 = pow( m[1][9], 2 );
474 double t68 = m[1][9] * m[2][9];
475 double t74 = pow( m[2][9], 2 );
476 double t78 = pow( m[1][10], 2 );
477 double t79 = pow( m[1][11], 2 );
478 double t84 = m[1][10] * m[2][10];
479 double t87 = m[1][11] * m[2][11];
480 double t90 = pow( m[2][10], 2 );
481 double t95 = pow( m[2][11], 2 );
482 double t99 = pow( m[1][12], 2 );
483 double t101 = m[1][12] * m[2][12];
484 double t105 = pow( m[2][12], 2 );
485
486 *P.ptr<double>(0,0) = t1 + t2 - 2 * m[1][4] * m[1][1] - 2 * m[1][5] * m[1][2] + t7 + t8;
487 *P.ptr<double>(0,1) = -2 * m[2][4] * m[1][1] + 2 * t11 + 2 * t12 - 2 * m[1][4] * m[2][1] - 2 * m[2][5] * m[1][2] + 2 * t15 + 2 * t16 - 2 * m[1][5] * m[2][2];
488 *P.ptr<double>(0,2) = t19 - 2 * m[2][4] * m[2][1] + t22 + t23 + t24 - 2 * m[2][5] * m[2][2];
489 *P.ptr<double>(0,3) = t28 + t29 - 2 * m[1][6] * m[1][3];
490 *P.ptr<double>(0,4) = -2 * m[2][6] * m[1][3] + 2 * t34 - 2 * m[1][6] * m[2][3] + 2 * t36;
491 *P.ptr<double>(0,5) = -2 * m[2][6] * m[2][3] + t40 + t41;
492
493 *P.ptr<double>(1,0) = t8 - 2 * m[1][8] * m[1][2] - 2 * m[1][7] * m[1][1] + t47 + t48 + t2;
494 *P.ptr<double>(1,1) = 2 * t15 - 2 * m[1][8] * m[2][2] - 2 * m[2][8] * m[1][2] + 2 * t52 - 2 * m[1][7] * m[2][1] - 2 * m[2][7] * m[1][1] + 2 * t55 + 2 * t11;
495 *P.ptr<double>(1,2) = -2 * m[2][8] * m[2][2] + t22 + t23 + t59 - 2 * m[2][7] * m[2][1] + t62;
496 *P.ptr<double>(1,3) = t29 + t64 - 2 * m[1][9] * m[1][3];
497 *P.ptr<double>(1,4) = 2 * t34 + 2 * t68 - 2 * m[2][9] * m[1][3] - 2 * m[1][9] * m[2][3];
498 *P.ptr<double>(1,5) = -2 * m[2][9] * m[2][3] + t74 + t41;
499
500 *P.ptr<double>(2,0) = -2 * m[1][11] * m[1][2] + t2 + t8 + t78 + t79 - 2 * m[1][10] * m[1][1];
501 *P.ptr<double>(2,1) = 2 * t15 - 2 * m[1][11] * m[2][2] + 2 * t84 - 2 * m[1][10] * m[2][1] - 2 * m[2][10] * m[1][1] + 2 * t87 - 2 * m[2][11] * m[1][2]+ 2 * t11;
502 *P.ptr<double>(2,2) = t90 + t22 - 2 * m[2][10] * m[2][1] + t23 - 2 * m[2][11] * m[2][2] + t95;
503 *P.ptr<double>(2,3) = -2 * m[1][12] * m[1][3] + t99 + t29;
504 *P.ptr<double>(2,4) = 2 * t34 + 2 * t101 - 2 * m[2][12] * m[1][3] - 2 * m[1][12] * m[2][3];
505 *P.ptr<double>(2,5) = t41 + t105 - 2 * m[2][12] * m[2][3];
506
507 *P.ptr<double>(3,0) = t48 + t1 - 2 * m[1][8] * m[1][5] + t7 - 2 * m[1][7] * m[1][4] + t47;
508 *P.ptr<double>(3,1) = 2 * t16 - 2 * m[1][7] * m[2][4] + 2 * t55 + 2 * t52 - 2 * m[1][8] * m[2][5] - 2 * m[2][8] * m[1][5] - 2 * m[2][7] * m[1][4] + 2 * t12;
509 *P.ptr<double>(3,2) = t24 - 2 * m[2][8] * m[2][5] + t19 - 2 * m[2][7] * m[2][4] + t62 + t59;
510 *P.ptr<double>(3,3) = -2 * m[1][9] * m[1][6] + t64 + t28;
511 *P.ptr<double>(3,4) = 2 * t68 + 2 * t36 - 2 * m[2][9] * m[1][6] - 2 * m[1][9] * m[2][6];
512 *P.ptr<double>(3,5) = t40 + t74 - 2 * m[2][9] * m[2][6];
513
514 *P.ptr<double>(4,0) = t1 - 2 * m[1][10] * m[1][4] + t7 + t78 + t79 - 2 * m[1][11] * m[1][5];
515 *P.ptr<double>(4,1) = 2 * t84 - 2 * m[1][11] * m[2][5] - 2 * m[1][10] * m[2][4] + 2 * t16 - 2 * m[2][11] * m[1][5] + 2 * t87 - 2 * m[2][10] * m[1][4] + 2 * t12;
516 *P.ptr<double>(4,2) = t19 + t24 - 2 * m[2][10] * m[2][4] - 2 * m[2][11] * m[2][5] + t95 + t90;
517 *P.ptr<double>(4,3) = t28 - 2 * m[1][12] * m[1][6] + t99;
518 *P.ptr<double>(4,4) = 2 * t101 + 2 * t36 - 2 * m[2][12] * m[1][6] - 2 * m[1][12] * m[2][6];
519 *P.ptr<double>(4,5) = t105 - 2 * m[2][12] * m[2][6] + t40;
520
521 *P.ptr<double>(5,0) = -2 * m[1][10] * m[1][7] + t47 + t48 + t78 + t79 - 2 * m[1][11] * m[1][8];
522 *P.ptr<double>(5,1) = 2 * t84 + 2 * t87 - 2 * m[2][11] * m[1][8] - 2 * m[1][10] * m[2][7] - 2 * m[2][10] * m[1][7] + 2 * t55 + 2 * t52 - 2 * m[1][11] * m[2][8];
523 *P.ptr<double>(5,2) = -2 * m[2][10] * m[2][7] - 2 * m[2][11] * m[2][8] + t62 + t59 + t90 + t95;
524 *P.ptr<double>(5,3) = t64 - 2 * m[1][12] * m[1][9] + t99;
525 *P.ptr<double>(5,4) = 2 * t68 - 2 * m[2][12] * m[1][9] - 2 * m[1][12] * m[2][9] + 2 * t101;
526 *P.ptr<double>(5,5) = t105 - 2 * m[2][12] * m[2][9] + t74;
527
528 return P;
529 }
530
generate_all_possible_solutions_for_f_unk(const double betas[5],double solutions[18][3])531 void upnp::generate_all_possible_solutions_for_f_unk(const double betas[5], double solutions[18][3])
532 {
533 int matrix_to_resolve[18][9] = {
534 { 2, 0, 0, 1, 1, 0, 2, 0, 2 }, { 2, 0, 0, 1, 1, 0, 1, 1, 2 },
535 { 2, 0, 0, 1, 1, 0, 0, 2, 2 }, { 2, 0, 0, 0, 2, 0, 2, 0, 2 },
536 { 2, 0, 0, 0, 2, 0, 1, 1, 2 }, { 2, 0, 0, 0, 2, 0, 0, 2, 2 },
537 { 2, 0, 0, 2, 0, 2, 1, 1, 2 }, { 2, 0, 0, 2, 0, 2, 0, 2, 2 },
538 { 2, 0, 0, 1, 1, 2, 0, 2, 2 }, { 1, 1, 0, 0, 2, 0, 2, 0, 2 },
539 { 1, 1, 0, 0, 2, 0, 1, 1, 2 }, { 1, 1, 0, 2, 0, 2, 0, 2, 2 },
540 { 1, 1, 0, 2, 0, 2, 1, 1, 2 }, { 1, 1, 0, 2, 0, 2, 0, 2, 2 },
541 { 1, 1, 0, 1, 1, 2, 0, 2, 2 }, { 0, 2, 0, 2, 0, 2, 1, 1, 2 },
542 { 0, 2, 0, 2, 0, 2, 0, 2, 2 }, { 0, 2, 0, 1, 1, 2, 0, 2, 2 }
543 };
544
545 int combination[18][3] = {
546 { 1, 2, 4 }, { 1, 2, 5 }, { 1, 2, 6 }, { 1, 3, 4 },
547 { 1, 3, 5 }, { 1, 3, 6 }, { 1, 4, 5 }, { 1, 4, 6 },
548 { 1, 5, 6 }, { 2, 3, 4 }, { 2, 3, 5 }, { 2, 3, 6 },
549 { 2, 4, 5 }, { 2, 4, 6 }, { 2, 5, 6 }, { 3, 4, 5 },
550 { 3, 4, 6 }, { 3, 5, 6 }
551 };
552
553 for (int i = 0; i < 18; ++i) {
554 double matrix[9], independent_term[3];
555 Mat M = Mat(3, 3, CV_64F, matrix);
556 Mat I = Mat(3, 1, CV_64F, independent_term);
557 Mat S = Mat(1, 3, CV_64F);
558
559 for (int j = 0; j < 9; ++j) matrix[j] = (double)matrix_to_resolve[i][j];
560
561 independent_term[0] = log( abs( betas[ combination[i][0]-1 ] ) );
562 independent_term[1] = log( abs( betas[ combination[i][1]-1 ] ) );
563 independent_term[2] = log( abs( betas[ combination[i][2]-1 ] ) );
564
565 exp( Mat(M.inv() * I), S);
566
567 solutions[i][0] = S.at<double>(0);
568 solutions[i][1] = S.at<double>(1) * sign( betas[1] );
569 solutions[i][2] = abs( S.at<double>(2) );
570 }
571 }
572
gauss_newton(const Mat * L_6x12,const Mat * Rho,double betas[4],double * f)573 void upnp::gauss_newton(const Mat * L_6x12, const Mat * Rho, double betas[4], double * f)
574 {
575 const int iterations_number = 50;
576
577 double a[6*4], b[6], x[4];
578 Mat * A = new Mat(6, 4, CV_64F, a);
579 Mat * B = new Mat(6, 1, CV_64F, b);
580 Mat * X = new Mat(4, 1, CV_64F, x);
581
582 for(int k = 0; k < iterations_number; k++)
583 {
584 compute_A_and_b_gauss_newton(L_6x12->ptr<double>(0), Rho->ptr<double>(0), betas, A, B, f[0]);
585 qr_solve(A, B, X);
586 for(int i = 0; i < 3; i++)
587 betas[i] += x[i];
588 f[0] += x[3];
589 }
590
591 if (f[0] < 0) f[0] = -f[0];
592 fu = fv = f[0];
593
594 }
595
compute_A_and_b_gauss_newton(const double * l_6x12,const double * rho,const double betas[4],Mat * A,Mat * b,double const f)596 void upnp::compute_A_and_b_gauss_newton(const double * l_6x12, const double * rho,
597 const double betas[4], Mat * A, Mat * b, double const f)
598 {
599
600 for(int i = 0; i < 6; i++) {
601 const double * rowL = l_6x12 + i * 12;
602 double * rowA = A->ptr<double>(i);
603
604 rowA[0] = 2 * rowL[0] * betas[0] + rowL[1] * betas[1] + rowL[2] * betas[2] + f*f * ( 2 * rowL[6]*betas[0] + rowL[7]*betas[1] + rowL[8]*betas[2] );
605 rowA[1] = rowL[1] * betas[0] + 2 * rowL[3] * betas[1] + rowL[4] * betas[2] + f*f * ( rowL[7]*betas[0] + 2 * rowL[9]*betas[1] + rowL[10]*betas[2] );
606 rowA[2] = rowL[2] * betas[0] + rowL[4] * betas[1] + 2 * rowL[5] * betas[2] + f*f * ( rowL[8]*betas[0] + rowL[10]*betas[1] + 2 * rowL[11]*betas[2] );
607 rowA[3] = 2*f * ( rowL[6]*betas[0]*betas[0] + rowL[7]*betas[0]*betas[1] + rowL[8]*betas[0]*betas[2] + rowL[9]*betas[1]*betas[1] + rowL[10]*betas[1]*betas[2] + rowL[11]*betas[2]*betas[2] ) ;
608
609 *b->ptr<double>(i) = rho[i] -
610 (
611 rowL[0] * betas[0] * betas[0] +
612 rowL[1] * betas[0] * betas[1] +
613 rowL[2] * betas[0] * betas[2] +
614 rowL[3] * betas[1] * betas[1] +
615 rowL[4] * betas[1] * betas[2] +
616 rowL[5] * betas[2] * betas[2] +
617 f*f * rowL[6] * betas[0] * betas[0] +
618 f*f * rowL[7] * betas[0] * betas[1] +
619 f*f * rowL[8] * betas[0] * betas[2] +
620 f*f * rowL[9] * betas[1] * betas[1] +
621 f*f * rowL[10] * betas[1] * betas[2] +
622 f*f * rowL[11] * betas[2] * betas[2]
623 );
624 }
625 }
626
compute_L_6x12(const double * ut,double * l_6x12)627 void upnp::compute_L_6x12(const double * ut, double * l_6x12)
628 {
629 const double * v[3];
630
631 v[0] = ut + 12 * 9;
632 v[1] = ut + 12 * 10;
633 v[2] = ut + 12 * 11;
634
635 double dv[3][6][3];
636
637 for(int i = 0; i < 3; i++) {
638 int a = 0, b = 1;
639 for(int j = 0; j < 6; j++) {
640 dv[i][j][0] = v[i][3 * a ] - v[i][3 * b];
641 dv[i][j][1] = v[i][3 * a + 1] - v[i][3 * b + 1];
642 dv[i][j][2] = v[i][3 * a + 2] - v[i][3 * b + 2];
643
644 b++;
645 if (b > 3) {
646 a++;
647 b = a + 1;
648 }
649 }
650 }
651
652 for(int i = 0; i < 6; i++) {
653 double * row = l_6x12 + 12 * i;
654
655 row[0] = dotXY(dv[0][i], dv[0][i]);
656 row[1] = 2.0f * dotXY(dv[0][i], dv[1][i]);
657 row[2] = dotXY(dv[1][i], dv[1][i]);
658 row[3] = 2.0f * dotXY(dv[0][i], dv[2][i]);
659 row[4] = 2.0f * dotXY(dv[1][i], dv[2][i]);
660 row[5] = dotXY(dv[2][i], dv[2][i]);
661
662 row[6] = dotZ(dv[0][i], dv[0][i]);
663 row[7] = 2.0f * dotZ(dv[0][i], dv[1][i]);
664 row[8] = 2.0f * dotZ(dv[0][i], dv[2][i]);
665 row[9] = dotZ(dv[1][i], dv[1][i]);
666 row[10] = 2.0f * dotZ(dv[1][i], dv[2][i]);
667 row[11] = dotZ(dv[2][i], dv[2][i]);
668 }
669 }
670
compute_rho(double * rho)671 void upnp::compute_rho(double * rho)
672 {
673 rho[0] = dist2(cws[0], cws[1]);
674 rho[1] = dist2(cws[0], cws[2]);
675 rho[2] = dist2(cws[0], cws[3]);
676 rho[3] = dist2(cws[1], cws[2]);
677 rho[4] = dist2(cws[1], cws[3]);
678 rho[5] = dist2(cws[2], cws[3]);
679 }
680
dist2(const double * p1,const double * p2)681 double upnp::dist2(const double * p1, const double * p2)
682 {
683 return
684 (p1[0] - p2[0]) * (p1[0] - p2[0]) +
685 (p1[1] - p2[1]) * (p1[1] - p2[1]) +
686 (p1[2] - p2[2]) * (p1[2] - p2[2]);
687 }
688
dot(const double * v1,const double * v2)689 double upnp::dot(const double * v1, const double * v2)
690 {
691 return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
692 }
693
dotXY(const double * v1,const double * v2)694 double upnp::dotXY(const double * v1, const double * v2)
695 {
696 return v1[0] * v2[0] + v1[1] * v2[1];
697 }
698
dotZ(const double * v1,const double * v2)699 double upnp::dotZ(const double * v1, const double * v2)
700 {
701 return v1[2] * v2[2];
702 }
703
sign(const double v)704 double upnp::sign(const double v)
705 {
706 return ( v < 0.0 ) ? -1.0 : ( v > 0.0 ) ? 1.0 : 0.0;
707 }
708
qr_solve(Mat * A,Mat * b,Mat * X)709 void upnp::qr_solve(Mat * A, Mat * b, Mat * X)
710 {
711 const int nr = A->rows;
712 const int nc = A->cols;
713
714 if (max_nr != 0 && max_nr < nr)
715 {
716 delete [] A1;
717 delete [] A2;
718 }
719 if (max_nr < nr)
720 {
721 max_nr = nr;
722 A1 = new double[nr];
723 A2 = new double[nr];
724 }
725
726 double * pA = A->ptr<double>(0), * ppAkk = pA;
727 for(int k = 0; k < nc; k++)
728 {
729 double * ppAik1 = ppAkk, eta = fabs(*ppAik1);
730 for(int i = k + 1; i < nr; i++)
731 {
732 double elt = fabs(*ppAik1);
733 if (eta < elt) eta = elt;
734 ppAik1 += nc;
735 }
736 if (eta == 0)
737 {
738 A1[k] = A2[k] = 0.0;
739 //cerr << "God damnit, A is singular, this shouldn't happen." << endl;
740 return;
741 }
742 else
743 {
744 double * ppAik2 = ppAkk, sum2 = 0.0, inv_eta = 1. / eta;
745 for(int i = k; i < nr; i++)
746 {
747 *ppAik2 *= inv_eta;
748 sum2 += *ppAik2 * *ppAik2;
749 ppAik2 += nc;
750 }
751 double sigma = sqrt(sum2);
752 if (*ppAkk < 0)
753 sigma = -sigma;
754 *ppAkk += sigma;
755 A1[k] = sigma * *ppAkk;
756 A2[k] = -eta * sigma;
757 for(int j = k + 1; j < nc; j++)
758 {
759 double * ppAik = ppAkk, sum = 0;
760 for(int i = k; i < nr; i++)
761 {
762 sum += *ppAik * ppAik[j - k];
763 ppAik += nc;
764 }
765 double tau = sum / A1[k];
766 ppAik = ppAkk;
767 for(int i = k; i < nr; i++)
768 {
769 ppAik[j - k] -= tau * *ppAik;
770 ppAik += nc;
771 }
772 }
773 }
774 ppAkk += nc + 1;
775 }
776
777 // b <- Qt b
778 double * ppAjj = pA, * pb = b->ptr<double>(0);
779 for(int j = 0; j < nc; j++)
780 {
781 double * ppAij = ppAjj, tau = 0;
782 for(int i = j; i < nr; i++)
783 {
784 tau += *ppAij * pb[i];
785 ppAij += nc;
786 }
787 tau /= A1[j];
788 ppAij = ppAjj;
789 for(int i = j; i < nr; i++)
790 {
791 pb[i] -= tau * *ppAij;
792 ppAij += nc;
793 }
794 ppAjj += nc + 1;
795 }
796
797 // X = R-1 b
798 double * pX = X->ptr<double>(0);
799 pX[nc - 1] = pb[nc - 1] / A2[nc - 1];
800 for(int i = nc - 2; i >= 0; i--)
801 {
802 double * ppAij = pA + i * nc + (i + 1), sum = 0;
803
804 for(int j = i + 1; j < nc; j++)
805 {
806 sum += *ppAij * pX[j];
807 ppAij++;
808 }
809 pX[i] = (pb[i] - sum) / A2[i];
810 }
811 }
812