1 #include "TFTensorEstimation.hh"
2 #include "TrifocalTensor.hh"
3 #include <Base/Geometry/HomgPoint2D.hh>
4 #include <MathAlgo/SVD.hh>
5 #include <Base/Math/Matrix.hh>
11 #define USE_FOUR_EQUATIONS_PER_POINT
12 #define TFT_EST_CHECK_EQUATIONS
13 #define TFT_EST_USE_SVD_HACK
16 TFTensorEstimation::TFTensorEstimation()
21 TFTensorEstimation::~TFTensorEstimation(){}
25 const vector<HomgPoint2D> &x1,
26 const vector<HomgPoint2D> &x2,
27 const vector<HomgPoint2D> &x3,
28 bool HartleyNormalization )
30 BIASASSERT( x1.size()==x2.size() && x2.size()==x3.size() );
33 BIASERR(
"Need at least 7 correspondences for computation!");
38 vector<HomgPoint2D> p1, p1norm;
39 vector<HomgPoint2D> p2, p2norm;
40 vector<HomgPoint2D> p3, p3norm;
48 if (HartleyNormalization)
50 cout <<
"Performing Hartley normalization..." << endl;
51 Norm_.Hartley(p1, p1norm, K1);
52 Norm_.Hartley(p2, p2norm, K2);
53 Norm_.Hartley(p3, p3norm, K3);
57 cout <<
"K1 = " << K1 << endl;
58 cout <<
"K2 = " << K2 << endl;
59 cout <<
"K3 = " << K3 << endl;
63 cerr <<
"Hartley normalization skipped." << endl;
68 #ifdef USE_FOUR_EQUATIONS_PER_POINT
70 for(
int corr=0; corr<(int)p1.size(); corr++) {
72 A[corr][0] = p1[corr][0];
74 A[corr][2] = - p1[corr][0] * p3[corr][0];
78 A[corr][6] = - p1[corr][0] * p2[corr][0];
80 A[corr][8] = p1[corr][0] * p2[corr][0] * p3[corr][0];
82 A[corr][9] = p1[corr][1];
84 A[corr][11] = - p1[corr][1] * p3[corr][0];
88 A[corr][15] = - p1[corr][1] * p2[corr][0];
90 A[corr][17] = p1[corr][1] * p2[corr][0] * p3[corr][0];
92 A[corr][18] = p1[corr][2];
94 A[corr][20] = - p1[corr][2] * p3[corr][0];
98 A[corr][24] = - p1[corr][2] * p2[corr][0];
100 A[corr][26] = p1[corr][2] * p2[corr][0] * p3[corr][0];
104 A[corr+n][1] = p1[corr][0];
105 A[corr+n][2] = - p1[corr][0] * p3[corr][1];
110 A[corr+n][7] = - p1[corr][0] * p2[corr][0];
111 A[corr+n][8] = p1[corr][0] * p2[corr][0] * p3[corr][1];
114 A[corr+n][10]= p1[corr][1];
115 A[corr+n][11]= - p1[corr][1] * p3[corr][1];
120 A[corr+n][16]= - p1[corr][1] * p2[corr][0];
121 A[corr+n][17]= p1[corr][1] * p2[corr][0] * p3[corr][1];
124 A[corr+n][19]= p1[corr][2];
125 A[corr+n][20]= - p1[corr][2] * p3[corr][1];
130 A[corr+n][25]= - p1[corr][2] * p2[corr][0];
131 A[corr+n][26]= p1[corr][2] * p2[corr][0] * p3[corr][1];
134 A[corr+2*n][0] = 0.0;
135 A[corr+2*n][1] = 0.0;
136 A[corr+2*n][2] = 0.0;
137 A[corr+2*n][3] = p1[corr][0];
138 A[corr+2*n][4] = 0.0;
139 A[corr+2*n][5] = - p1[corr][0] * p3[corr][0];
140 A[corr+2*n][6] = - p1[corr][0] * p2[corr][1];
141 A[corr+2*n][7] = 0.0;
142 A[corr+2*n][8] = p1[corr][0] * p2[corr][1] * p3[corr][0];
144 A[corr+2*n][9] = 0.0;
145 A[corr+2*n][10]= 0.0;
146 A[corr+2*n][11]= 0.0;
147 A[corr+2*n][12]= p1[corr][1];
148 A[corr+2*n][13]= 0.0;
149 A[corr+2*n][14]= - p1[corr][1] * p3[corr][0];
150 A[corr+2*n][15]= - p1[corr][1] * p2[corr][1];
151 A[corr+2*n][16]= 0.0;
152 A[corr+2*n][17]= p1[corr][1] * p2[corr][1] * p3[corr][0];
154 A[corr+2*n][18]= 0.0;
155 A[corr+2*n][19]= 0.0;
156 A[corr+2*n][20]= 0.0;
157 A[corr+2*n][21]= p1[corr][2];
158 A[corr+2*n][22]= 0.0;
159 A[corr+2*n][23]= - p1[corr][2] * p3[corr][0];
160 A[corr+2*n][24]= - p1[corr][2] * p2[corr][1];
161 A[corr+2*n][25]= 0.0;
162 A[corr+2*n][26]= p1[corr][2] * p2[corr][1] * p3[corr][0];
165 A[corr+3*n][0] = 0.0;
166 A[corr+3*n][1] = 0.0;
167 A[corr+3*n][2] = 0.0;
168 A[corr+3*n][3] = 0.0;
169 A[corr+3*n][4] = p1[corr][0];
170 A[corr+3*n][5] = - p1[corr][0] * p3[corr][1];
171 A[corr+3*n][6] = 0.0;
172 A[corr+3*n][7] = - p1[corr][0] * p2[corr][1];
173 A[corr+3*n][8] = p1[corr][0] * p2[corr][1] * p3[corr][1];
175 A[corr+3*n][9] = 0.0;
176 A[corr+3*n][10]= 0.0;
177 A[corr+3*n][11]= 0.0;
178 A[corr+3*n][12]= 0.0;
179 A[corr+3*n][13]= p1[corr][1];
180 A[corr+3*n][14]= - p1[corr][1] * p3[corr][1];
181 A[corr+3*n][15]= 0.0;
182 A[corr+3*n][16]= - p1[corr][1] * p2[corr][1];
183 A[corr+3*n][17]= p1[corr][1] * p2[corr][1] * p3[corr][1];
185 A[corr+3*n][18]= 0.0;
186 A[corr+3*n][19]= 0.0;
187 A[corr+3*n][20]= 0.0;
188 A[corr+3*n][21]= 0.0;
189 A[corr+3*n][22]= p1[corr][2];
190 A[corr+3*n][23]= - p1[corr][2] * p3[corr][1];
191 A[corr+3*n][24]= 0.0;
192 A[corr+3*n][25]= - p1[corr][2] * p2[corr][1];
193 A[corr+3*n][26]= p1[corr][2] * p2[corr][1] * p3[corr][1];
197 for (
int i=0; i<(int)p1.size(); i++)
204 A[i][2] = -p1[i][0] * p3[i][0] - p1[i][0] * p3[i][1];
210 A[i][5] = -p1[i][0] * p3[i][0] - p1[i][0] * p3[i][1];
212 A[i][6] = -p1[i][0] * p2[i][0] - p1[i][0] * p2[i][1];
214 A[i][7] = -p1[i][0] * p2[i][0] - p1[i][0] * p2[i][1];
217 p1[i][0] * p2[i][0] * p3[i][0] +
218 p1[i][0] * p2[i][0] * p3[i][1] +
219 p1[i][0] * p2[i][1] * p3[i][0] +
220 p1[i][0] * p2[i][1] * p3[i][1] ;
226 A[i][11] = -p1[i][1] * p3[i][0] - p1[i][1] * p3[i][1];
232 A[i][14] = -p1[i][1] * p3[i][0] - p1[i][1] * p3[i][1];
234 A[i][15] = -p1[i][1] * p2[i][0] - p1[i][1] * p2[i][1];
236 A[i][16] = -p1[i][1] * p2[i][0] - p1[i][1] * p2[i][1];
239 p1[i][1] * p2[i][0] * p3[i][0] +
240 p1[i][1] * p2[i][0] * p3[i][1] +
241 p1[i][1] * p2[i][1] * p3[i][0] +
242 p1[i][1] * p2[i][1] * p3[i][1] ;
248 A[i][20] = -p1[i][2] * p3[i][0] - p1[i][2] * p3[i][1];
254 A[i][23] = -p1[i][2] * p3[i][0] - p1[i][2] * p3[i][1];
256 A[i][24] = -p1[i][2] * p2[i][0] - p1[i][2] * p2[i][1];
258 A[i][25] = -p1[i][2] * p2[i][0] - p1[i][2] * p2[i][1];
261 p1[i][2] * p2[i][0] * p3[i][0] +
262 p1[i][2] * p2[i][0] * p3[i][1] +
263 p1[i][2] * p2[i][1] * p3[i][0] +
264 p1[i][2] * p2[i][1] * p3[i][1] ;
268 #ifdef TFT_EST_CHECK_EQUATIONS
269 cout <<
"A = " << A << endl;
276 #ifdef TFT_EST_USE_SVD_HACK
280 for (
int col=0; col < VT.
num_cols(); col++)
282 Tvec[col] = VT[ VT.
num_cols() - 1 ][col];
288 cout <<
"Tvec = " << Tvec << endl;
290 #ifdef TFT_EST_CHECK_EQUATIONS
291 cout << A * Tvec << endl;
296 #ifdef TFT_EST_CHECK_EQUATIONS
298 for (
unsigned int i=0; i<p1.size(); i++)
300 cout <<
"\nChecking correspondence " << i << endl;
302 p1[i][0] * p2[i][0] * p3[i][0] * T(0,2,2)
303 - p1[i][0] * p3[i][0] * T(0,0,2)
304 - p1[i][0] * p2[i][0] * T(0,2,0)
305 + p1[i][0] * T(0,0,0);
307 p1[i][1] * p2[i][0] * p3[i][0] * T(1,2,2)
308 - p1[i][1] * p3[i][0] * T(1,0,2)
309 - p1[i][1] * p2[i][0] * T(1,2,0)
310 + p1[i][1] * T(1,0,0);
312 p1[i][2] * p2[i][0] * p3[i][0] * T(2,2,2)
313 - p1[i][2] * p3[i][0] * T(2,0,2)
314 - p1[i][2] * p2[i][0] * T(2,2,0)
315 + p1[i][2] * T(2,0,0);
316 cout <<
" result 1 is "<<result<<endl;
319 p1[i][0] * p2[i][0] * p3[i][1] * T(0,2,2)
320 - p1[i][0] * p3[i][1] * T(0,0,2)
321 - p1[i][0] * p2[i][0] * T(0,2,1)
322 + p1[i][0] * T(0,0,1);
324 p1[i][1] * p2[i][0] * p3[i][1] * T(1,2,2)
325 - p1[i][1] * p3[i][1] * T(1,0,2)
326 - p1[i][1] * p2[i][0] * T(1,2,1)
327 + p1[i][1] * T(1,0,1);
329 p1[i][2] * p2[i][0] * p3[i][1] * T(2,2,2)
330 - p1[i][2] * p3[i][1] * T(2,0,2)
331 - p1[i][2] * p2[i][0] * T(2,2,1)
332 + p1[i][2] * T(2,0,1);
333 cout <<
" result 2 is "<<result<<endl;
336 p1[i][0] * p2[i][1] * p3[i][0] * T(0,2,2)
337 - p1[i][0] * p3[i][0] * T(0,1,2)
338 - p1[i][0] * p2[i][1] * T(0,2,0)
339 + p1[i][0] * T(0,1,0);
341 p1[i][1] * p2[i][1] * p3[i][0] * T(1,2,2)
342 - p1[i][1] * p3[i][0] * T(1,1,2)
343 - p1[i][1] * p2[i][1] * T(1,2,0)
344 + p1[i][1] * T(1,1,0);
346 p1[i][2] * p2[i][1] * p3[i][0] * T(2,2,2)
347 - p1[i][2] * p3[i][0] * T(2,1,2)
348 - p1[i][2] * p2[i][1] * T(2,2,0)
349 + p1[i][2] * T(2,1,0);
350 cout <<
" result 3 is "<<result<<endl;
353 p1[i][0] * p2[i][1] * p3[i][1] * T(0,2,2)
354 - p1[i][0] * p3[i][1] * T(0,1,2)
355 - p1[i][0] * p2[i][1] * T(0,2,1)
356 + p1[i][0] * T(0,1,1);
358 p1[i][1] * p2[i][1] * p3[i][1] * T(1,2,2)
359 - p1[i][1] * p3[i][1] * T(1,1,2)
360 - p1[i][1] * p2[i][1] * T(1,2,1)
361 + p1[i][1] * T(1,1,1);
363 p1[i][2] * p2[i][1] * p3[i][1] * T(2,2,2)
364 - p1[i][2] * p3[i][1] * T(2,1,2)
365 - p1[i][2] * p2[i][1] * T(2,2,1)
366 + p1[i][2] * T(2,1,1);
367 cout <<
" result 4 is "<<result<<endl;
372 AlgebraicMinimization(T,T2);
374 if (HartleyNormalization)
377 T. premultiply2(K2.
Invert(),T2);
393 cerr <<
"The algebraic minimization is not fully implemented yet.\n"
394 <<
"So the result is the initial tensor!" << endl;
Vector< double > GetNullvector(const int last_offset=0)
return one of the nullvectors.
computes and holds the singular value decomposition of a rectangular (not necessarily quadratic) Matr...
Subscript num_cols() const
class for column vectors with arbitrary size
void postmultiply1(const BIAS::Matrix3x3< T > &M, Tensor3D3x3x3< T > &result) const
Compute S_{ijk} = T_{pjk} M_{pi}.
void SetFromVector(const BIAS::Vector< T > &v)
set the tensor by the rows of the vector.
void premultiply3(const BIAS::Matrix3x3< T > &M, Tensor3D3x3x3< T > &result) const
compute S_{ijk} = M_{kp} T_{ijp}
const int RightNullspaceDim() const
returns the dim of the matrix's right nullspace
const Matrix< double > & GetVT() const
return VT (=transposed(V))
const int LeftNullspaceDim() const
returns the dim of the matrix's left nullspace
matrix class with arbitrary size, indexing is row major.
K describes the mapping from world coordinates (wcs) to pixel coordinates (pcs).
KMatrix Invert() const
returns analyticaly inverted matrix