Main MRPT website > C++ reference for MRPT 1.5.6
upnp.cpp
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2 | Mobile Robot Programming Toolkit (MRPT) |
3 | http://www.mrpt.org/ |
4 | |
5 | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6 | See: http://www.mrpt.org/Authors - All rights reserved. |
7 | Released under BSD License. See details in http://www.mrpt.org/License |
8 +---------------------------------------------------------------------------+ */
9 
10 #include "vision-precomp.h" // Precompiled headers
11 
12 //M*//////////////////////////////////////////////////////////////////////////////////////
13 //
14 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
15 //
16 // By downloading, copying, installing or using the software you agree to this license.
17 // If you do not agree to this license, do not download, install,
18 // copy or use the software.
19 //
20 //
21 // License Agreement
22 // For Open Source Computer Vision Library
23 //
24 // Copyright (C) 2000, Intel Corporation, all rights reserved.
25 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
26 // Third party copyrights are property of their respective owners.
27 //
28 // Redistribution and use in source and binary forms, with or without modification,
29 // are permitted provided that the following conditions are met:
30 //
31 // * Redistribution's of source code must retain the above copyright notice,
32 // this list of conditions and the following disclaimer.
33 //
34 // * Redistribution's in binary form must reproduce the above copyright notice,
35 // this list of conditions and the following disclaimer in the documentation
36 // and/or other materials provided with the distribution.
37 //
38 // * The name of the copyright holders may not be used to endorse or promote products
39 // derived from this software without specific prior written permission.
40 //
41 // This software is provided by the copyright holders and contributors "as is" and
42 // any express or implied warranties, including, but not limited to, the implied
43 // warranties of merchantability and fitness for a particular purpose are disclaimed.
44 // In no event shall the Intel Corporation or contributors be liable for any direct,
45 // indirect, incidental, special, exemplary, or consequential damages
46 // (including, but not limited to, procurement of substitute goods or services;
47 // loss of use, data, or profits; or business interruption) however caused
48 // and on any theory of liability, whether in contract, strict liability,
49 // or tort (including negligence or otherwise) arising in any way out of
50 // the use of this software, even if advised of the possibility of such damage.
51 //
52 //M*/
53 
54 /****************************************************************************************\
55 * Exhaustive Linearization for Robust Camera Pose and Focal Length Estimation.
56 * Contributed by Edgar Riba
57 \****************************************************************************************/
58 
59 #include <iostream>
60 #include <mrpt/otherlibs/do_opencv_includes.h>
61 
62 // Opencv 2.3 had a broken <opencv/eigen.h> in Ubuntu 14.04 Trusty => Disable PNP classes
63 #include <mrpt/config.h>
64 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM<0x240
65 # undef MRPT_HAS_OPENCV
66 # define MRPT_HAS_OPENCV 0
67 #endif
68 
69 
70 #include <limits>
71 using namespace std;
72 #if MRPT_HAS_OPENCV
73 
74  using namespace cv;
75 
76  #include "upnp.h"
77  using namespace mrpt::vision::pnp;
78 
79  upnp::upnp(const Mat& cameraMatrix, const Mat& opoints, const Mat& ipoints)
80  {
81  if (cameraMatrix.depth() == CV_32F)
82  init_camera_parameters<float>(cameraMatrix);
83  else
84  init_camera_parameters<double>(cameraMatrix);
85 
86  number_of_correspondences = std::max(opoints.checkVector(3, CV_32F), opoints.checkVector(3, CV_64F));
87 
88  pws.resize(3 * number_of_correspondences);
89  us.resize(2 * number_of_correspondences);
90 
91  if (opoints.depth() == ipoints.depth())
92  {
93  if (opoints.depth() == CV_32F)
94  init_points<Point3f,Point2f>(opoints, ipoints);
95  else
96  init_points<Point3d,Point2d>(opoints, ipoints);
97  }
98  else if (opoints.depth() == CV_32F)
99  init_points<Point3f,Point2d>(opoints, ipoints);
100  else
101  init_points<Point3d,Point2f>(opoints, ipoints);
102 
103  alphas.resize(4 * number_of_correspondences);
104  pcs.resize(3 * number_of_correspondences);
105 
106  max_nr = 0;
107  A1 = NULL;
108  A2 = NULL;
109  }
110 
111  upnp::~upnp()
112  {
113  if (A1)
114  delete[] A1;
115  if (A2)
116  delete[] A2;
117  }
118 
119  double upnp::compute_pose(Mat& R, Mat& t)
120  {
121  choose_control_points();
122  compute_alphas();
123 
124  Mat * M = new Mat(2 * number_of_correspondences, 12, CV_64F);
125 
126  for(int i = 0; i < number_of_correspondences; i++)
127  {
128  fill_M(M, 2 * i, &alphas[0] + 4 * i, us[2 * i], us[2 * i + 1]);
129  }
130 
131  double mtm[12 * 12], d[12], ut[12 * 12], vt[12 * 12];
132  Mat MtM = Mat(12, 12, CV_64F, mtm);
133  Mat D = Mat(12, 1, CV_64F, d);
134  Mat Ut = Mat(12, 12, CV_64F, ut);
135  Mat Vt = Mat(12, 12, CV_64F, vt);
136 
137  MtM = M->t() * (*M);
138  SVD::compute(MtM, D, Ut, Vt, SVD::MODIFY_A | SVD::FULL_UV);
139  Mat(Ut.t()).copyTo(Ut);
140  M->release();
141  delete M;
142 
143  double l_6x12[6 * 12], rho[6];
144  Mat L_6x12 = Mat(6, 12, CV_64F, l_6x12);
145  Mat Rho = Mat(6, 1, CV_64F, rho);
146 
147  compute_L_6x12(ut, l_6x12);
148  compute_rho(rho);
149 
150  double Betas[3][4], Efs[3][1], rep_errors[3];
151  double Rs[3][3][3], ts[3][3];
152 
153  find_betas_and_focal_approx_1(&Ut, &Rho, Betas[1], Efs[1]);
154  gauss_newton(&L_6x12, &Rho, Betas[1], Efs[1]);
155  rep_errors[1] = compute_R_and_t(ut, Betas[1], Rs[1], ts[1]);
156 
157  find_betas_and_focal_approx_2(&Ut, &Rho, Betas[2], Efs[2]);
158  gauss_newton(&L_6x12, &Rho, Betas[2], Efs[2]);
159  rep_errors[2] = compute_R_and_t(ut, Betas[2], Rs[2], ts[2]);
160 
161  int N = 1;
162  if (rep_errors[2] < rep_errors[1]) N = 2;
163 
164  Mat(3, 1, CV_64F, ts[N]).copyTo(t);
165  Mat(3, 3, CV_64F, Rs[N]).copyTo(R);
166  fu = fv = Efs[N][0];
167 
168  return fu;
169  }
170 
171  void upnp::copy_R_and_t(const double R_src[3][3], const double t_src[3],
172  double R_dst[3][3], double t_dst[3])
173  {
174  for(int i = 0; i < 3; i++) {
175  for(int j = 0; j < 3; j++)
176  R_dst[i][j] = R_src[i][j];
177  t_dst[i] = t_src[i];
178  }
179  }
180 
181  void upnp::estimate_R_and_t(double R[3][3], double t[3])
182  {
183  double pc0[3], pw0[3];
184 
185  pc0[0] = pc0[1] = pc0[2] = 0.0;
186  pw0[0] = pw0[1] = pw0[2] = 0.0;
187 
188  for(int i = 0; i < number_of_correspondences; i++) {
189  const double * pc = &pcs[3 * i];
190  const double * pw = &pws[3 * i];
191 
192  for(int j = 0; j < 3; j++) {
193  pc0[j] += pc[j];
194  pw0[j] += pw[j];
195  }
196  }
197  for(int j = 0; j < 3; j++) {
198  pc0[j] /= number_of_correspondences;
199  pw0[j] /= number_of_correspondences;
200  }
201 
202  double abt[3 * 3], abt_d[3], abt_u[3 * 3], abt_v[3 * 3];
203  Mat ABt = Mat(3, 3, CV_64F, abt);
204  Mat ABt_D = Mat(3, 1, CV_64F, abt_d);
205  Mat ABt_U = Mat(3, 3, CV_64F, abt_u);
206  Mat ABt_V = Mat(3, 3, CV_64F, abt_v);
207 
208  ABt.setTo(0.0);
209  for(int i = 0; i < number_of_correspondences; i++) {
210  double * pc = &pcs[3 * i];
211  double * pw = &pws[3 * i];
212 
213  for(int j = 0; j < 3; j++) {
214  abt[3 * j ] += (pc[j] - pc0[j]) * (pw[0] - pw0[0]);
215  abt[3 * j + 1] += (pc[j] - pc0[j]) * (pw[1] - pw0[1]);
216  abt[3 * j + 2] += (pc[j] - pc0[j]) * (pw[2] - pw0[2]);
217  }
218  }
219 
220  SVD::compute(ABt, ABt_D, ABt_U, ABt_V, SVD::MODIFY_A);
221  Mat(ABt_V.t()).copyTo(ABt_V);
222 
223  for(int i = 0; i < 3; i++)
224  for(int j = 0; j < 3; j++)
225  R[i][j] = dot(abt_u + 3 * i, abt_v + 3 * j);
226 
227  const double det =
228  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] -
229  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];
230 
231  if (det < 0) {
232  R[2][0] = -R[2][0];
233  R[2][1] = -R[2][1];
234  R[2][2] = -R[2][2];
235  }
236 
237  t[0] = pc0[0] - dot(R[0], pw0);
238  t[1] = pc0[1] - dot(R[1], pw0);
239  t[2] = pc0[2] - dot(R[2], pw0);
240  }
241 
242  void upnp::solve_for_sign(void)
243  {
244  if (pcs[2] < 0.0) {
245  for(int i = 0; i < 4; i++)
246  for(int j = 0; j < 3; j++)
247  ccs[i][j] = -ccs[i][j];
248 
249  for(int i = 0; i < number_of_correspondences; i++) {
250  pcs[3 * i ] = -pcs[3 * i];
251  pcs[3 * i + 1] = -pcs[3 * i + 1];
252  pcs[3 * i + 2] = -pcs[3 * i + 2];
253  }
254  }
255  }
256 
257  double upnp::compute_R_and_t(const double * ut, const double * betas,
258  double R[3][3], double t[3])
259  {
260  compute_ccs(betas, ut);
261  compute_pcs();
262 
263  solve_for_sign();
264 
265  estimate_R_and_t(R, t);
266 
267  return reprojection_error(R, t);
268  }
269 
270  double upnp::reprojection_error(const double R[3][3], const double t[3])
271  {
272  double sum2 = 0.0;
273 
274  for(int i = 0; i < number_of_correspondences; i++) {
275  double * pw = &pws[3 * i];
276  double Xc = dot(R[0], pw) + t[0];
277  double Yc = dot(R[1], pw) + t[1];
278  double inv_Zc = 1.0 / (dot(R[2], pw) + t[2]);
279  double ue = uc + fu * Xc * inv_Zc;
280  double ve = vc + fv * Yc * inv_Zc;
281  double u = us[2 * i], v = us[2 * i + 1];
282 
283  sum2 += sqrt( (u - ue) * (u - ue) + (v - ve) * (v - ve) );
284  }
285 
286  return sum2 / number_of_correspondences;
287  }
288 
289  void upnp::choose_control_points()
290  {
291  for (int i = 0; i < 4; ++i)
292  cws[i][0] = cws[i][1] = cws[i][2] = 0.0;
293  cws[0][0] = cws[1][1] = cws[2][2] = 1.0;
294  }
295 
296  void upnp::compute_alphas()
297  {
298  Mat CC = Mat(4, 3, CV_64F, &cws);
299  Mat PC = Mat(number_of_correspondences, 3, CV_64F, &pws[0]);
300  Mat ALPHAS = Mat(number_of_correspondences, 4, CV_64F, &alphas[0]);
301 
302  Mat CC_ = CC.clone().t();
303  Mat PC_ = PC.clone().t();
304 
305  Mat row14 = Mat::ones(1, 4, CV_64F);
306  Mat row1n = Mat::ones(1, number_of_correspondences, CV_64F);
307 
308  CC_.push_back(row14);
309  PC_.push_back(row1n);
310 
311  ALPHAS = Mat( CC_.inv() * PC_ ).t();
312  }
313 
314  void upnp::fill_M(Mat * M, const int row, const double * as, const double u, const double v)
315  {
316  double * M1 = M->ptr<double>(row);
317  double * M2 = M1 + 12;
318 
319  for(int i = 0; i < 4; i++) {
320  M1[3 * i ] = as[i] * fu;
321  M1[3 * i + 1] = 0.0;
322  M1[3 * i + 2] = as[i] * (uc - u);
323 
324  M2[3 * i ] = 0.0;
325  M2[3 * i + 1] = as[i] * fv;
326  M2[3 * i + 2] = as[i] * (vc - v);
327  }
328  }
329 
330  void upnp::compute_ccs(const double * betas, const double * ut)
331  {
332  for(int i = 0; i < 4; ++i)
333  ccs[i][0] = ccs[i][1] = ccs[i][2] = 0.0;
334 
335  int N = 4;
336  for(int i = 0; i < N; ++i) {
337  const double * v = ut + 12 * (9 + i);
338  for(int j = 0; j < 4; ++j)
339  for(int k = 0; k < 3; ++k)
340  ccs[j][k] += betas[i] * v[3 * j + k];
341  }
342 
343  for (int i = 0; i < 4; ++i) ccs[i][2] *= fu;
344  }
345 
346  void upnp::compute_pcs(void)
347  {
348  for(int i = 0; i < number_of_correspondences; i++) {
349  double * a = &alphas[0] + 4 * i;
350  double * pc = &pcs[0] + 3 * i;
351 
352  for(int j = 0; j < 3; j++)
353  pc[j] = a[0] * ccs[0][j] + a[1] * ccs[1][j] + a[2] * ccs[2][j] + a[3] * ccs[3][j];
354  }
355  }
356 
357  void upnp::find_betas_and_focal_approx_1(Mat * Ut, Mat * Rho, double * betas, double * efs)
358  {
359  Mat Kmf1 = 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_2param_6eq_2unk_f_unk( Kmf1 );
363  Mat Dt = D.t();
364 
365  Mat A = Dt * D;
366  Mat b = Dt * dsq;
367 
368  Mat x = Mat(2, 1, CV_64F);
369  solve(A, b, x);
370 
371  betas[0] = sqrt( abs( x.at<double>(0) ) );
372  betas[1] = betas[2] = betas[3] = 0.0;
373 
374  efs[0] = sqrt( abs( x.at<double>(1) ) ) / betas[0];
375  }
376 
377  void upnp::find_betas_and_focal_approx_2(Mat * Ut, Mat * Rho, double * betas, double * efs)
378  {
379  double u[12*12];
380  Mat U = Mat(12, 12, CV_64F, u);
381  Ut->copyTo(U);
382 
383  Mat Kmf1 = Mat(12, 1, CV_64F, Ut->ptr<double>(10));
384  Mat Kmf2 = Mat(12, 1, CV_64F, Ut->ptr<double>(11));
385  Mat dsq = Mat(6, 1, CV_64F, Rho->ptr<double>(0));
386 
387  Mat D = compute_constraint_distance_3param_6eq_6unk_f_unk( Kmf1, Kmf2 );
388 
389  Mat A = D;
390  Mat b = dsq;
391 
392  double x[6];
393  Mat X = Mat(6, 1, CV_64F, x);
394 
395  solve(A, b, X, DECOMP_QR);
396 
397  double solutions[18][3];
398  generate_all_possible_solutions_for_f_unk(x, solutions);
399 
400  // find solution with minimum reprojection error
401  double min_error = std::numeric_limits<double>::max();
402  int min_sol = 0;
403  for (int i = 0; i < 18; ++i) {
404 
405  betas[3] = solutions[i][0];
406  betas[2] = solutions[i][1];
407  betas[1] = betas[0] = 0.0;
408  fu = fv = solutions[i][2];
409 
410  double Rs[3][3], ts[3];
411  double error_i = compute_R_and_t( u, betas, Rs, ts);
412 
413  if( error_i < min_error)
414  {
415  min_error = error_i;
416  min_sol = i;
417  }
418  }
419 
420  betas[0] = solutions[min_sol][0];
421  betas[1] = solutions[min_sol][1];
422  betas[2] = betas[3] = 0.0;
423 
424  efs[0] = solutions[min_sol][2];
425  }
426 
427  Mat upnp::compute_constraint_distance_2param_6eq_2unk_f_unk(const Mat& M1)
428  {
429  Mat P = Mat(6, 2, CV_64F);
430 
431  double m[13];
432  for (int i = 1; i < 13; ++i) m[i] = *M1.ptr<double>(i-1);
433 
434  double t1 = pow( m[4], 2 );
435  double t4 = pow( m[1], 2 );
436  double t5 = pow( m[5], 2 );
437  double t8 = pow( m[2], 2 );
438  double t10 = pow( m[6], 2 );
439  double t13 = pow( m[3], 2 );
440  double t15 = pow( m[7], 2 );
441  double t18 = pow( m[8], 2 );
442  double t22 = pow( m[9], 2 );
443  double t26 = pow( m[10], 2 );
444  double t29 = pow( m[11], 2 );
445  double t33 = pow( m[12], 2 );
446 
447  *P.ptr<double>(0,0) = t1 - 2 * m[4] * m[1] + t4 + t5 - 2 * m[5] * m[2] + t8;
448  *P.ptr<double>(0,1) = t10 - 2 * m[6] * m[3] + t13;
449  *P.ptr<double>(1,0) = t15 - 2 * m[7] * m[1] + t4 + t18 - 2 * m[8] * m[2] + t8;
450  *P.ptr<double>(1,1) = t22 - 2 * m[9] * m[3] + t13;
451  *P.ptr<double>(2,0) = t26 - 2 * m[10] * m[1] + t4 + t29 - 2 * m[11] * m[2] + t8;
452  *P.ptr<double>(2,1) = t33 - 2 * m[12] * m[3] + t13;
453  *P.ptr<double>(3,0) = t15 - 2 * m[7] * m[4] + t1 + t18 - 2 * m[8] * m[5] + t5;
454  *P.ptr<double>(3,1) = t22 - 2 * m[9] * m[6] + t10;
455  *P.ptr<double>(4,0) = t26 - 2 * m[10] * m[4] + t1 + t29 - 2 * m[11] * m[5] + t5;
456  *P.ptr<double>(4,1) = t33 - 2 * m[12] * m[6] + t10;
457  *P.ptr<double>(5,0) = t26 - 2 * m[10] * m[7] + t15 + t29 - 2 * m[11] * m[8] + t18;
458  *P.ptr<double>(5,1) = t33 - 2 * m[12] * m[9] + t22;
459 
460  return P;
461  }
462 
463  Mat upnp::compute_constraint_distance_3param_6eq_6unk_f_unk(const Mat& M1, const Mat& M2)
464  {
465  Mat P = Mat(6, 6, CV_64F);
466 
467  double m[3][13];
468  for (int i = 1; i < 13; ++i)
469  {
470  m[1][i] = *M1.ptr<double>(i-1);
471  m[2][i] = *M2.ptr<double>(i-1);
472  }
473 
474  double t1 = pow( m[1][4], 2 );
475  double t2 = pow( m[1][1], 2 );
476  double t7 = pow( m[1][5], 2 );
477  double t8 = pow( m[1][2], 2 );
478  double t11 = m[1][1] * m[2][1];
479  double t12 = m[1][5] * m[2][5];
480  double t15 = m[1][2] * m[2][2];
481  double t16 = m[1][4] * m[2][4];
482  double t19 = pow( m[2][4], 2 );
483  double t22 = pow( m[2][2], 2 );
484  double t23 = pow( m[2][1], 2 );
485  double t24 = pow( m[2][5], 2 );
486  double t28 = pow( m[1][6], 2 );
487  double t29 = pow( m[1][3], 2 );
488  double t34 = pow( m[1][3], 2 );
489  double t36 = m[1][6] * m[2][6];
490  double t40 = pow( m[2][6], 2 );
491  double t41 = pow( m[2][3], 2 );
492  double t47 = pow( m[1][7], 2 );
493  double t48 = pow( m[1][8], 2 );
494  double t52 = m[1][7] * m[2][7];
495  double t55 = m[1][8] * m[2][8];
496  double t59 = pow( m[2][8], 2 );
497  double t62 = pow( m[2][7], 2 );
498  double t64 = pow( m[1][9], 2 );
499  double t68 = m[1][9] * m[2][9];
500  double t74 = pow( m[2][9], 2 );
501  double t78 = pow( m[1][10], 2 );
502  double t79 = pow( m[1][11], 2 );
503  double t84 = m[1][10] * m[2][10];
504  double t87 = m[1][11] * m[2][11];
505  double t90 = pow( m[2][10], 2 );
506  double t95 = pow( m[2][11], 2 );
507  double t99 = pow( m[1][12], 2 );
508  double t101 = m[1][12] * m[2][12];
509  double t105 = pow( m[2][12], 2 );
510 
511  *P.ptr<double>(0,0) = t1 + t2 - 2 * m[1][4] * m[1][1] - 2 * m[1][5] * m[1][2] + t7 + t8;
512  *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];
513  *P.ptr<double>(0,2) = t19 - 2 * m[2][4] * m[2][1] + t22 + t23 + t24 - 2 * m[2][5] * m[2][2];
514  *P.ptr<double>(0,3) = t28 + t29 - 2 * m[1][6] * m[1][3];
515  *P.ptr<double>(0,4) = -2 * m[2][6] * m[1][3] + 2 * t34 - 2 * m[1][6] * m[2][3] + 2 * t36;
516  *P.ptr<double>(0,5) = -2 * m[2][6] * m[2][3] + t40 + t41;
517 
518  *P.ptr<double>(1,0) = t8 - 2 * m[1][8] * m[1][2] - 2 * m[1][7] * m[1][1] + t47 + t48 + t2;
519  *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;
520  *P.ptr<double>(1,2) = -2 * m[2][8] * m[2][2] + t22 + t23 + t59 - 2 * m[2][7] * m[2][1] + t62;
521  *P.ptr<double>(1,3) = t29 + t64 - 2 * m[1][9] * m[1][3];
522  *P.ptr<double>(1,4) = 2 * t34 + 2 * t68 - 2 * m[2][9] * m[1][3] - 2 * m[1][9] * m[2][3];
523  *P.ptr<double>(1,5) = -2 * m[2][9] * m[2][3] + t74 + t41;
524 
525  *P.ptr<double>(2,0) = -2 * m[1][11] * m[1][2] + t2 + t8 + t78 + t79 - 2 * m[1][10] * m[1][1];
526  *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;
527  *P.ptr<double>(2,2) = t90 + t22 - 2 * m[2][10] * m[2][1] + t23 - 2 * m[2][11] * m[2][2] + t95;
528  *P.ptr<double>(2,3) = -2 * m[1][12] * m[1][3] + t99 + t29;
529  *P.ptr<double>(2,4) = 2 * t34 + 2 * t101 - 2 * m[2][12] * m[1][3] - 2 * m[1][12] * m[2][3];
530  *P.ptr<double>(2,5) = t41 + t105 - 2 * m[2][12] * m[2][3];
531 
532  *P.ptr<double>(3,0) = t48 + t1 - 2 * m[1][8] * m[1][5] + t7 - 2 * m[1][7] * m[1][4] + t47;
533  *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;
534  *P.ptr<double>(3,2) = t24 - 2 * m[2][8] * m[2][5] + t19 - 2 * m[2][7] * m[2][4] + t62 + t59;
535  *P.ptr<double>(3,3) = -2 * m[1][9] * m[1][6] + t64 + t28;
536  *P.ptr<double>(3,4) = 2 * t68 + 2 * t36 - 2 * m[2][9] * m[1][6] - 2 * m[1][9] * m[2][6];
537  *P.ptr<double>(3,5) = t40 + t74 - 2 * m[2][9] * m[2][6];
538 
539  *P.ptr<double>(4,0) = t1 - 2 * m[1][10] * m[1][4] + t7 + t78 + t79 - 2 * m[1][11] * m[1][5];
540  *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;
541  *P.ptr<double>(4,2) = t19 + t24 - 2 * m[2][10] * m[2][4] - 2 * m[2][11] * m[2][5] + t95 + t90;
542  *P.ptr<double>(4,3) = t28 - 2 * m[1][12] * m[1][6] + t99;
543  *P.ptr<double>(4,4) = 2 * t101 + 2 * t36 - 2 * m[2][12] * m[1][6] - 2 * m[1][12] * m[2][6];
544  *P.ptr<double>(4,5) = t105 - 2 * m[2][12] * m[2][6] + t40;
545 
546  *P.ptr<double>(5,0) = -2 * m[1][10] * m[1][7] + t47 + t48 + t78 + t79 - 2 * m[1][11] * m[1][8];
547  *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];
548  *P.ptr<double>(5,2) = -2 * m[2][10] * m[2][7] - 2 * m[2][11] * m[2][8] + t62 + t59 + t90 + t95;
549  *P.ptr<double>(5,3) = t64 - 2 * m[1][12] * m[1][9] + t99;
550  *P.ptr<double>(5,4) = 2 * t68 - 2 * m[2][12] * m[1][9] - 2 * m[1][12] * m[2][9] + 2 * t101;
551  *P.ptr<double>(5,5) = t105 - 2 * m[2][12] * m[2][9] + t74;
552 
553  return P;
554  }
555 
556  void upnp::generate_all_possible_solutions_for_f_unk(const double betas[5], double solutions[18][3])
557  {
558  int matrix_to_resolve[18][9] = {
559  { 2, 0, 0, 1, 1, 0, 2, 0, 2 }, { 2, 0, 0, 1, 1, 0, 1, 1, 2 },
560  { 2, 0, 0, 1, 1, 0, 0, 2, 2 }, { 2, 0, 0, 0, 2, 0, 2, 0, 2 },
561  { 2, 0, 0, 0, 2, 0, 1, 1, 2 }, { 2, 0, 0, 0, 2, 0, 0, 2, 2 },
562  { 2, 0, 0, 2, 0, 2, 1, 1, 2 }, { 2, 0, 0, 2, 0, 2, 0, 2, 2 },
563  { 2, 0, 0, 1, 1, 2, 0, 2, 2 }, { 1, 1, 0, 0, 2, 0, 2, 0, 2 },
564  { 1, 1, 0, 0, 2, 0, 1, 1, 2 }, { 1, 1, 0, 2, 0, 2, 0, 2, 2 },
565  { 1, 1, 0, 2, 0, 2, 1, 1, 2 }, { 1, 1, 0, 2, 0, 2, 0, 2, 2 },
566  { 1, 1, 0, 1, 1, 2, 0, 2, 2 }, { 0, 2, 0, 2, 0, 2, 1, 1, 2 },
567  { 0, 2, 0, 2, 0, 2, 0, 2, 2 }, { 0, 2, 0, 1, 1, 2, 0, 2, 2 }
568  };
569 
570  int combination[18][3] = {
571  { 1, 2, 4 }, { 1, 2, 5 }, { 1, 2, 6 }, { 1, 3, 4 },
572  { 1, 3, 5 }, { 1, 3, 6 }, { 1, 4, 5 }, { 1, 4, 6 },
573  { 1, 5, 6 }, { 2, 3, 4 }, { 2, 3, 5 }, { 2, 3, 6 },
574  { 2, 4, 5 }, { 2, 4, 6 }, { 2, 5, 6 }, { 3, 4, 5 },
575  { 3, 4, 6 }, { 3, 5, 6 }
576  };
577 
578  for (int i = 0; i < 18; ++i) {
579  double matrix[9], independent_term[3];
580  Mat M = Mat(3, 3, CV_64F, matrix);
581  Mat I = Mat(3, 1, CV_64F, independent_term);
582  Mat S = Mat(1, 3, CV_64F);
583 
584  for (int j = 0; j < 9; ++j) matrix[j] = (double)matrix_to_resolve[i][j];
585 
586  independent_term[0] = log( abs( betas[ combination[i][0]-1 ] ) );
587  independent_term[1] = log( abs( betas[ combination[i][1]-1 ] ) );
588  independent_term[2] = log( abs( betas[ combination[i][2]-1 ] ) );
589 
590  exp( Mat(M.inv() * I), S);
591 
592  solutions[i][0] = S.at<double>(0);
593  solutions[i][1] = S.at<double>(1) * sign( betas[1] );
594  solutions[i][2] = abs( S.at<double>(2) );
595  }
596  }
597 
598  void upnp::gauss_newton(const Mat * L_6x12, const Mat * Rho, double betas[4], double * f)
599  {
600  const int iterations_number = 50;
601 
602  double a[6*4], b[6], x[4];
603  Mat * A = new Mat(6, 4, CV_64F, a);
604  Mat * B = new Mat(6, 1, CV_64F, b);
605  Mat * X = new Mat(4, 1, CV_64F, x);
606 
607  for(int k = 0; k < iterations_number; k++)
608  {
609  compute_A_and_b_gauss_newton(L_6x12->ptr<double>(0), Rho->ptr<double>(0), betas, A, B, f[0]);
610  qr_solve(A, B, X);
611  for(int i = 0; i < 3; i++)
612  betas[i] += x[i];
613  f[0] += x[3];
614  }
615 
616  if (f[0] < 0) f[0] = -f[0];
617  fu = fv = f[0];
618 
619  A->release();
620  delete A;
621 
622  B->release();
623  delete B;
624 
625  X->release();
626  delete X;
627 
628  }
629 
630  void upnp::compute_A_and_b_gauss_newton(const double * l_6x12, const double * rho,
631  const double betas[4], Mat * A, Mat * b, double const f)
632  {
633 
634  for(int i = 0; i < 6; i++) {
635  const double * rowL = l_6x12 + i * 12;
636  double * rowA = A->ptr<double>(i);
637 
638  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] );
639  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] );
640  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] );
641  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] ) ;
642 
643  *b->ptr<double>(i) = rho[i] -
644  (
645  rowL[0] * betas[0] * betas[0] +
646  rowL[1] * betas[0] * betas[1] +
647  rowL[2] * betas[0] * betas[2] +
648  rowL[3] * betas[1] * betas[1] +
649  rowL[4] * betas[1] * betas[2] +
650  rowL[5] * betas[2] * betas[2] +
651  f*f * rowL[6] * betas[0] * betas[0] +
652  f*f * rowL[7] * betas[0] * betas[1] +
653  f*f * rowL[8] * betas[0] * betas[2] +
654  f*f * rowL[9] * betas[1] * betas[1] +
655  f*f * rowL[10] * betas[1] * betas[2] +
656  f*f * rowL[11] * betas[2] * betas[2]
657  );
658  }
659  }
660 
661  void upnp::compute_L_6x12(const double * ut, double * l_6x12)
662  {
663  const double * v[3];
664 
665  v[0] = ut + 12 * 9;
666  v[1] = ut + 12 * 10;
667  v[2] = ut + 12 * 11;
668 
669  double dv[3][6][3];
670 
671  for(int i = 0; i < 3; i++) {
672  int a = 0, b = 1;
673  for(int j = 0; j < 6; j++) {
674  dv[i][j][0] = v[i][3 * a ] - v[i][3 * b];
675  dv[i][j][1] = v[i][3 * a + 1] - v[i][3 * b + 1];
676  dv[i][j][2] = v[i][3 * a + 2] - v[i][3 * b + 2];
677 
678  b++;
679  if (b > 3) {
680  a++;
681  b = a + 1;
682  }
683  }
684  }
685 
686  for(int i = 0; i < 6; i++) {
687  double * row = l_6x12 + 12 * i;
688 
689  row[0] = dotXY(dv[0][i], dv[0][i]);
690  row[1] = 2.0f * dotXY(dv[0][i], dv[1][i]);
691  row[2] = dotXY(dv[1][i], dv[1][i]);
692  row[3] = 2.0f * dotXY(dv[0][i], dv[2][i]);
693  row[4] = 2.0f * dotXY(dv[1][i], dv[2][i]);
694  row[5] = dotXY(dv[2][i], dv[2][i]);
695 
696  row[6] = dotZ(dv[0][i], dv[0][i]);
697  row[7] = 2.0f * dotZ(dv[0][i], dv[1][i]);
698  row[8] = 2.0f * dotZ(dv[0][i], dv[2][i]);
699  row[9] = dotZ(dv[1][i], dv[1][i]);
700  row[10] = 2.0f * dotZ(dv[1][i], dv[2][i]);
701  row[11] = dotZ(dv[2][i], dv[2][i]);
702  }
703  }
704 
705  void upnp::compute_rho(double * rho)
706  {
707  rho[0] = dist2(cws[0], cws[1]);
708  rho[1] = dist2(cws[0], cws[2]);
709  rho[2] = dist2(cws[0], cws[3]);
710  rho[3] = dist2(cws[1], cws[2]);
711  rho[4] = dist2(cws[1], cws[3]);
712  rho[5] = dist2(cws[2], cws[3]);
713  }
714 
715  double upnp::dist2(const double * p1, const double * p2)
716  {
717  return
718  (p1[0] - p2[0]) * (p1[0] - p2[0]) +
719  (p1[1] - p2[1]) * (p1[1] - p2[1]) +
720  (p1[2] - p2[2]) * (p1[2] - p2[2]);
721  }
722 
723  double upnp::dot(const double * v1, const double * v2)
724  {
725  return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
726  }
727 
728  double upnp::dotXY(const double * v1, const double * v2)
729  {
730  return v1[0] * v2[0] + v1[1] * v2[1];
731  }
732 
733  double upnp::dotZ(const double * v1, const double * v2)
734  {
735  return v1[2] * v2[2];
736  }
737 
738  double upnp::sign(const double v)
739  {
740  return ( v < 0.0 ) ? -1.0 : ( v > 0.0 ) ? 1.0 : 0.0;
741  }
742 
743  void upnp::qr_solve(Mat * A, Mat * b, Mat * X)
744  {
745  const int nr = A->rows;
746  const int nc = A->cols;
747 
748  if (max_nr != 0 && max_nr < nr)
749  {
750  delete [] A1;
751  delete [] A2;
752  }
753  if (max_nr < nr)
754  {
755  max_nr = nr;
756  A1 = new double[nr];
757  A2 = new double[nr];
758  }
759 
760  double * pA = A->ptr<double>(0), * ppAkk = pA;
761  for(int k = 0; k < nc; k++)
762  {
763  double * ppAik1 = ppAkk, eta = fabs(*ppAik1);
764  for(int i = k + 1; i < nr; i++)
765  {
766  double elt = fabs(*ppAik1);
767  if (eta < elt) eta = elt;
768  ppAik1 += nc;
769  }
770  if (eta == 0)
771  {
772  A1[k] = A2[k] = 0.0;
773  //cerr << "God damnit, A is singular, this shouldn't happen." << endl;
774  return;
775  }
776  else
777  {
778  double * ppAik2 = ppAkk, sum2 = 0.0, inv_eta = 1. / eta;
779  for(int i = k; i < nr; i++)
780  {
781  *ppAik2 *= inv_eta;
782  sum2 += *ppAik2 * *ppAik2;
783  ppAik2 += nc;
784  }
785  double sigma = sqrt(sum2);
786  if (*ppAkk < 0)
787  sigma = -sigma;
788  *ppAkk += sigma;
789  A1[k] = sigma * *ppAkk;
790  A2[k] = -eta * sigma;
791  for(int j = k + 1; j < nc; j++)
792  {
793  double * ppAik = ppAkk, sum = 0;
794  for(int i = k; i < nr; i++)
795  {
796  sum += *ppAik * ppAik[j - k];
797  ppAik += nc;
798  }
799  double tau = sum / A1[k];
800  ppAik = ppAkk;
801  for(int i = k; i < nr; i++)
802  {
803  ppAik[j - k] -= tau * *ppAik;
804  ppAik += nc;
805  }
806  }
807  }
808  ppAkk += nc + 1;
809  }
810 
811  // b <- Qt b
812  double * ppAjj = pA, * pb = b->ptr<double>(0);
813  for(int j = 0; j < nc; j++)
814  {
815  double * ppAij = ppAjj, tau = 0;
816  for(int i = j; i < nr; i++)
817  {
818  tau += *ppAij * pb[i];
819  ppAij += nc;
820  }
821  tau /= A1[j];
822  ppAij = ppAjj;
823  for(int i = j; i < nr; i++)
824  {
825  pb[i] -= tau * *ppAij;
826  ppAij += nc;
827  }
828  ppAjj += nc + 1;
829  }
830 
831  // X = R-1 b
832  double * pX = X->ptr<double>(0);
833  pX[nc - 1] = pb[nc - 1] / A2[nc - 1];
834  for(int i = nc - 2; i >= 0; i--)
835  {
836  double * ppAij = pA + i * nc + (i + 1), sum = 0;
837 
838  for(int j = i + 1; j < nc; j++)
839  {
840  sum += *ppAij * pX[j];
841  ppAij++;
842  }
843  pX[i] = (pb[i] - sum) / A2[i];
844  }
845  }
846 #endif
EIGEN_STRONG_INLINE Scalar det() const
Unified PnP - Eigen Wrapper for OpenCV function.
GLdouble GLdouble t
Definition: glext.h:3610
GLuint GLenum matrix
Definition: glext.h:6092
Perspective n Point (PnP) Algorithms toolkit for MRPT.
Definition: pnp_algos.h:23
STL namespace.
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
GLubyte GLubyte b
Definition: glext.h:5575
int sign(T x)
Returns the sign of X as "1" or "-1".
Definition: bits.h:104
double A1
UTC constant and 1st order terms.
const GLdouble * v
Definition: glext.h:3603
GLfloat GLfloat v1
Definition: glext.h:3922
const float R
GLenum GLenum GLvoid * row
Definition: glext.h:3533
GLfloat GLfloat GLfloat v2
Definition: glext.h:3923
GLenum GLint x
Definition: glext.h:3516
EIGEN_STRONG_INLINE void ones(const size_t row, const size_t col)
Resize matrix and set all elements to one.
Definition: eigen_plugins.h:71
GLubyte GLubyte GLubyte a
Definition: glext.h:5575



Page generated by Doxygen 1.8.14 for MRPT 1.5.6 Git: 4c65e8431 Tue Apr 24 08:18:17 2018 +0200 at lun oct 28 01:35:26 CET 2019