contrib/oxl/mvl/FMatrixComputeRobust.cxx
Go to the documentation of this file.
00001 #include "FMatrixComputeRobust.h"
00002 //:
00003 // \file
00004 #include <mvl/Probability.h>
00005 #include <mvl/HomgNorm2D.h>
00006 #include <mvl/HomgOperator2D.h>
00007 #include <mvl/HomgInterestPointSet.h>
00008 #include <mvl/FMatrixCompute7Point.h>
00009 #include <vnl/vnl_double_2.h>
00010 #include <vnl/vnl_double_3x3.h>
00011 #include <vcl_iostream.h>
00012 #include <vcl_cmath.h>
00013 
00014 FMatrixComputeRobust::FMatrixComputeRobust() {}
00015 
00016 FMatrixComputeRobust::~FMatrixComputeRobust() {}
00017 //-----------------------------------------------------------------------------
00018 //
00019 //: Compute a robust fundamental matrix.
00020 //
00021 // \returns false if the calculation fails.
00022 //
00023 //-----------------------------------------------------------------------------
00024 bool FMatrixComputeRobust::compute(PairMatchSetCorner& matches, FMatrix *F)
00025 {
00026   inliers_.resize(0);
00027   residuals_.resize(0);
00028 
00029   // Copy matching points from matchset.
00030   // Set up some initial variables
00031   HomgInterestPointSet const* points1 = matches.get_corners1();
00032   HomgInterestPointSet const* points2 = matches.get_corners2();
00033   vcl_vector<HomgPoint2D> point1_store, point2_store;
00034   vcl_vector<int> point1_int, point2_int;
00035   matches.extract_matches(point1_store, point1_int, point2_store, point2_int);
00036   data_size_ = matches.count();
00037   vcl_vector<HomgPoint2D> point1_image(data_size_), point2_image(data_size_);
00038 
00039   // Store the image points
00040   for (int a = 0; a < data_size_; a++) {
00041     vnl_double_2 temp1;
00042     temp1 = points1->get_2d(point1_int[a]);
00043     point1_image[a] = HomgPoint2D(temp1[0], temp1[1], 1.0);
00044   }
00045 
00046   for (int a = 0; a < data_size_; a++) {
00047     vnl_double_2 temp2;
00048     temp2 = points2->get_2d(point2_int[a]);
00049     point2_image[a] = HomgPoint2D(temp2[0], temp2[1], 1.0);
00050   }
00051 
00052   FMatrix Fs;
00053   double Ds = 1e+10;
00054   int count = 0;
00055   vcl_vector<bool> inlier_list(data_size_, false);
00056   vcl_vector<double> residualsF(data_size_, 100.0);
00057 
00058   // 150 random samples from the points set
00059   for (int i = 0; i < 100; i++) {
00060     vcl_vector<int> index(7);
00061 
00062     // Take the minimum sample of seven points for the F Matrix calculation
00063     index = Monte_Carlo(point1_store, point1_int,  8, 7);
00064     vcl_vector<HomgPoint2D> seven1(7);
00065     vcl_vector<HomgPoint2D> seven2(7);
00066     for (int j = 0; j < 7; j++) {
00067       vnl_double_2 t1 = points1->get_2d(index[j]);
00068       seven1[j] = HomgPoint2D(t1[0], t1[1], 1.0);
00069       int other = matches.get_match_12(index[j]);
00070       vnl_double_2 t2 = points2->get_2d(other);
00071       seven2[j] = HomgPoint2D(t2[0], t2[1], 1.0);
00072     }
00073 
00074     // Set up a new FMatrix 7 point Computor
00075     // Note the conditioning and de-conditioning is done internally
00076     FMatrixCompute7Point Computor(true, rank2_truncate_);
00077 
00078     // Compute F
00079     vcl_vector<FMatrix*> F_temp;
00080     if (!Computor.compute(seven1, seven2, F_temp))
00081       vcl_cerr << "Seven point failure\n";
00082 
00083     for (unsigned int k = 0; k < F_temp.size(); k++) {
00084       int temp_count = 0;
00085       vcl_vector<bool> list(data_size_);
00086       vcl_vector<double> residuals = calculate_residuals(point1_image, point2_image, F_temp[k]);
00087       double term_error = calculate_term(residuals, list, temp_count);
00088       if (term_error < Ds) {
00089         Fs = *F_temp[k];
00090         Ds = term_error;
00091         basis_ = index;
00092         inlier_list = list;
00093         residualsF = residuals;
00094         count = temp_count;
00095       }
00096     }
00097 
00098     for (unsigned int k = 0; k < F_temp.size(); k++)
00099       delete F_temp[k];
00100   }
00101   vcl_cerr << "Final Figures...\n"
00102            << "Ds : " << Ds << '\n';
00103   vnl_double_3x3 sample = Fs.get_matrix();
00104   HomgPoint2D one, two;
00105   Fs.get_epipoles(&one, &two);
00106   vnl_double_2 o = one.get_double2();
00107   vnl_double_2 t = two.get_double2();
00108   HomgPoint2D c1(o[0], o[1], 1.0);
00109   HomgPoint2D c2(t[0], t[1], 1.0);
00110   vcl_cerr << "Epipole 1 : " << c1 << " Epipole 2 : " << c2 << "\n\n";
00111   epipole1_ = c1;
00112   epipole2_ = c2;
00113   sample /= sample.get(2, 2);
00114   vcl_cerr << "FMatrix : " << sample << '\n';
00115   F->set(Fs.get_matrix());
00116 
00117   int inlier_count = count;
00118   double std_in = 0.0;
00119 
00120   for (int k = 0; k < data_size_; k++) {
00121     if (inlier_list[k]) {
00122       std_in += residualsF[k];
00123     }
00124   }
00125   std_in /= inlier_count;
00126   std_in = vcl_sqrt(std_in);
00127 
00128   // Update the inliers in the PairMatchSet object
00129   matches.set(inlier_list, point1_int, point2_int);
00130 #if 0
00131   for (int z=0, k=0; z < inlier_list.size(); z++)
00132     if (inlier_list[z]) {
00133       vcl_cerr << "residualsF[" << z << "] : " << residualsF[z] << '\n';
00134                << k++ << '\n';
00135     }
00136 #endif
00137   inliers_ = inlier_list;
00138   residuals_ = residualsF;
00139   vcl_cerr << "Inlier -\n"
00140            << "         std : " << std_in << '\n'
00141            << "         " << inlier_count << '/' << data_size_ << '\n';
00142   return true;
00143 }
00144 
00145 //: Calculate all the residuals for a given relation
00146 vcl_vector<double> FMatrixComputeRobust::calculate_residuals(vcl_vector<vgl_homg_point_2d<double> >& one,
00147                                                              vcl_vector<vgl_homg_point_2d<double> >& two,
00148                                                              FMatrix* F)
00149 {
00150   vcl_vector<double> ret(data_size_);
00151   for (int i = 0; i < data_size_; i++) {
00152     double val = calculate_residual(one[i], two[i], F);
00153       ret[i] = val;
00154   }
00155   return ret;
00156 }
00157 
00158 //: Calculate all the residuals for a given relation
00159 vcl_vector<double> FMatrixComputeRobust::calculate_residuals(vcl_vector<HomgPoint2D>& one,
00160                                                              vcl_vector<HomgPoint2D>& two,
00161                                                              FMatrix* F)
00162 {
00163   vcl_vector<double> ret(data_size_);
00164   for (int i = 0; i < data_size_; i++) {
00165     double val = calculate_residual(one[i], two[i], F);
00166       ret[i] = val;
00167   }
00168   return ret;
00169 }
00170 
00171 //: Find the standard deviation of the residuals
00172 double FMatrixComputeRobust::stdev(vcl_vector<double>& residuals)
00173 {
00174   double ret = 0.0;
00175   for (int i = 0; i < data_size_; i++)
00176     ret += residuals[i];
00177 
00178   ret /= residuals.size();
00179   ret = vcl_sqrt(ret);
00180   return ret;
00181 }
00182 
00183 //:
00184 // \todo not yet implemented
00185 double FMatrixComputeRobust::calculate_term(vcl_vector<double>& /*residuals*/,
00186                                             vcl_vector<bool>& /*inlier_list*/,
00187                                             int& /*count*/)
00188 {
00189   vcl_cerr << "FMatrixComputeRobust::calculate_term() not yet implemented\n";
00190   return 10000.0;
00191 }
00192 
00193 //:
00194 // \todo not yet implemented
00195 double FMatrixComputeRobust::calculate_residual(vgl_homg_point_2d<double>& /*one*/,
00196                                                 vgl_homg_point_2d<double>& /*two*/,
00197                                                 FMatrix* /*F*/)
00198 {
00199   vcl_cerr << "FMatrixComputeRobust::calculate_residual() not yet implemented\n";
00200   return 100.0;
00201 }
00202 
00203 //:
00204 // \todo not yet implemented
00205 double FMatrixComputeRobust::calculate_residual(HomgPoint2D& /*one*/,
00206                                                 HomgPoint2D& /*two*/,
00207                                                 FMatrix* /*F*/)
00208 {
00209   vcl_cerr << "FMatrixComputeRobust::calculate_residual() not yet implemented\n";
00210   return 100.0;
00211 }