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



Page generated by Doxygen 1.8.17 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at miƩ 12 jul 2023 10:03:34 CEST