cgv
thin_plate_spline.h
1 #pragma once
2 #include <cgv/math/mat.h>
3 #include <cgv/math/vec.h>
4 #include <cgv/math/lin_solve.h>
5 
6 namespace cgv {
7  namespace math {
8 
13 template <typename T>
15 {
16  mat<T> controlpoints;
17  mat<T> weights;
18  mat<T> affine_transformation;
19 
22  {
23  assert(p.size() == 2);
24  vec<T> r(2);
25  r(0) = affine_transformation(0,0)
26  +affine_transformation(1,0)*p(0)
27  +affine_transformation(2,0)*p(1);
28  r(1) = affine_transformation(0,1)
29  +affine_transformation(1,1)*p(0)
30  +affine_transformation(2,1)*p(1);
31  for(unsigned i = 0;i < weights.nrows();i++)
32  {
33  T u_sqr_dist=U(sqr_length(p-controlpoints.col(i)));
34  r(0)+=weights(i,0)*u_sqr_dist;
35  r(1)+=weights(i,1)*u_sqr_dist;
36  }
37  return r;
38  }
39 
41  vec<T> map_affine_position(const vec<T>& p)
42  {
43  assert(p.size() == 2);
44  vec<T> r(2);
45 
46  vec<T> temp(4);
47  temp(0) = (affine_transformation(1,0) + affine_transformation(2,1))/2;
48  temp(1) = (affine_transformation(2,0) - affine_transformation(1,1))/2;
49  temp(2) = - temp(1);
50  temp(3) = temp(0);
51 
52  r(0) = affine_transformation(0,0)
53  +temp(0) * p(0)
54  +temp(1) * p(1);
55  r(1) = affine_transformation(0,1)
56  +temp(2) * p(0)
57  +temp(3) * p(1);
58 
59  return r;
60  }
62 
64  mat<T> map_positions(const mat<T>& points)
65  {
66  assert(points.nrows() == 2);
67  mat<T> rpoints(points.nrows(),points.ncols());
68 
69  for(unsigned i = 0; i < points.ncols(); i++)
70  rpoints.set_col(i,map_position(points.col(i)));
71 
72  return rpoints;
73  }
74 
76  static T U(const T& sqr_dist)
77  {
78  static const T factor = (T)(1.0/(2.0*log((double)10)));
79  if(sqr_dist == 0)
80  return 0;
81  return sqr_dist*log(sqr_dist)*factor;
82  }
83 
84 };
85 
86 
87 
88 
89 
93 template <typename T>
95  const mat<T>& points2,
96  thin_plate_spline<T>& spline)
97 {
98  assert(points1.nrows() == 2 && points2.nrows() == 2);
99  assert(points1.ncols() == points2.ncols());
100  assert(points1.ncols() > 2);//at least three points
101 
102  int n = points1.ncols();
103 
104  mat<T> L(n+3,n+3);
105 
106 
107  for(int i = 0; i < n;i++)
108  for(int j = 0; j < n;j++)
109  {
110  T sqr_dist = sqr_length(points1.col(i)-points1.col(j));
111  L(i,j)=thin_plate_spline<T>::U(sqr_dist);
112  }
113 
114  for(int i = 0; i < n; i++)
115  {
116  L(i,n) = 1;
117  L(i,n+1) = points1.col(i)(0);
118  L(i,n+2) = points1.col(i)(1);
119  L(n,i) = 1;
120  L(n+1,i) = points1.col(i)(0);
121  L(n+2,i) = points1.col(i)(1);
122  }
123 
124  for(int i = n; i < n+3;i++)
125  {
126  for(int j = n; j < n+3;j++)
127  {
128  L(i,j)=0;
129  }
130 
131  }
132 
133  mat<T> V(n+3,2);
134  for(int i =0;i < n; i++)
135  {
136  V(i,0)=points2(0,i);
137  V(i,1)=points2(1,i);
138  }
139  V(n,0)=V(n,1)=V(n+1,0)=V(n+1,1)=V(n+2,0)=V(n+2,1)=0;
140  mat<T> W(n+3,2);
141 
142  svd_solve(L,V,W);
143 
144  spline.controlpoints=points1;
145  spline.weights=W.sub_mat(0,0,n,2);
146 
147  spline.affine_transformation =W.sub_mat(n,0,3,2);
148 
149 }
150 
153 template <typename T>
155 {
156  mat<T> controlpoints;
157  mat<T> weights;
158  mat<T> affine_transformation;
159 
162  {
163 
164  assert(p.size() == 3);
165  vec<T> r(3);
166  r(0) = affine_transformation(0,0)
167  +affine_transformation(1,0)*p(0)
168  +affine_transformation(2,0)*p(1)
169  +affine_transformation(3,0)*p(2);
170 
171  r(1) = affine_transformation(0,1)
172  +affine_transformation(1,1)*p(0)
173  +affine_transformation(2,1)*p(1)
174  +affine_transformation(3,1)*p(2);
175 
176  r(2) = affine_transformation(0,2)
177  +affine_transformation(1,2)*p(0)
178  +affine_transformation(2,2)*p(1)
179  +affine_transformation(3,2)*p(2);
180 
181  for(unsigned i = 0;i < weights.nrows();i++)
182  {
183  T u=length(p-controlpoints.col(i));
184  r(0)+=weights(i,0)*u;
185  r(1)+=weights(i,1)*u;
186  r(2)+=weights(i,2)*u;
187  }
188  return r;
189 
190  }
191 
193  mat<T> map_positions(const mat<T>& points)
194  {
195  mat<T> rpoints(points.nrows(),points.ncols());
196  assert(points.nrows() == 3);
197  for(unsigned i = 0; i < points.ncols(); i++)
198  {
199  rpoints.set_col(i,map_position(points.col(i)));
200  }
201  return rpoints;
202  }
203 
204 };
205 
206 
210 template <typename T>
212  const mat<T>& points2,
214 {
215  assert(points1.nrows() == 3 && points2.nrows()==3);
216  assert(points1.ncols() == points2.ncols());
217  assert(points1.nrows()==4);
218 
219  int n = points1.ncols();
220 
221  mat<T> L(n+4,n+4);
222 
223 
224  for(int i = 0; i < n;i++)
225  for(int j = 0; j < n;j++)
226  {
227  L(i,j)=length(points1.col(i)-points1.col(j));
228  }
229 
230  for(int i = 0; i < n; i++)
231  {
232  L(i,n) = 1;
233  L(i,n+1) = points1.col(i)(0);
234  L(i,n+2) = points1.col(i)(1);
235  L(i,n+3) = points1.col(i)(2);
236  L(n,i) = 1;
237  L(n+1,i) = points1.col(i)(0);
238  L(n+2,i) = points1.col(i)(1);
239  L(n+3,i) = points1.col(i)(2);
240 
241  }
242 
243  for(int i = n; i < n+4;i++)
244  {
245  for(int j = n; j < n+4;j++)
246  {
247  L(i,j)=0;
248  }
249  }
250 
251 
252  mat<T> V(n+4,3);
253  for(int i =0;i < n; i++)
254  {
255  V(i,0)=points2(0,i);
256  V(i,1)=points2(1,i);
257  V(i,2)=points2(2,i);
258  }
259  V(n,0)=V(n,1)=V(n,2)=V(n+1,0)=V(n+1,1)=V(n+1,2)=V(n+2,0)=V(n+2,1)=V(n+2,2)
260  =V(n+3,0)=V(n+3,1)=V(n+3,2)=0;
261 
262  mat<T> W(n+4,3);
263  svd_solve(L,V,W);
264 
265  spline.controlpoints=points1;
266  spline.weights=W.sub_mat(0,0,n,3);
267  spline.affine_transformation =W.sub_mat(n,0,4,3);
268 
269 
270 
271 }
272 
273 
276 template <typename T>
278 {
279  assert(points.nrows() == 2);
280  for(unsigned i = 0; i < points.ncols(); i++)
281  {
282  points.set_col(i,s.map_position(points.col(i)));
283  }
284 }
285 
288 template <typename T>
290 {
291  assert(points.nrows() == 3);
292  for(unsigned i = 0; i < points.ncols(); i++)
293  {
294  points.set_col(i,s.map_position(points.col(i)));
295  }
296 }
297 
298 
299 }
300 
301 
302 
303 
304 }
cgv::math::thin_plate_spline::map_position
vec< T > map_position(const vec< T > &p)
deform a 2d point
Definition: thin_plate_spline.h:21
cgv::math::svd_solve
bool svd_solve(const mat< T > &a, const vec< T > &b, vec< T > &x)
solve ax=b with svd decomposition
Definition: lin_solve.h:300
cgv::math::thin_hyper_plate_spline::map_positions
mat< T > map_positions(const mat< T > &points)
deform 3d points stored as columns of the matrix points
Definition: thin_plate_spline.h:193
cgv::math::mat
Definition: mat.h:14
cgv::math::thin_plate_spline::U
static T U(const T &sqr_dist)
basis function
Definition: thin_plate_spline.h:76
cgv::math::thin_plate_spline
Definition: thin_plate_spline.h:15
cgv::math::vec
A column vector class.
Definition: fvec.h:13
cgv::math::thin_hyper_plate_spline::map_position
vec< T > map_position(const vec< T > &p)
deform 2d point p
Definition: thin_plate_spline.h:161
cgv::math::vec::size
unsigned size() const
number of elements
Definition: vec.h:97
cgv::math::thin_hyper_plate_spline
Definition: thin_plate_spline.h:155
cgv::math::mat::col
const vec< T > col(unsigned j) const
extract a column of the matrix as a vector
Definition: mat.h:839
cgv::math::apply_nonrigid_transformation
void apply_nonrigid_transformation(const thin_plate_spline< T > &s, mat< T > &points)
Definition: thin_plate_spline.h:277
cgv::math::find_nonrigid_transformation
void find_nonrigid_transformation(const mat< T > &points1, const mat< T > &points2, thin_plate_spline< T > &spline)
Definition: thin_plate_spline.h:94
cgv::math::mat::set_col
void set_col(unsigned j, const vec< T > &v)
set column j of the matrix to vector v
Definition: mat.h:852
cgv::math::sqr_length
T sqr_length(const fvec< T, N > &v)
returns the squared length of vector v
Definition: fvec.h:330
cgv::math::mat::sub_mat
mat< T > sub_mat(unsigned top, unsigned left, unsigned rows, unsigned cols) const
create submatrix m(top,left)...m(top+rows,left+cols)
Definition: mat.h:803
cgv::math::thin_plate_spline::map_positions
mat< T > map_positions(const mat< T > &points)
deform 2d points stored as columns of the matrix points
Definition: thin_plate_spline.h:64
cgv::math::mat::nrows
unsigned nrows() const
number of rows
Definition: mat.h:541
cgv::math::mat::ncols
unsigned ncols() const
number of columns
Definition: mat.h:547
cgv
the cgv namespace
Definition: vr_calib.cxx:9
cgv::math::length
T length(const fvec< T, N > &v)
returns the length of vector v
Definition: fvec.h:310