vpgl_ortho_procrustes.cxx
Go to the documentation of this file.
2 //:
3 // \file
4 #include <vnl/vnl_matrix.h>
5 #include <vnl/vnl_trace.h>
6 #include <vnl/vnl_matrix_fixed.h>
7 #include <vnl/vnl_vector_fixed.h>
8 #include <vnl/vnl_det.h>
9 #include <vnl/algo/vnl_svd.h>
10 
11 //: only one constructor. X and Y must have dimensions 3 x N
14  vnl_matrix<double> const& Y)
15  : cannot_compute_(false), computed_(false), s_(1.0), residual_(0)
16 {
17  if (X.rows()!=3 || Y.rows()!=3||X.columns()!=Y.columns()){
18  cannot_compute_ = true;
19  std::cout << "Fatal error in vpgl_ortho_procrustes - unmatched pointsets\n";
20  return;
21  }
22  X_ = X;
23  Y_ = Y;
24 }
25 
27 {
28  unsigned N = X_.columns();
29  //remove the centroid of both point sets
31  Cx.fill(0); Cy.fill(0);
32  for (unsigned c = 0; c<N; ++c)
33  {
35  for (unsigned r = 0; r<3; ++r)
36  {
37  vx[r] = X_[r][c];
38  vy[r] = Y_[r][c];
39  }
40  Cx += vx;
41  Cy += vy;
42  }
43  Cx/=N; Cy/=N;
44  vnl_matrix<double> Xm(3, N), Ym(3,N);
45  double smx=0, smy=0;
46  for (unsigned c = 0; c<N; ++c)
47  {
49  for (unsigned r = 0; r<3; ++r)
50  {
51  Xm[r][c] = X_[r][c]-Cx[r];
52  Ym[r][c] = Y_[r][c]-Cy[r];
53  Sx[r] = Xm[r][c];
54  Sy[r] = Ym[r][c];
55  }
56  smx += Sx.squared_magnitude();
57  smy += Sy.squared_magnitude();
58  }
59 
60  auto neu = vnl_trace<double, 3, 3>(Xm*(Xm.transpose()));
61  auto den = vnl_trace<double, 3, 3>(Ym*(Ym.transpose()));
62  if (den!=0)
63  s_ = std::sqrt(neu/den);
64 
65  //Normalize X, Y by the average radius
66  double sigma_x = std::sqrt(smx/N), sigma_y = std::sqrt(smy/N);
67  Xm /= sigma_x;
68  Ym /= sigma_y;
69 
70  vnl_matrix<double> Xt = Xm.transpose();
72  vnl_svd<double> SVD(M.as_ref());
75  vnl_matrix_fixed<double, 3,3> Ut = U.transpose();
77  temp = V*Ut;
78  T.fill(0);
79  T[0][0]=1.0;
80  T[1][1]=1.0;
81  T[2][2]=vnl_det<double>(temp);
83  double dt = vnl_det(rr);
84  if(dt<=0.0){
85  cannot_compute_ = true;
86  return;
87  }
89  t_ = (1.0/s_)*Cx - rr*Cy;
90  //compute the mean square residual
91  residual_ = 0;
92  for (unsigned c = 0; c<N; ++c)
93  {
94  vnl_vector_fixed<double, 3> x, y, diff;
95  for (unsigned r = 0; r<3; ++r)
96  {
97  x[r]=X_[r][c];
98  y[r]=Y_[r][c];
99  }
100  diff = s_*(rr*y + t_) - x;
101  residual_ += diff.squared_magnitude();
102  }
103  residual_ /= (3*N);
104  computed_ = true;
105 }
106 
108 {
109  if (!computed_&&!cannot_compute_)
110  this->compute();
111  return R_;
112 }
113 
115 {
116  if (!computed_&&!cannot_compute_)
117  this->compute();
118  return s_;
119 }
120 
121 
123 {
124  if (!computed_&&!cannot_compute_)
125  this->compute();
126  return residual_;
127 }
128 
130 {
131  if (!computed_&&!cannot_compute_)
132  this->compute();
133  return t_;
134 }
vnl_matrix_ref< T > as_ref()
vnl_matrix< double > Y_
vnl_vector_fixed< double, 3 > t()
the resulting translation vector.
vnl_matrix< double > transpose() const
vpgl_ortho_procrustes()
No default constructor.
vnl_matrix< double > X_
vnl_vector_fixed & fill(T const &v)
vgl_rotation_3d< double > R_
abs_t squared_magnitude() const
VNL_EXPORT T vnl_det(T const *row0, T const *row1)
vnl_matrix_fixed & fill(T)
double residual_mean_sq_error()
the residual error.
unsigned int rows() const
vnl_vector_fixed< double, 3 > t_
vgl_rotation_3d< double > R()
the resulting rotation matrix.
unsigned int columns() const
Solve min(R,s) ||X-s(RY+t)||, where R is a rotation matrix, X,Y are 3-d points, s is a scalar and t i...
double s()
The scale factor, s.