cgv
Loading...
Searching...
No Matches
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
6namespace cgv {
7 namespace math {
8
13template <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
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
93template <typename T>
94void find_nonrigid_transformation(const mat<T>& points1,
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
153template <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
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
210template <typename T>
211void find_nonrigid_transformation(const mat<T>& points1,
212 const mat<T>& points2,
213 thin_hyper_plate_spline<T>& spline)
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
276template <typename T>
277void apply_nonrigid_transformation(const thin_plate_spline<T>& s, mat<T>& points)
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
288template <typename T>
289void apply_nonrigid_transformation(const thin_hyper_plate_spline<T>& s, mat<T>& points)
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}
A matrix type (full column major storage) The matrix can be loaded directly into OpenGL without need ...
Definition mat.h:208
unsigned ncols() const
number of columns
Definition mat.h:546
void set_col(unsigned j, const vec< T > &v)
set column j of the matrix to vector v
Definition mat.h:846
const vec< T > col(unsigned j) const
extract a column of the matrix as a vector
Definition mat.h:833
unsigned nrows() const
number of rows
Definition mat.h:540
A column vector class.
Definition vec.h:28
unsigned size() const
number of elements
Definition vec.h:59
the cgv namespace
Definition print.h:11
A thin hyperplate spline which represents 3d deformations 3d extension of the thin plate spline.
mat< T > map_positions(const mat< T > &points)
deform 3d points stored as columns of the matrix points
vec< T > map_position(const vec< T > &p)
deform 2d point p
A thin plate spline which represents 2d deformations See Fred L.
vec< T > map_position(const vec< T > &p)
deform a 2d point
static T U(const T &sqr_dist)
basis function
mat< T > map_positions(const mat< T > &points)
deform 2d points stored as columns of the matrix points