MRPT  1.9.9
dls.h
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 #ifndef DLS_H_
11 #define DLS_H_
12 
13 #include <mrpt/otherlibs/do_opencv_includes.h>
14 
15 #if MRPT_HAS_OPENCV
16 
17 namespace mrpt::vision::pnp
18 {
19 /** \addtogroup pnp Perspective-n-Point pose estimation
20  * \ingroup mrpt_vision_grp
21  * @{
22  */
23 
24 /**
25  * @class dls
26  * @author Chandra Mangipudi
27  * @date 12/08/16
28  * @file dls.h
29  * @brief Direct Least Squares (DLS) - Eigen wrapper for OpenCV Implementation
30  */
31 class dls
32 {
33  public:
34  //! Constructor for DLS class
35  dls(const cv::Mat& opoints, const cv::Mat& ipoints);
36  ~dls();
37 
38  //! OpenCV function for computing pose
39  bool compute_pose(cv::Mat& R, cv::Mat& t);
40 
41  private:
42  /**
43  * @brief Initialization of object points and image points
44  * @param[in] opoints
45  * @param[in] ipoints
46  */
47  template <typename OpointType, typename IpointType>
48  void init_points(const cv::Mat& opoints, const cv::Mat& ipoints)
49  {
50  for (int i = 0; i < N; i++)
51  {
52  p.at<double>(0, i) = opoints.at<OpointType>(i, 0);
53  p.at<double>(1, i) = opoints.at<OpointType>(i, 1);
54  p.at<double>(2, i) = opoints.at<OpointType>(i, 2);
55 
56  // compute mean of object points
57  mn.at<double>(0) += p.at<double>(0, i);
58  mn.at<double>(1) += p.at<double>(1, i);
59  mn.at<double>(2) += p.at<double>(2, i);
60 
61  // make z into unit vectors from normalized pixel coords
62  double sr = std::pow(ipoints.at<IpointType>(i, 0), 2) +
63  std::pow(ipoints.at<IpointType>(i, 1), 2) + (double)1;
64  sr = std::sqrt(sr);
65 
66  z.at<double>(0, i) = ipoints.at<IpointType>(i, 0) / sr;
67  z.at<double>(1, i) = ipoints.at<IpointType>(i, 1) / sr;
68  z.at<double>(2, i) = (double)1 / sr;
69  }
70 
71  mn.at<double>(0) /= (double)N;
72  mn.at<double>(1) /= (double)N;
73  mn.at<double>(2) /= (double)N;
74  }
75 
76  /**
77  * @brief Create a matrix from vector
78  * @param[in] v
79  * @return Matrix containing vector v as columns
80  */
81  cv::Mat LeftMultVec(const cv::Mat& v);
82 
83  /**
84  * @brief Main function to run DLS-PnP
85  * @param[in] pp
86  */
87  void run_kernel(const cv::Mat& pp);
88 
89  /**
90  * @brief Build the Maucaulay matrix co-efficients
91  * @param[in] pp
92  * @param[out] Mtilde
93  * @param[out] D
94  */
95  void build_coeff_matrix(const cv::Mat& pp, cv::Mat& Mtilde, cv::Mat& D);
96 
97  /**
98  * @brief Eigen Value Decomposition
99  * @param Mtilde Matrix to be decomposed
100  * @param eigenval_real Real eigenvalues
101  * @param eigenval_imag Imaginary eigenvalues
102  * @param eigenvec_real Eigen Vectors corresponding to real eigen values
103  * @param eigenvec_imag Eigen Vectors corresponding to imaginary eigen
104  * values
105  */
106  void compute_eigenvec(
107  const cv::Mat& Mtilde, cv::Mat& eigenval_real, cv::Mat& eigenval_imag,
108  cv::Mat& eigenvec_real, cv::Mat& eigenvec_imag);
109 
110  /**
111  * @brief Fill the hessian functions
112  * @param[in] D
113  */
114  void fill_coeff(const cv::Mat* D);
115 
116  /**
117  * @brief Fill the Maucaulay matrix with co-efficients
118  * @param[in] a
119  * @param[in] b
120  * @param[in] c
121  * @param[in] u
122  * @return Maucaulay matrix M
123  */
124  cv::Mat cayley_LS_M(
125  const std::vector<double>& a, const std::vector<double>& b,
126  const std::vector<double>& c, const std::vector<double>& u);
127 
128  /**
129  * @brief Compute the Hessian matrix for the polynomial co-efficient vector
130  * s
131  * @param[in] s
132  * @return
133  */
134  cv::Mat Hessian(const double s[]);
135 
136  /**
137  * @brief Cayley parameters to Rotation Matrix
138  * @param[in] s
139  * @return Rotation Matrix
140  */
141  cv::Mat cayley2rotbar(const cv::Mat& s);
142 
143  /**
144  * @brief Create a skwy-symmetric matrix from a vector
145  * @param[in] X1
146  * @return Skew-symmetric matrix
147  */
148  cv::Mat skewsymm(const cv::Mat* X1);
149 
150  /**
151  * @brief Rotation matrix along x-axis by angle t
152  * @param[in] t
153  * @return Rotation Matrix
154  */
155  cv::Mat rotx(const double t);
156 
157  /**
158  * @brief Rotation matrix along y-axis by angle t
159  * @param[in] t
160  * @return Rotation Matrix
161  */
162  cv::Mat roty(const double t);
163 
164  /**
165  * @brief Rotation matrix along z-axis by angle t
166  * @param[in] t
167  * @return Rotation Matrix
168  */
169  cv::Mat rotz(const double t);
170 
171  /**
172  * @brief Column-wise mean of matrix M
173  * @param[in] M
174  * @return Mean vector
175  */
176  cv::Mat mean(const cv::Mat& M);
177 
178  /**
179  * @brief Check for negative values in vector v
180  * @param[in] v
181  * @return False if v[i] < 0 else True
182  */
183  bool is_empty(const cv::Mat* v);
184 
185  /**
186  * @brief check for positive eigenvalues
187  * @param[in] eigenvalues
188  * @return True if positivie eigenvalues are found else False
189  */
190  bool positive_eigenvalues(const cv::Mat* eigenvalues);
191 
192  cv::Mat p, z, mn; //! object-image points
193  int N; //! number of input points
194  std::vector<double> f1coeff, f2coeff, f3coeff,
195  cost_; //! coefficient for coefficients matrix
196  std::vector<cv::Mat> C_est_, t_est_; //! optimal candidates
197  cv::Mat C_est__, t_est__; //! optimal found solution
198  double cost__; //! cost for optimal found solution
199 };
200 
201 /**
202  * \cond INTERNAL_FUNC_DLS
203  */
204 class EigenvalueDecomposition
205 {
206  private:
207  int n; //! Holds the data dimension.
208 
209  double cdivr, cdivi; //! Stores real/imag part of a complex division.
210 
211  double *d, *e, *ort; //! Pointer to internal memory.
212  double **V, **H; //! Pointer to internal memory.
213 
214  cv::Mat _eigenvalues; //! Holds the computed eigenvalues.
215 
216  cv::Mat _eigenvectors; //! Holds the computed eigenvectors.
217 
218  /**
219  * @brief Function to allocate memmory for 1d array
220  * @param[in] m Size of new 1d array
221  * @return New 1d array of appropriate type
222  */
223  template <typename _Tp>
224  _Tp* alloc_1d(int m)
225  {
226  return new _Tp[m];
227  }
228 
229  /**
230  * @brief Function to allocate memmory and initialize 1d array
231  * @param[in] m Size of new 1d array
232  * @param[in] val Initial values for the array
233  * @return New 1d array
234  */
235  template <typename _Tp>
236  _Tp* alloc_1d(int m, _Tp val)
237  {
238  _Tp* arr = alloc_1d<_Tp>(m);
239  for (int i = 0; i < m; i++) arr[i] = val;
240  return arr;
241  }
242 
243  /**
244  * @brief Function to allocate memmory for 2d array
245  * @param m Row size
246  * @param _n Column size
247  * @return New 2d array
248  */
249  template <typename _Tp>
250  _Tp** alloc_2d(int m, int _n)
251  {
252  _Tp** arr = new _Tp*[m];
253  for (int i = 0; i < m; i++) arr[i] = new _Tp[_n];
254  return arr;
255  }
256 
257  /**
258  * @brief Function to allocate memmory for 2d array and initialize the array
259  * @param[in] m Row size
260  * @param[in] _n Column size
261  * @param[out] val Initialization for 2d array
262  * @return
263  */
264  template <typename _Tp>
265  _Tp** alloc_2d(int m, int _n, _Tp val)
266  {
267  _Tp** arr = alloc_2d<_Tp>(m, _n);
268  for (int i = 0; i < m; i++)
269  {
270  for (int j = 0; j < _n; j++)
271  {
272  arr[i][j] = val;
273  }
274  }
275  return arr;
276  }
277 
278  /**
279  * @brief Internal function
280  * @param[in] xr
281  * @param[in] xi
282  * @param[in] yr
283  * @param[in] yi
284  */
285  void cdiv(double xr, double xi, double yr, double yi)
286  {
287  double r, dv;
288  if (std::abs(yr) > std::abs(yi))
289  {
290  r = yi / yr;
291  dv = yr + r * yi;
292  cdivr = (xr + r * xi) / dv;
293  cdivi = (xi - r * xr) / dv;
294  }
295  else
296  {
297  r = yr / yi;
298  dv = yi + r * yr;
299  cdivr = (r * xr + xi) / dv;
300  cdivi = (r * xi - xr) / dv;
301  }
302  }
303 
304  /**
305  * @brief Nonsymmetric reduction from Hessenberg to real Schur form.
306  *
307  * This is derived from the Algol procedure hqr2,
308  * by Martin and Wilkinson, Handbook for Auto. Comp.,
309  * Vol.ii-Linear Algebra, and the corresponding
310  * Fortran subroutine in EISPACK.
311  */
312  void hqr2()
313  {
314  // Initialize
315  int nn = this->n;
316  int n1 = nn - 1;
317  int low = 0;
318  int high = nn - 1;
319  double eps = std::pow(2.0, -52.0);
320  double exshift = 0.0;
321  double p = 0, q = 0, r = 0, s = 0, z = 0, t, w, x, y;
322 
323  // Store roots isolated by balanc and compute matrix norm
324 
325  double norm = 0.0;
326  for (int i = 0; i < nn; i++)
327  {
328  if (i < low || i > high)
329  {
330  d[i] = H[i][i];
331  e[i] = 0.0;
332  }
333  for (int j = std::max(i - 1, 0); j < nn; j++)
334  {
335  norm = norm + std::abs(H[i][j]);
336  }
337  }
338 
339  // Outer loop over eigenvalue index
340  int iter = 0;
341  while (n1 >= low)
342  {
343  // Look for single small sub-diagonal element
344  int l = n1;
345  while (l > low)
346  {
347  s = std::abs(H[l - 1][l - 1]) + std::abs(H[l][l]);
348  if (s == 0.0)
349  {
350  s = norm;
351  }
352  if (std::abs(H[l][l - 1]) < eps * s)
353  {
354  break;
355  }
356  l--;
357  }
358 
359  // Check for convergence
360  // One root found
361 
362  if (l == n1)
363  {
364  H[n1][n1] = H[n1][n1] + exshift;
365  d[n1] = H[n1][n1];
366  e[n1] = 0.0;
367  n1--;
368  iter = 0;
369 
370  // Two roots found
371  }
372  else if (l == n1 - 1)
373  {
374  w = H[n1][n1 - 1] * H[n1 - 1][n1];
375  p = (H[n1 - 1][n1 - 1] - H[n1][n1]) / 2.0;
376  q = p * p + w;
377  z = std::sqrt(std::abs(q));
378  H[n1][n1] = H[n1][n1] + exshift;
379  H[n1 - 1][n1 - 1] = H[n1 - 1][n1 - 1] + exshift;
380  x = H[n1][n1];
381 
382  // Real pair
383 
384  if (q >= 0)
385  {
386  if (p >= 0)
387  {
388  z = p + z;
389  }
390  else
391  {
392  z = p - z;
393  }
394  d[n1 - 1] = x + z;
395  d[n1] = d[n1 - 1];
396  if (z != 0.0)
397  {
398  d[n1] = x - w / z;
399  }
400  e[n1 - 1] = 0.0;
401  e[n1] = 0.0;
402  x = H[n1][n1 - 1];
403  s = std::abs(x) + std::abs(z);
404  p = x / s;
405  q = z / s;
406  r = std::sqrt(p * p + q * q);
407  p = p / r;
408  q = q / r;
409 
410  // Row modification
411 
412  for (int j = n1 - 1; j < nn; j++)
413  {
414  z = H[n1 - 1][j];
415  H[n1 - 1][j] = q * z + p * H[n1][j];
416  H[n1][j] = q * H[n1][j] - p * z;
417  }
418 
419  // Column modification
420 
421  for (int i = 0; i <= n1; i++)
422  {
423  z = H[i][n1 - 1];
424  H[i][n1 - 1] = q * z + p * H[i][n1];
425  H[i][n1] = q * H[i][n1] - p * z;
426  }
427 
428  // Accumulate transformations
429 
430  for (int i = low; i <= high; i++)
431  {
432  z = V[i][n1 - 1];
433  V[i][n1 - 1] = q * z + p * V[i][n1];
434  V[i][n1] = q * V[i][n1] - p * z;
435  }
436 
437  // Complex pair
438  }
439  else
440  {
441  d[n1 - 1] = x + p;
442  d[n1] = x + p;
443  e[n1 - 1] = z;
444  e[n1] = -z;
445  }
446  n1 = n1 - 2;
447  iter = 0;
448 
449  // No convergence yet
450  }
451  else
452  {
453  // Form shift
454 
455  x = H[n1][n1];
456  y = 0.0;
457  w = 0.0;
458  if (l < n1)
459  {
460  y = H[n1 - 1][n1 - 1];
461  w = H[n1][n1 - 1] * H[n1 - 1][n1];
462  }
463 
464  // Wilkinson's original ad hoc shift
465 
466  if (iter == 10)
467  {
468  exshift += x;
469  for (int i = low; i <= n1; i++)
470  {
471  H[i][i] -= x;
472  }
473  s = std::abs(H[n1][n1 - 1]) + std::abs(H[n1 - 1][n1 - 2]);
474  x = y = 0.75 * s;
475  w = -0.4375 * s * s;
476  }
477 
478  // MATLAB's new ad hoc shift
479 
480  if (iter == 30)
481  {
482  s = (y - x) / 2.0;
483  s = s * s + w;
484  if (s > 0)
485  {
486  s = std::sqrt(s);
487  if (y < x)
488  {
489  s = -s;
490  }
491  s = x - w / ((y - x) / 2.0 + s);
492  for (int i = low; i <= n1; i++)
493  {
494  H[i][i] -= s;
495  }
496  exshift += s;
497  x = y = w = 0.964;
498  }
499  }
500 
501  iter = iter + 1; // (Could check iteration count here.)
502 
503  // Look for two consecutive small sub-diagonal elements
504  int m = n1 - 2;
505  while (m >= l)
506  {
507  z = H[m][m];
508  r = x - z;
509  s = y - z;
510  p = (r * s - w) / H[m + 1][m] + H[m][m + 1];
511  q = H[m + 1][m + 1] - z - r - s;
512  r = H[m + 2][m + 1];
513  s = std::abs(p) + std::abs(q) + std::abs(r);
514  p = p / s;
515  q = q / s;
516  r = r / s;
517  if (m == l)
518  {
519  break;
520  }
521  if (std::abs(H[m][m - 1]) * (std::abs(q) + std::abs(r)) <
522  eps * (std::abs(p) *
523  (std::abs(H[m - 1][m - 1]) + std::abs(z) +
524  std::abs(H[m + 1][m + 1]))))
525  {
526  break;
527  }
528  m--;
529  }
530 
531  for (int i = m + 2; i <= n1; i++)
532  {
533  H[i][i - 2] = 0.0;
534  if (i > m + 2)
535  {
536  H[i][i - 3] = 0.0;
537  }
538  }
539 
540  // Double QR step involving rows l:n and columns m:n
541 
542  for (int k = m; k <= n1 - 1; k++)
543  {
544  bool notlast = (k != n1 - 1);
545  if (k != m)
546  {
547  p = H[k][k - 1];
548  q = H[k + 1][k - 1];
549  r = (notlast ? H[k + 2][k - 1] : 0.0);
550  x = std::abs(p) + std::abs(q) + std::abs(r);
551  if (x != 0.0)
552  {
553  p = p / x;
554  q = q / x;
555  r = r / x;
556  }
557  }
558  if (x == 0.0)
559  {
560  break;
561  }
562  s = std::sqrt(p * p + q * q + r * r);
563  if (p < 0)
564  {
565  s = -s;
566  }
567  if (s != 0)
568  {
569  if (k != m)
570  {
571  H[k][k - 1] = -s * x;
572  }
573  else if (l != m)
574  {
575  H[k][k - 1] = -H[k][k - 1];
576  }
577  p = p + s;
578  x = p / s;
579  y = q / s;
580  z = r / s;
581  q = q / p;
582  r = r / p;
583 
584  // Row modification
585 
586  for (int j = k; j < nn; j++)
587  {
588  p = H[k][j] + q * H[k + 1][j];
589  if (notlast)
590  {
591  p = p + r * H[k + 2][j];
592  H[k + 2][j] = H[k + 2][j] - p * z;
593  }
594  H[k][j] = H[k][j] - p * x;
595  H[k + 1][j] = H[k + 1][j] - p * y;
596  }
597 
598  // Column modification
599 
600  for (int i = 0; i <= std::min(n1, k + 3); i++)
601  {
602  p = x * H[i][k] + y * H[i][k + 1];
603  if (notlast)
604  {
605  p = p + z * H[i][k + 2];
606  H[i][k + 2] = H[i][k + 2] - p * r;
607  }
608  H[i][k] = H[i][k] - p;
609  H[i][k + 1] = H[i][k + 1] - p * q;
610  }
611 
612  // Accumulate transformations
613 
614  for (int i = low; i <= high; i++)
615  {
616  p = x * V[i][k] + y * V[i][k + 1];
617  if (notlast)
618  {
619  p = p + z * V[i][k + 2];
620  V[i][k + 2] = V[i][k + 2] - p * r;
621  }
622  V[i][k] = V[i][k] - p;
623  V[i][k + 1] = V[i][k + 1] - p * q;
624  }
625  } // (s != 0)
626  } // k loop
627  } // check convergence
628  } // while (n1 >= low)
629 
630  // Backsubstitute to find vectors of upper triangular form
631 
632  if (norm == 0.0)
633  {
634  return;
635  }
636 
637  for (n1 = nn - 1; n1 >= 0; n1--)
638  {
639  p = d[n1];
640  q = e[n1];
641 
642  // Real vector
643 
644  if (q == 0)
645  {
646  int l = n1;
647  H[n1][n1] = 1.0;
648  for (int i = n1 - 1; i >= 0; i--)
649  {
650  w = H[i][i] - p;
651  r = 0.0;
652  for (int j = l; j <= n1; j++)
653  {
654  r = r + H[i][j] * H[j][n1];
655  }
656  if (e[i] < 0.0)
657  {
658  z = w;
659  s = r;
660  }
661  else
662  {
663  l = i;
664  if (e[i] == 0.0)
665  {
666  if (w != 0.0)
667  {
668  H[i][n1] = -r / w;
669  }
670  else
671  {
672  H[i][n1] = -r / (eps * norm);
673  }
674 
675  // Solve real equations
676  }
677  else
678  {
679  x = H[i][i + 1];
680  y = H[i + 1][i];
681  q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
682  t = (x * s - z * r) / q;
683  H[i][n1] = t;
684  if (std::abs(x) > std::abs(z))
685  {
686  H[i + 1][n1] = (-r - w * t) / x;
687  }
688  else
689  {
690  H[i + 1][n1] = (-s - y * t) / z;
691  }
692  }
693 
694  // Overflow control
695 
696  t = std::abs(H[i][n1]);
697  if ((eps * t) * t > 1)
698  {
699  for (int j = i; j <= n1; j++)
700  {
701  H[j][n1] = H[j][n1] / t;
702  }
703  }
704  }
705  }
706  // Complex vector
707  }
708  else if (q < 0)
709  {
710  int l = n1 - 1;
711 
712  // Last vector component imaginary so matrix is triangular
713 
714  if (std::abs(H[n1][n1 - 1]) > std::abs(H[n1 - 1][n1]))
715  {
716  H[n1 - 1][n1 - 1] = q / H[n1][n1 - 1];
717  H[n1 - 1][n1] = -(H[n1][n1] - p) / H[n1][n1 - 1];
718  }
719  else
720  {
721  cdiv(0.0, -H[n1 - 1][n1], H[n1 - 1][n1 - 1] - p, q);
722  H[n1 - 1][n1 - 1] = cdivr;
723  H[n1 - 1][n1] = cdivi;
724  }
725  H[n1][n1 - 1] = 0.0;
726  H[n1][n1] = 1.0;
727  for (int i = n1 - 2; i >= 0; i--)
728  {
729  double ra, sa;
730  ra = 0.0;
731  sa = 0.0;
732  for (int j = l; j <= n1; j++)
733  {
734  ra = ra + H[i][j] * H[j][n1 - 1];
735  sa = sa + H[i][j] * H[j][n1];
736  }
737  w = H[i][i] - p;
738 
739  if (e[i] < 0.0)
740  {
741  z = w;
742  r = ra;
743  s = sa;
744  }
745  else
746  {
747  l = i;
748  if (e[i] == 0)
749  {
750  cdiv(-ra, -sa, w, q);
751  H[i][n1 - 1] = cdivr;
752  H[i][n1] = cdivi;
753  }
754  else
755  {
756  // Solve complex equations
757 
758  x = H[i][i + 1];
759  y = H[i + 1][i];
760  double vr =
761  (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
762  double vi = (d[i] - p) * 2.0 * q;
763  if (vr == 0.0 && vi == 0.0)
764  {
765  vr = eps * norm *
766  (std::abs(w) + std::abs(q) + std::abs(x) +
767  std::abs(y) + std::abs(z));
768  }
769  cdiv(
770  x * r - z * ra + q * sa,
771  x * s - z * sa - q * ra, vr, vi);
772  H[i][n1 - 1] = cdivr;
773  H[i][n1] = cdivi;
774  if (std::abs(x) > (std::abs(z) + std::abs(q)))
775  {
776  H[i + 1][n1 - 1] =
777  (-ra - w * H[i][n1 - 1] + q * H[i][n1]) / x;
778  H[i + 1][n1] =
779  (-sa - w * H[i][n1] - q * H[i][n1 - 1]) / x;
780  }
781  else
782  {
783  cdiv(
784  -r - y * H[i][n1 - 1], -s - y * H[i][n1], z,
785  q);
786  H[i + 1][n1 - 1] = cdivr;
787  H[i + 1][n1] = cdivi;
788  }
789  }
790 
791  // Overflow control
792 
793  t = std::max(
794  std::abs(H[i][n1 - 1]), std::abs(H[i][n1]));
795  if ((eps * t) * t > 1)
796  {
797  for (int j = i; j <= n1; j++)
798  {
799  H[j][n1 - 1] = H[j][n1 - 1] / t;
800  H[j][n1] = H[j][n1] / t;
801  }
802  }
803  }
804  }
805  }
806  }
807 
808  // Vectors of isolated roots
809 
810  for (int i = 0; i < nn; i++)
811  {
812  if (i < low || i > high)
813  {
814  for (int j = i; j < nn; j++)
815  {
816  V[i][j] = H[i][j];
817  }
818  }
819  }
820 
821  // Back transformation to get eigenvectors of original matrix
822 
823  for (int j = nn - 1; j >= low; j--)
824  {
825  for (int i = low; i <= high; i++)
826  {
827  z = 0.0;
828  for (int k = low; k <= std::min(j, high); k++)
829  {
830  z = z + V[i][k] * H[k][j];
831  }
832  V[i][j] = z;
833  }
834  }
835  }
836 
837  /**
838  * @brief Nonsymmetric reduction to Hessenberg form.
839  *
840  * This is derived from the Algol procedures orthes and ortran,
841  * by Martin and Wilkinson, Handbook for Auto. Comp.,
842  * Vol.ii-Linear Algebra, and the corresponding
843  * Fortran subroutines in EISPACK.
844  */
845  void orthes()
846  {
847  int low = 0;
848  int high = n - 1;
849 
850  for (int m = low + 1; m <= high - 1; m++)
851  {
852  // Scale column.
853 
854  double scale = 0.0;
855  for (int i = m; i <= high; i++)
856  {
857  scale = scale + std::abs(H[i][m - 1]);
858  }
859  if (scale != 0.0)
860  {
861  // Compute Householder transformation.
862 
863  double h = 0.0;
864  for (int i = high; i >= m; i--)
865  {
866  ort[i] = H[i][m - 1] / scale;
867  h += ort[i] * ort[i];
868  }
869  double g = std::sqrt(h);
870  if (ort[m] > 0)
871  {
872  g = -g;
873  }
874  h = h - ort[m] * g;
875  ort[m] = ort[m] - g;
876 
877  // Apply Householder similarity transformation
878  // H = (I-u*u'/h)*H*(I-u*u')/h)
879 
880  for (int j = m; j < n; j++)
881  {
882  double f = 0.0;
883  for (int i = high; i >= m; i--)
884  {
885  f += ort[i] * H[i][j];
886  }
887  f = f / h;
888  for (int i = m; i <= high; i++)
889  {
890  H[i][j] -= f * ort[i];
891  }
892  }
893 
894  for (int i = 0; i <= high; i++)
895  {
896  double f = 0.0;
897  for (int j = high; j >= m; j--)
898  {
899  f += ort[j] * H[i][j];
900  }
901  f = f / h;
902  for (int j = m; j <= high; j++)
903  {
904  H[i][j] -= f * ort[j];
905  }
906  }
907  ort[m] = scale * ort[m];
908  H[m][m - 1] = scale * g;
909  }
910  }
911 
912  // Accumulate transformations (Algol's ortran).
913 
914  for (int i = 0; i < n; i++)
915  {
916  for (int j = 0; j < n; j++)
917  {
918  V[i][j] = (i == j ? 1.0 : 0.0);
919  }
920  }
921 
922  for (int m = high - 1; m >= low + 1; m--)
923  {
924  if (H[m][m - 1] != 0.0)
925  {
926  for (int i = m + 1; i <= high; i++)
927  {
928  ort[i] = H[i][m - 1];
929  }
930  for (int j = m; j <= high; j++)
931  {
932  double g = 0.0;
933  for (int i = m; i <= high; i++)
934  {
935  g += ort[i] * V[i][j];
936  }
937  // Double division avoids possible underflow
938  g = (g / ort[m]) / H[m][m - 1];
939  for (int i = m; i <= high; i++)
940  {
941  V[i][j] += g * ort[i];
942  }
943  }
944  }
945  }
946  }
947 
948  /**
949  * @brief Releases all internal working memory.
950  */
951  void release()
952  {
953  // releases the working data
954  delete[] d;
955  delete[] e;
956  delete[] ort;
957  for (int i = 0; i < n; i++)
958  {
959  delete[] H[i];
960  delete[] V[i];
961  }
962  delete[] H;
963  delete[] V;
964  }
965 
966  /**
967  * @brief Computes the Eigenvalue Decomposition for a matrix given in H.
968  */
969  void compute()
970  {
971  // Allocate memory for the working data.
972  V = alloc_2d<double>(n, n, 0.0);
973  d = alloc_1d<double>(n);
974  e = alloc_1d<double>(n);
975  ort = alloc_1d<double>(n);
976  // Reduce to Hessenberg form.
977  orthes();
978  // Reduce Hessenberg to real Schur form.
979  hqr2();
980  // Copy eigenvalues to OpenCV Matrix.
981  _eigenvalues.create(1, n, CV_64FC1);
982  for (int i = 0; i < n; i++)
983  {
984  _eigenvalues.at<double>(0, i) = d[i];
985  }
986  // Copy eigenvectors to OpenCV Matrix.
987  _eigenvectors.create(n, n, CV_64FC1);
988  for (int i = 0; i < n; i++)
989  for (int j = 0; j < n; j++)
990  _eigenvectors.at<double>(i, j) = V[i][j];
991  // Deallocate the memory by releasing all internal working data.
992  release();
993  }
994 
995  public:
996  //! Constructor for EigenvalueDecomposition class
997  EigenvalueDecomposition() : n(0) {}
998  /**
999  * Initializes & computes the Eigenvalue Decomposition for a general matrix
1000  * given in src. This function is a port of the EigenvalueSolver in JAMA,
1001  * which has been released to public domain by The MathWorks and the
1002  * National Institute of Standards and Technology (NIST).
1003  */
1004  EigenvalueDecomposition(cv::InputArray src) { compute(src); }
1005  /** This function computes the Eigenvalue Decomposition for a general matrix
1006  * given in src. This function is a port of the EigenvalueSolver in JAMA,
1007  * which has been released to public domain by The MathWorks and the
1008  * National Institute of Standards and Technology (NIST).
1009  */
1010  void compute(cv::InputArray src)
1011  {
1012  /*if(isSymmetric(src)) {
1013  // Fall back to OpenCV for a symmetric matrix!
1014  cv::eigen(src, _eigenvalues, _eigenvectors);
1015  } else {*/
1016  cv::Mat tmp;
1017  // Convert the given input matrix to double. Is there any way to
1018  // prevent allocating the temporary memory? Only used for copying
1019  // into working memory and deallocated after.
1020  src.getMat().convertTo(tmp, CV_64FC1);
1021  // Get dimension of the matrix.
1022  this->n = tmp.cols;
1023  // Allocate the matrix data to work on.
1024  this->H = alloc_2d<double>(n, n);
1025  // Now safely copy the data.
1026  for (int i = 0; i < tmp.rows; i++)
1027  {
1028  for (int j = 0; j < tmp.cols; j++)
1029  {
1030  this->H[i][j] = tmp.at<double>(i, j);
1031  }
1032  }
1033  // Deallocates the temporary matrix before computing.
1034  tmp.release();
1035  // Performs the eigenvalue decomposition of H.
1036  compute();
1037  // }
1038  }
1039 
1040  //! Destructor for EigenvalueDecomposition class
1041  ~EigenvalueDecomposition() {}
1042  /**
1043  * @brief Returns the eigenvalues of the Eigenvalue Decomposition.
1044  * @return eigenvalues
1045  */
1046  cv::Mat eigenvalues() { return _eigenvalues; }
1047  /**
1048  * @brief Returns the eigenvectors of the Eigenvalue Decomposition.
1049  * @return eigenvectors
1050  */
1051  cv::Mat eigenvectors() { return _eigenvectors; }
1052 };
1053 
1054 /**
1055  * \endcond
1056  */
1057 
1058 /** @} */ // end of grouping
1059 }
1060 #endif // OPENCV_Check
1061 #endif // DLS_H
1062 
1063 
bool is_empty(const cv::Mat *v)
Check for negative values in vector v.
GLdouble GLdouble t
Definition: glext.h:3689
GLdouble GLdouble z
Definition: glext.h:3872
#define min(a, b)
bool compute_pose(cv::Mat &R, cv::Mat &t)
OpenCV function for computing pose.
void build_coeff_matrix(const cv::Mat &pp, cv::Mat &Mtilde, cv::Mat &D)
Build the Maucaulay matrix co-efficients.
cv::Mat t_est__
Definition: dls.h:197
Perspective n Point (PnP) Algorithms toolkit for MRPT mrpt_vision_grp.
Definition: pnp_algos.h:23
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:6502
void fill_coeff(const cv::Mat *D)
Fill the hessian functions.
std::vector< double > f1coeff
number of input points
Definition: dls.h:194
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3721
GLenum GLsizei n
Definition: glext.h:5074
cv::Mat roty(const double t)
Rotation matrix along y-axis by angle t.
std::vector< double > f2coeff
Definition: dls.h:194
int N
object-image points
Definition: dls.h:193
GLdouble s
Definition: glext.h:3676
GLuint src
Definition: glext.h:7278
void compute_eigenvec(const cv::Mat &Mtilde, cv::Mat &eigenval_real, cv::Mat &eigenval_imag, cv::Mat &eigenvec_real, cv::Mat &eigenvec_imag)
Eigen Value Decomposition.
std::vector< cv::Mat > t_est_
Definition: dls.h:196
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
cv::Mat rotz(const double t)
Rotation matrix along z-axis by angle t.
std::vector< cv::Mat > C_est_
coefficient for coefficients matrix
Definition: dls.h:196
const GLubyte * c
Definition: glext.h:6313
GLubyte g
Definition: glext.h:6279
int val
Definition: mrpt_jpeglib.h:955
GLubyte GLubyte b
Definition: glext.h:6279
std::vector< double > cost_
Definition: dls.h:194
std::vector< double > f3coeff
Definition: dls.h:194
const double eps
cv::Mat cayley_LS_M(const std::vector< double > &a, const std::vector< double > &b, const std::vector< double > &c, const std::vector< double > &u)
Fill the Maucaulay matrix with co-efficients.
cv::Mat Hessian(const double s[])
Compute the Hessian matrix for the polynomial co-efficient vector s.
double cost__
optimal found solution
Definition: dls.h:198
cv::Mat rotx(const double t)
Rotation matrix along x-axis by angle t.
cv::Mat LeftMultVec(const cv::Mat &v)
Create a matrix from vector.
const GLdouble * v
Definition: glext.h:3678
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
const float R
cv::Mat mean(const cv::Mat &M)
Column-wise mean of matrix M.
cv::Mat cayley2rotbar(const cv::Mat &s)
Cayley parameters to Rotation Matrix.
void run_kernel(const cv::Mat &pp)
Main function to run DLS-PnP.
GLenum GLint GLint y
Definition: glext.h:3538
GLenum GLint x
Definition: glext.h:3538
void init_points(const cv::Mat &opoints, const cv::Mat &ipoints)
Initialization of object points and image points.
Definition: dls.h:48
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
GLfloat GLfloat p
Definition: glext.h:6305
dls(const cv::Mat &opoints, const cv::Mat &ipoints)
Constructor for DLS class.
bool positive_eigenvalues(const cv::Mat *eigenvalues)
check for positive eigenvalues
CONTAINER::Scalar norm(const CONTAINER &v)
cv::Mat skewsymm(const cv::Mat *X1)
Create a skwy-symmetric matrix from a vector.
cv::Mat C_est__
optimal candidates
Definition: dls.h:197



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020