contrib/oxl/mvl/mvl_linear_backproject.cxx
Go to the documentation of this file.
00001 #include "mvl_linear_backproject.h"
00002 #include <vcl_iostream.h>
00003 #include <vcl_cstdlib.h>
00004 #include <vnl/algo/vnl_svd.h>
00005 
00006 vnl_vector<double> mvl_linear_backproject(
00007           // camera matrices:
00008           vcl_vector<PMatrix> Ps,
00009           // image coordinates
00010           HomgPoint2D const *imgcoords,
00011           // world point:
00012           HomgPoint3D &X,
00013           // if true (default false), use current value of X to commute weights.
00014           bool re_weighted,
00015           // if 'e' (default) then use eigenvalue method if 'l' use least-squares (see Hartley & Sturm 'Triangulation' paper)
00016           char method)
00017 {
00018   int numviews = Ps.size();
00019   vnl_vector<double> weights(numviews, 0);
00020   vnl_matrix<double> A(numviews*2, 4);
00021 
00022   // there are the two rows of the least squares problem for each view:
00023   vnl_vector<double> row0(4), row1(4);
00024 
00025   // i is the view index
00026   for (int i=0, j=0; i < numviews; i++, j+=2)
00027   {
00028     vnl_double_3x4 const &P = Ps[i].get_matrix();
00029 
00030     row0[0] = imgcoords[i].x()*P(2,0) - P(0,0);
00031     row0[1] = imgcoords[i].x()*P(2,1) - P(0,1);
00032     row0[2] = imgcoords[i].x()*P(2,2) - P(0,2);
00033     row0[3] = imgcoords[i].x()*P(2,3) - P(0,3);
00034 
00035     row1[0] = imgcoords[i].y()*P(2,0) - P(1,0);
00036     row1[1] = imgcoords[i].y()*P(2,1) - P(1,1);
00037     row1[2] = imgcoords[i].y()*P(2,2) - P(1,2);
00038     row1[3] = imgcoords[i].y()*P(2,3) - P(1,3);
00039 
00040     // normalisation :
00041     if (re_weighted) // calculate weight as p3*X
00042     {
00043       //weights[i] = P(2,0)*X.x() + P(2,1)*X.y() + P(2,2)*X.z() + P(2,3)*X.w();
00044       weights[i] = dot_product(P.get_row(2), X.get_vector()); // same as above
00045       row0 /= weights[i];
00046       row1 /= weights[i];
00047     }
00048     else
00049     {
00050       row0.normalize(); // normalise rows to provide better conditioning
00051       row1.normalize();
00052     }
00053 
00054     A.set_row(j, row0);
00055     A.set_row(j+1, row1);
00056   }
00057 
00058   if (method == 'e')
00059   {
00060     vnl_svd<double> svd(A);
00061     X.set(svd.nullvector());
00062   }
00063   else if (method == 'l')
00064   {
00065     vnl_vector<double> b =  -A.get_column(3);
00066     vnl_matrix<double> newA = A.extract(4, 3);
00067     vnl_svd<double> svd(newA);
00068     vnl_vector<double> b2 = svd.U().transpose() * b;
00069 
00070     vnl_vector<double> y(3);
00071     vnl_vector<double> D = svd.W().diagonal();
00072 
00073     for (int i = 0; i < 3; i++)
00074       y[i] = b2[i]/D[i];
00075 
00076     vnl_vector<double> tempX = svd.V()*y;
00077     X.set(tempX[0], tempX[1], tempX[2], 1.0);
00078   }
00079   else
00080   {
00081     vcl_cerr << "\nError: mvl_linear_backproject method must be 'e' or 'l'\n";
00082     vcl_exit(0);
00083   }
00084 
00085   return weights;
00086 }