contrib/mul/m23d/m23d_correction_matrix_error.cxx
Go to the documentation of this file.
00001 #include "m23d_correction_matrix_error.h"
00002 //:
00003 // \file
00004 // \author Tim Cootes
00005 // \brief Error term for calculation of correction to projective matrix
00006 
00007 #include <mbl/mbl_matxvec.h>
00008 #include <vcl_cassert.h>
00009 
00010 m23d_correction_matrix_error::m23d_correction_matrix_error(const vnl_matrix<double>& A,
00011                               const vnl_vector<double>& rhs,
00012                               unsigned n_modes,
00013                               unsigned k)
00014   : vnl_least_squares_function(9*(n_modes+1),A.rows(),use_gradient),
00015     A_(A),rhs_(rhs),n_modes_(n_modes),k_(k)
00016 {
00017 #ifndef NDEBUG
00018   unsigned t = 3*(n_modes+1);
00019   assert(A.cols() == (t*(t+1))/2);
00020 #endif
00021   q_.set_size(A.cols());
00022 }
00023 
00024 //: Compute q from supplied g
00025 //  g1==g2 for full q, g2 = (0 0 ..1 ...0) when computing derivatives
00026 //  q is set to the unique elements of G1.G2', where G1 and G2 are the
00027 //  3*(m+1) x 3 matrices formed from the elements of g1 and g2.
00028 void m23d_correction_matrix_error::compute_q(const vnl_vector<double>& g1,
00029                  const vnl_vector<double>& g2,
00030                  vnl_vector<double>& q)
00031 {
00032   unsigned t = 3*(n_modes_+1);
00033   unsigned k=0;
00034   const double* r1=g1.data_block();
00035   for (unsigned i=0;i<t;++i,r1+=3)
00036   {
00037     const double* r2=g2.data_block();
00038     for (unsigned j=0;j<=i;++j,++k,r2+=3)
00039        q[k]= r1[0]*r2[0] + r1[1]*r2[1] +r1[2]*r2[2];
00040   }
00041 }
00042 
00043 
00044 //: The main function.
00045 //  Given g, returns error vector fx=(Aq-rhs), where vector q are the
00046 //  unique elements of the symmetric matrix Q=GG', G being the
00047 //  3(m+1) x 3 matrix formed from the elements of the supplied
00048 //  vector g.
00049 void m23d_correction_matrix_error::f(vnl_vector<double> const& g,
00050                                      vnl_vector<double>& fx)
00051 {
00052   assert(g.size() == 9*(n_modes_+1));
00053   compute_q(g,g,q_);
00054   mbl_matxvec_prod_mv(A_,q_,fx);
00055   fx-=rhs_;
00056 }
00057 
00058 //: Calculate the Jacobian, given the parameter vector g.
00059 void m23d_correction_matrix_error::gradf(vnl_vector<double> const& g,
00060                                          vnl_matrix<double>& jacobian)
00061 {
00062   unsigned ng = 9*(n_modes_+1);
00063   assert(g.size() == ng);
00064   jacobian.set_size(get_number_of_residuals(),ng);
00065   r_.set_size(get_number_of_residuals());
00066 
00067   vnl_vector<double> g1(ng,0.0),q1(A_.cols());
00068   for (unsigned j=0;j<ng;++j)
00069   {
00070     g1[j]=1.0;
00071     compute_q(g,g1,q_);
00072     compute_q(g1,g,q1);
00073     q_+=q1;
00074     mbl_matxvec_prod_mv(A_,q_,r_);
00075     jacobian.set_column(j,r_);
00076     g1[j]=0.0;  // Reset to zero
00077   }
00078 }