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