Go to the documentation of this file.00001
00002 #include "mbl_correspond_points.h"
00003
00004
00005
00006
00007
00008 #include <vcl_cmath.h>
00009 #include <vgl/vgl_distance.h>
00010 #include <vnl/vnl_math.h>
00011 #include <vnl/algo/vnl_symmetric_eigensystem.h>
00012 #include <vcl_algorithm.h>
00013
00014
00015
00016
00017
00018 mbl_correspond_points::mbl_correspond_points()
00019 {
00020 }
00021
00022
00023 unsigned mbl_correspond_points::closest_row(const vnl_matrix<double>& H1,
00024 const vnl_matrix<double>& H2,
00025 unsigned i1)
00026 {
00027 unsigned nc = vcl_min(H1.cols(),H2.cols());
00028 unsigned best_i = 0;
00029 double best_d2 = -1.0;
00030 const double* h1 = &H1(i1,0);
00031 for (unsigned i=0;i<H2.rows();++i)
00032 {
00033 const double* h2 = &H2(i,0);
00034 double sum=0.0;
00035 for (unsigned j=0;j<nc;++j)
00036 {
00037 double d = h1[j]-h2[j];
00038 sum += d*d;
00039 }
00040 if (best_d2 < 0 || sum<best_d2)
00041 {
00042 best_d2=sum;
00043 best_i = i;
00044 }
00045 }
00046
00047 return best_i;
00048 }
00049
00050
00051 void mbl_correspond_points::fix_eigenvectors(vnl_matrix<double>& P)
00052 {
00053 for (unsigned j=0;j<P.cols();++j)
00054 {
00055 vnl_vector<double> p = P.get_column(j);
00056 if (p.sum()<0) { p*=-1.0; P.set_column(j,p); }
00057 }
00058 }
00059
00060
00061
00062
00063
00064 void mbl_correspond_points::correspond(const vcl_vector<vgl_point_2d<double> >& points1,
00065 const vcl_vector<vgl_point_2d<double> >& points2,
00066 vcl_vector<unsigned>& matches, double sigma)
00067 {
00068 unsigned n1 = points1.size();
00069 unsigned n2 = points2.size();
00070
00071 vnl_matrix<double> H1(n1,n1),H2(n2,n2);
00072 proximity_by_tanh(points1,H1,sigma);
00073 proximity_by_tanh(points2,H2,sigma);
00074
00075
00076
00077 vnl_matrix<double> P1(n1,n1),P2(n2,n2);
00078 evals1_.set_size(n1);
00079 evals2_.set_size(n2);
00080 vnl_symmetric_eigensystem_compute(H1,P1,evals1_);
00081 vnl_symmetric_eigensystem_compute(H2,P2,evals2_);
00082
00083
00084 P1.fliplr(); evals1_.flip();
00085 P2.fliplr(); evals2_.flip();
00086
00087
00088
00089 fix_eigenvectors(P1);
00090 fix_eigenvectors(P2);
00091
00092
00093
00094 matches.resize(n1);
00095 for (unsigned i=0;i<n1;++i)
00096 matches[i] = closest_row(P1,P2,i);
00097 }
00098
00099
00100
00101
00102 void mbl_correspond_points::proximity_by_tanh(const vcl_vector<vgl_point_2d<double> >& points,
00103 vnl_matrix<double>& H, double sigma)
00104 {
00105 const unsigned n = points.size();
00106 const vgl_point_2d<double> *p = &points[0];
00107 H.set_size(n,n);
00108
00109 const double k1 = 2.0/vnl_math::pi;
00110 const double k2 = vnl_math::pi/sigma;
00111
00112 for (unsigned i=0;i<n;++i)
00113 {
00114 H(i,i)=0.0;
00115 for (unsigned j=i+1;j<n;++j)
00116 {
00117 double d = vgl_distance(p[i],p[j]);
00118 H(i,j) = H(j,i) = k1*vcl_tanh(k2*d)/d;
00119 }
00120 }
00121 }