contrib/oxl/mvl/HMatrix2DComputeLinear.cxx
Go to the documentation of this file.
00001 // This is oxl/mvl/HMatrix2DComputeLinear.cxx
00002 #include "HMatrix2DComputeLinear.h"
00003 //:
00004 //  \file
00005 
00006 #include <vcl_vector.h>
00007 #include <vcl_iostream.h>
00008 #include <vcl_cassert.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 #include <mvl/HMatrix2D.h>
00011 #include <mvl/HomgMetric.h>
00012 #include <mvl/HomgNorm2D.h>
00013 
00014 //: Construct a HMatrix2DComputeLinear object.
00015 // The allow_ideal_points flag is described below.
00016 HMatrix2DComputeLinear::HMatrix2DComputeLinear(bool allow_ideal_points):
00017   allow_ideal_points_(allow_ideal_points)
00018 {
00019 }
00020 
00021 
00022 // Should provide:
00023 //   Points-only method
00024 //   Lines-only
00025 //   Points&lines
00026 //
00027 // FSM - this is now done by HMatrix2DComputeDesign.
00028 
00029 const int TM_UNKNOWNS_COUNT = 9;
00030 const double DEGENERACY_THRESHOLD = 0.00001;  // FSM. see below.
00031 
00032 //-----------------------------------------------------------------------------
00033 //
00034 //: Compute a plane-plane projectivity using linear least squares.
00035 // Returns false if the calculation fails or there are fewer than four point
00036 // matches in the list.  The algorithm finds the nullvector of the $2 n \times 9$ design
00037 // matrix:
00038 // \f[
00039 // \left(\begin{array}{ccccccccc}
00040 // 0 & 0 & 0 &        x_1 z_1' & y_1 z_1' & z_1 z_1' & -x_1 y_1' & -y_1 y_1' & -z_1 y_1' \cr
00041 // x_1 z_1' & y_1 z_1' & z_1 z_1' & 0 & 0 & 0 & -x_1 x_1' & -y_1 x_1' & -z_1 x_1' \cr
00042 // \multicolumn{9}{c}{\cdots} \cr
00043 // 0 & 0 & 0 &        x_n z_n' & y_n z_n' & z_n z_n' & -x_n y_n' & -y_n y_n' & -z_n y_n'\cr
00044 // x_n z_n' & y_n z_n' & z_n z_n' & 0 & 0 & 0 & -x_n x_n' & -y_n x_n' & -z_n x_n'
00045 // \end{array}\right)
00046 // \f]
00047 // If \t allow_ideal_points was set at construction, the $3 \times 9$ version which
00048 // allows for ideal points is used.
00049 
00050 bool
00051 HMatrix2DComputeLinear::compute_p(PointArray const& inpoints1,
00052                                   PointArray const& inpoints2,
00053                                   HMatrix2D *H)
00054 {
00055   // tm_tmatrix_linear_nonrobust_trivecs
00056   assert(inpoints1.size() == inpoints2.size());
00057   int n = inpoints1.size();
00058 
00059   int equ_count = n * (allow_ideal_points_ ? 3 : 2);
00060   if (n * 2 < TM_UNKNOWNS_COUNT - 1) {
00061     vcl_cerr << "HMatrix2DComputeLinear: Need at least 4 matches.\n";
00062     if (n == 0) vcl_cerr << "Could be vcl_vector setlength idiosyncrasies!\n";
00063     return false;
00064   }
00065 
00066   HomgNorm2D points1(inpoints1); if (points1.was_coincident()) return false; // FSM
00067   HomgNorm2D points2(inpoints2); if (points2.was_coincident()) return false; // FSM
00068 
00069   vnl_matrix<double> D(equ_count, TM_UNKNOWNS_COUNT);
00070 
00071   int row = 0;
00072   for (int i = 0; i < n; i++) {
00073     const HomgPoint2D& p1 = points1[i];
00074     const HomgPoint2D& p2 = points2[i];
00075 
00076     D(row, 0) =  p1.x() * p2.w();
00077     D(row, 1) =  p1.y() * p2.w();
00078     D(row, 2) =  p1.w() * p2.w();
00079     D(row, 3) = 0;
00080     D(row, 4) = 0;
00081     D(row, 5) = 0;
00082     D(row, 6) = -p1.x() * p2.x();
00083     D(row, 7) = -p1.y() * p2.x();
00084     D(row, 8) = -p1.w() * p2.x();
00085     ++row;
00086 
00087     D(row, 0) = 0;
00088     D(row, 1) = 0;
00089     D(row, 2) = 0;
00090     D(row, 3) =  p1.x() * p2.w();
00091     D(row, 4) =  p1.y() * p2.w();
00092     D(row, 5) =  p1.w() * p2.w();
00093     D(row, 6) = -p1.x() * p2.y();
00094     D(row, 7) = -p1.y() * p2.y();
00095     D(row, 8) = -p1.w() * p2.y();
00096     ++row;
00097 
00098     if (allow_ideal_points_) {
00099       D(row, 0) =  p1.x() * p2.y();
00100       D(row, 1) =  p1.y() * p2.y();
00101       D(row, 2) =  p1.w() * p2.y();
00102       D(row, 3) = -p1.x() * p2.x();
00103       D(row, 4) = -p1.y() * p2.x();
00104       D(row, 5) = -p1.w() * p2.x();
00105       D(row, 6) = 0;
00106       D(row, 7) = 0;
00107       D(row, 8) = 0;
00108       ++row;
00109     }
00110   }
00111 
00112   D.normalize_rows();
00113   vnl_svd<double> svd(D);
00114 
00115   //
00116   // FSM added :
00117   //
00118   if (svd.W(7)<DEGENERACY_THRESHOLD*svd.W(8)) {
00119     vcl_cerr << "HMatrix2DComputeLinear : design matrix has rank < 8" << vcl_endl;
00120     vcl_cerr << "HMatrix2DComputeLinear : probably due to degenerate point configuration" << vcl_endl;
00121     return false;
00122   }
00123   H->set(svd.nullvector().data_block());
00124 
00125   *H = HomgMetric::homg_to_image_H(*H, &points1, &points2);
00126 
00127   return true;
00128 }