contrib/mul/m23d/m23d_select_basis_views.cxx
Go to the documentation of this file.
00001 #include "m23d_select_basis_views.h"
00002 //:
00003 // \file
00004 // \author Tim Cootes
00005 // \brief Select a subset most suitable for use as a basis set
00006 
00007 #include <mbl/mbl_random_n_from_m.h>
00008 #include <vnl/algo/vnl_svd.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_cstdlib.h>  // abort()
00011 #include <vcl_algorithm.h>  // vcl_sort
00012 
00013 //: Select a subset most suitable for use as a basis set
00014 //  Data matrix is 2ns x np (ns= number of samples, np = number of points)
00015 //  Each two rows gives the points in a single view.
00016 //  This returns a list of point indices for views which have most
00017 //  independent points, and are thus suitable for defining the basis.
00018 vcl_vector<unsigned> m23d_select_basis_views(const vnl_matrix<double>& P2D,
00019                                         unsigned n_modes,
00020                                         unsigned n_tries)
00021 {
00022   unsigned ns = P2D.rows()/2;
00023 
00024   // Initialise with first (n_modes+1) views
00025   vcl_vector<unsigned> s(n_modes+1),best_s(n_modes+1);
00026   for (unsigned i=0;i<=n_modes;++i) best_s[i]=i;
00027   double best_v = m23d_evaluate_basis(P2D,best_s);
00028   vcl_cout<<"Quality of first basis: "<<best_v<<vcl_endl;
00029 
00030   // Now generate random subsets and select the best
00031   mbl_random_n_from_m n_from_m;
00032   vcl_vector<unsigned> s1(n_modes);
00033   s[0]=0;  // Always include the first example
00034   for (unsigned i=0;i<n_tries;++i)
00035   {
00036     n_from_m.choose_n_from_m(s1,n_modes,ns-1);
00037     for (unsigned j=0;j<n_modes;++j) s[j+1]=s1[j]+1;
00038 
00039     double v = m23d_evaluate_basis(P2D,s);
00040 
00041     if (v>best_v)
00042     {
00043       best_v=v;
00044       best_s=s;
00045     }
00046   }
00047 
00048   vcl_sort(best_s.begin(),best_s.end());
00049   vcl_cout<<"Quality of selected basis: "<<best_v<<vcl_endl
00050           <<"Selected basis: [ ";
00051   for (unsigned i=0;i<best_s.size();++i)
00052     vcl_cout<<best_s[i]<<' ';
00053   vcl_cout<<']'<<vcl_endl;
00054 
00055   return best_s;
00056 }
00057 
00058 //: Evaluate quality of a basis set
00059 //  Data matrix is 2ns x np (ns= number of samples, np = number of points)
00060 //  Each two rows gives the points in a single view.
00061 //  Form a basis from the pairs of rows defined by selected, and compute
00062 //  a measure of how independent the rows are.
00063 double m23d_evaluate_basis(const vnl_matrix<double>& P2D,
00064                            const vcl_vector<unsigned>& selected)
00065 {
00066   unsigned np = P2D.columns();
00067   unsigned ns = P2D.rows()/2;
00068   unsigned n = selected.size();
00069   vnl_matrix<double> M(2*n,np);
00070   for (unsigned i=0;i<n;++i)
00071   {
00072     if (selected[i]>=ns)
00073     {
00074       vcl_cerr<<"m23d_evaluate_basis selected rows out of range."<<vcl_endl;
00075       vcl_abort();
00076     }
00077 
00078     // Copy selected pair of rows into M
00079     M.update(P2D.extract(2,np,2*selected[i],0),2*i,0);
00080   }
00081 
00082   vnl_svd<double> svd(M);
00083   return svd.W(2*n-1)/svd.W(0);  // Smallest singular value/largest SV
00084 }
00085