contrib/oxl/mvl/PMatrixComputeLinear.cxx
Go to the documentation of this file.
00001 // This is oxl/mvl/PMatrixComputeLinear.cxx
00002 #include "PMatrixComputeLinear.h"
00003 //:
00004 //  \file
00005 
00006 #include <vcl_vector.h>
00007 #include <vcl_cassert.h>
00008 #include <vnl/vnl_matrix.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 
00011 #include <mvl/PMatrix.h>
00012 
00013 //-----------------------------------------------------------------------------
00014 //
00015 //: Compute a projection matrix using linear least squares.
00016 // Input is a list of 3D-2D point correspondences.
00017 //
00018 // Return false if the calculation fails or there are fewer than six point
00019 // matches in the list.
00020 //
00021 // The algorithm finds the nullvector of the following design matrix, where
00022 // the 3d points $\vec X^i$ are projected into 2d points $\vec u^i$.
00023 // \f[
00024 // \left(
00025 // \begin{array}{ccc}
00026 // \vec X^1 u^1_3        & 0_{4}             & -\vec X^1 u^1_1 \cr
00027 // 0_4                   & \vec X^1 u^1_3    & -\vec X^1 u^1_2 \cr
00028 // \vdots                & \vdots & \vdots \cr
00029 // \vec X^n u^n_3        & 0_{4}             & -\vec X^n u^n_1 \cr
00030 // 0_4                   & \vec X^n u^n_3    & -\vec X^n u^n_2 \cr
00031 // \end{array}
00032 // \right)
00033 // \f]
00034 bool
00035 PMatrixComputeLinear::compute(vcl_vector<vgl_homg_point_2d<double> > const& points1,
00036                               vcl_vector<vgl_homg_point_3d<double> > const& points2,
00037                               PMatrix *P)
00038 {
00039   assert(P);
00040   assert(points1.size() >= 6);
00041   assert(points2.size() == points1.size());
00042 
00043   unsigned npts = points1.size();
00044   vnl_matrix<double> a_matrix(npts * 2, 12);
00045 
00046   for (unsigned i = 0; i < npts; i++) {
00047     vgl_homg_point_2d<double> const& u = points1[i];
00048     vgl_homg_point_3d<double> const& X = points2[i];
00049 
00050     unsigned row_index = i * 2;
00051     a_matrix(row_index,  0) =  X.x() * u.w();
00052     a_matrix(row_index,  1) =  X.y() * u.w();
00053     a_matrix(row_index,  2) =  X.z() * u.w();
00054     a_matrix(row_index,  3) =  X.w() * u.w();
00055     a_matrix(row_index,  4) =  0;
00056     a_matrix(row_index,  5) =  0;
00057     a_matrix(row_index,  6) =  0;
00058     a_matrix(row_index,  7) =  0;
00059     a_matrix(row_index,  8) = -X.x() * u.x();
00060     a_matrix(row_index,  9) = -X.y() * u.x();
00061     a_matrix(row_index, 10) = -X.z() * u.x();
00062     a_matrix(row_index, 11) = -X.w() * u.x();
00063 
00064     row_index = i * 2 + 1;
00065     a_matrix(row_index,  0) =  0;
00066     a_matrix(row_index,  1) =  0;
00067     a_matrix(row_index,  2) =  0;
00068     a_matrix(row_index,  3) =  0;
00069     a_matrix(row_index,  4) =  X.x() * u.w();
00070     a_matrix(row_index,  5) =  X.y() * u.w();
00071     a_matrix(row_index,  6) =  X.z() * u.w();
00072     a_matrix(row_index,  7) =  X.w() * u.w();
00073     a_matrix(row_index,  8) = -X.x() * u.y();
00074     a_matrix(row_index,  9) = -X.y() * u.y();
00075     a_matrix(row_index, 10) = -X.z() * u.y();
00076     a_matrix(row_index, 11) = -X.w() * u.y();
00077   }
00078 
00079   a_matrix.normalize_rows();
00080   vnl_svd<double> svd(a_matrix);
00081 
00082   P->set(svd.nullvector().data_block());
00083 
00084   return true;
00085 }
00086 
00087 bool
00088 PMatrixComputeLinear::compute (vcl_vector<HomgPoint2D> const& points1, vcl_vector<HomgPoint3D> const& points2, PMatrix *P)
00089 {
00090   assert(P);
00091   assert(points1.size() >= 6);
00092   assert(points2.size() == points1.size());
00093 
00094   unsigned npts = points1.size();
00095   vnl_matrix<double> a_matrix(npts * 2, 12);
00096 
00097   for (unsigned i = 0; i < npts; i++) {
00098     HomgPoint2D const& u = points1[i];
00099     HomgPoint3D const& X = points2[i];
00100 
00101     unsigned row_index = i * 2;
00102     a_matrix(row_index,  0) =  X.x() * u.w();
00103     a_matrix(row_index,  1) =  X.y() * u.w();
00104     a_matrix(row_index,  2) =  X.z() * u.w();
00105     a_matrix(row_index,  3) =  X.w() * u.w();
00106     a_matrix(row_index,  4) =  0;
00107     a_matrix(row_index,  5) =  0;
00108     a_matrix(row_index,  6) =  0;
00109     a_matrix(row_index,  7) =  0;
00110     a_matrix(row_index,  8) = -X.x() * u.x();
00111     a_matrix(row_index,  9) = -X.y() * u.x();
00112     a_matrix(row_index, 10) = -X.z() * u.x();
00113     a_matrix(row_index, 11) = -X.w() * u.x();
00114 
00115     row_index = i * 2 + 1;
00116     a_matrix(row_index,  0) =  0;
00117     a_matrix(row_index,  1) =  0;
00118     a_matrix(row_index,  2) =  0;
00119     a_matrix(row_index,  3) =  0;
00120     a_matrix(row_index,  4) =  X.x() * u.w();
00121     a_matrix(row_index,  5) =  X.y() * u.w();
00122     a_matrix(row_index,  6) =  X.z() * u.w();
00123     a_matrix(row_index,  7) =  X.w() * u.w();
00124     a_matrix(row_index,  8) = -X.x() * u.y();
00125     a_matrix(row_index,  9) = -X.y() * u.y();
00126     a_matrix(row_index, 10) = -X.z() * u.y();
00127     a_matrix(row_index, 11) = -X.w() * u.y();
00128   }
00129 
00130   a_matrix.normalize_rows();
00131   vnl_svd<double> svd(a_matrix);
00132 
00133   P->set(svd.nullvector().data_block());
00134 
00135   return true;
00136 }