vgl_compute_rigid_3d.hxx
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_compute_rigid_3d.hxx
2 #ifndef vgl_compute_rigid_3d_hxx_
3 #define vgl_compute_rigid_3d_hxx_
4 //:
5 // \file
6 
7 #include <iostream>
8 #include "vgl_compute_rigid_3d.h"
10 #include <vnl/vnl_double_4.h>
11 #include <vnl/algo/vnl_svd.h>
12 #include <vnl/algo/vnl_determinant.h>
13 #include <vnl/vnl_matrix.h>
14 #ifdef _MSC_VER
15 # include <vcl_msvc_warnings.h>
16 #endif
17 #include <cassert>
18 
19 template <class T>
21 vgl_compute_rigid_3d(std::vector<vgl_point_3d<T> > const& points1,
22  std::vector<vgl_point_3d<T> > const& points2)
23 : points1_(points1),
24  points2_(points2)
25 {
26  assert(points1.size() == points2.size());
27 }
28 
29 template <class T>
32 {
33  points1_.push_back(p1);
34  points2_.push_back(p2);
35 }
36 
37 
38 template <class T>
40 {
41  points1_.clear();
42  points2_.clear();
43 }
44 
45 
46 //: center all the points at the origin, and return the applied translation
47 template <class T>
49 center_points(std::vector<vgl_point_3d<T> >& pts,
50  vgl_vector_3d<T>& t) const
51 {
52  t.set(0,0,0);
53  vgl_point_3d<T> origin(0,0,0);
54  for (unsigned i=0; i<pts.size(); ++i)
55  {
56  t += origin - pts[i];
57  }
58  t /= pts.size();
59  for (unsigned i=0; i<pts.size(); ++i)
60  {
61  pts[i] += t;
62  }
63 }
64 
65 
66 //: normalize the scale of the points, and return the applied scale
67 // The average distance from the origin will be sqrt(3)
68 template <class T>
70 scale_points(std::vector<vgl_point_3d<T> >& pts,
71  T& s) const
72 {
73  s = 0.0;
74  vgl_point_3d<T> origin(0,0,0);
75  for (unsigned i=0; i<pts.size(); ++i)
76  {
77  s += (pts[i]-origin).length();
78  }
79  s = std::sqrt(3.0)*pts.size()/s;
80  for (unsigned i=0; i<pts.size(); ++i)
81  {
82  vgl_point_3d<T>& p = pts[i];
83  p.set(p.x()*s, p.y()*s, p.z()*s);
84  }
85 }
86 
87 
88 template <class T>
90 {
91  vgl_vector_3d<T> t1, t2;
92  std::vector<vgl_point_3d<T> > pts1(points1_), pts2(points2_);
93  center_points(pts1, t1);
94  center_points(pts2, t2);
95 
96  T s1, s2;
97  scale_points(pts2, s2);
98  s1 = s2;
99  for (unsigned i=0; i<pts1.size(); ++i)
100  {
101  vgl_point_3d<T>& p = pts1[i];
102  p.set(p.x()*s1, p.y()*s1, p.z()*s1);
103  }
104 
105  // estimate rotation
106  vnl_matrix<T> M(3,3,0.0);
107  for (unsigned i=0; i<pts1.size(); ++i)
108  {
109  vgl_point_3d<T>& p1 = pts1[i];
110  vgl_point_3d<T>& p2 = pts2[i];
111  M(0,0) += p1.x()*p2.x();
112  M(0,1) += p1.x()*p2.y();
113  M(0,2) += p1.x()*p2.z();
114  M(1,0) += p1.y()*p2.x();
115  M(1,1) += p1.y()*p2.y();
116  M(1,2) += p1.y()*p2.z();
117  M(2,0) += p1.z()*p2.x();
118  M(2,1) += p1.z()*p2.y();
119  M(2,2) += p1.z()*p2.z();
120  }
121 
122  vnl_matrix<T> N(4,4);
123  N(0,0) = M(0,0) - M(1,1) - M(2,2);
124  N(1,1) = - M(0,0) + M(1,1) - M(2,2);
125  N(2,2) = - M(0,0) - M(1,1) + M(2,2);
126  N(3,3) = M(0,0) + M(1,1) + M(2,2);
127  N(0,1) = N(1,0) = M(0,1) + M(1,0);
128  N(0,2) = N(2,0) = M(2,0) + M(0,2);
129  N(1,2) = N(2,1) = M(1,2) + M(2,1);
130  N(3,0) = N(0,3) = M(1,2) - M(2,1);
131  N(3,1) = N(1,3) = M(2,0) - M(0,2);
132  N(3,2) = N(2,3) = M(0,1) - M(1,0);
133 
134  vnl_svd<T> svd(N);
135  vnl_double_4 q(svd.V().get_column(0));
136  rotation_ = vgl_rotation_3d<T>(vnl_quaternion<T>(q));
137  translation_ = (rotation_*t1) - t2;
138 
139  return true;
140 }
141 
142 //--------------------------------------------------------------------------
143 #undef VGL_COMPUTE_RIGID_3D_INSTANTIATE
144 #define VGL_COMPUTE_RIGID_3D_INSTANTIATE(T) \
145 template class vgl_compute_rigid_3d<T >
146 
147 #endif // vgl_compute_rigid_3d_hxx_
void center_points(std::vector< vgl_point_3d< T > > &pts, vgl_vector_3d< T > &t) const
center all the points at the origin, and return the applied translation.
vgl_compute_rigid_3d()=default
double length(v const &a)
Return the length of a vector.
Definition: vgl_vector_2d.h:94
Type & z()
Definition: vgl_point_3d.h:73
void scale_points(std::vector< vgl_point_3d< T > > &pts, T &s) const
normalize the scale of the points, and return the applied scale.
Compute a rigid transformation between two corresponding sets of 3D points.
bool estimate()
estimates the rigid transformation from the stored points.
Type & x()
Definition: vgl_point_3d.h:71
Direction vector in Euclidean 3D space, templated by type of element.
Definition: vgl_fwd.h:13
void set(T vx, T vy, T vz)
Assignment.
Definition: vgl_vector_3d.h:60
void set(Type px, Type py, Type pz)
Set x, y and z.
Definition: vgl_point_3d.h:81
void add_points(vgl_point_3d< T > const &p1, vgl_point_3d< T > const &p2)
add a pair of points to point sets.
void clear()
clear internal data.
The similarity transform that normalizes a 3-d point set.
Type & y()
Definition: vgl_point_3d.h:72