contrib/rpl/rgrl/rgrl_trans_similarity.cxx
Go to the documentation of this file.
00001 #include "rgrl_trans_similarity.h"
00002 //:
00003 // \file
00004 // \author Amitha Perera
00005 // \date   Feb 2003
00006 
00007 #include <vcl_cassert.h>
00008 #include <vnl/vnl_fastops.h>
00009 #include <vnl/algo/vnl_svd.h>
00010 #include <rgrl/rgrl_util.h>
00011 
00012 rgrl_trans_similarity::
00013 rgrl_trans_similarity( unsigned int dimension )
00014   : A_( vnl_matrix<double>( dimension, dimension, vnl_matrix_identity ) ),
00015     trans_( vnl_vector<double>( dimension, 0.0 ) ),
00016     from_centre_( dimension, 0.0 )
00017 {
00018 }
00019 
00020 rgrl_trans_similarity::
00021 rgrl_trans_similarity( vnl_matrix<double> const& rot_and_scale,
00022                        vnl_vector<double> const& in_trans )
00023   : A_( rot_and_scale ),
00024     trans_( in_trans ),
00025     from_centre_( in_trans.size(), 0.0 )
00026 {
00027   assert ( A_.rows() == A_.cols() );
00028   assert ( A_.rows() == trans_.size() );
00029   // assert ( ( A_.rows() != 2 || covar_.rows() == 4 ) ); // 2d has 4 params
00030   // assert ( ( A_.rows() != 3 || covar_.rows() == 7 ) ); // 3d has 7 params
00031 }
00032 
00033 rgrl_trans_similarity::
00034 rgrl_trans_similarity( vnl_matrix<double> const& rot_and_scale,
00035                        vnl_vector<double> const& in_trans,
00036                        vnl_matrix<double> const& in_covar )
00037   : rgrl_transformation( in_covar ),
00038     A_( rot_and_scale ),
00039     trans_( in_trans ),
00040     from_centre_( in_trans.size(), 0.0 )
00041 {
00042   assert ( A_.rows() == A_.cols() );
00043   assert ( A_.rows() == trans_.size() );
00044   if ( is_covar_set() ) {
00045     assert ( covar_.rows() == covar_.cols() );
00046     assert ( ( A_.rows() != 2 || covar_.rows() == 4 ) ); // 2d has 4 params
00047     assert ( ( A_.rows() != 3 || covar_.rows() == 7 ) ); // 3d has 7 params
00048   }
00049 }
00050 
00051 rgrl_trans_similarity::
00052 rgrl_trans_similarity( vnl_matrix<double> const& in_A,
00053                        vnl_vector<double> const& in_trans,
00054                        vnl_matrix<double> const& in_covar,
00055                        vnl_vector<double> const& in_from_centre,
00056                        vnl_vector<double> const& in_to_centre )
00057   : rgrl_transformation( in_covar ),
00058     A_( in_A ),
00059     trans_( in_trans + in_to_centre ),
00060     from_centre_( in_from_centre )
00061 {
00062   assert ( A_.rows() == A_.cols() );
00063   assert ( A_.rows() == trans_.size() );
00064   assert ( from_centre_.size() == trans_.size() );
00065   if ( is_covar_set() ) {
00066     assert ( covar_.rows() == covar_.cols() );
00067     assert ( ( A_.rows() != 2 || covar_.rows() == 4 ) ); // 2d has 4 params
00068     assert ( ( A_.rows() != 3 || covar_.rows() == 7 ) ); // 3d has 7 params
00069   }
00070 }
00071 
00072 void
00073 rgrl_trans_similarity::
00074 map_loc( vnl_vector<double> const& from,
00075          vnl_vector<double>      & to   ) const
00076 {
00077   assert ( from.size() == A_.rows() );
00078   // for efficiency, rewrite the following as:
00079   // to = A_ * (from-from_centre_) + trans_;
00080   //
00081   vnl_fastops::Ab( to, A_, from-from_centre_ );
00082   to += trans_;
00083 }
00084 
00085 void
00086 rgrl_trans_similarity::
00087 map_dir( vnl_vector<double> const& from_loc,
00088          vnl_vector<double> const& from_dir,
00089          vnl_vector<double>      & to_dir    ) const
00090 {
00091   assert ( from_loc.size() == A_.cols() );
00092   assert ( from_dir.size() == A_.cols() );
00093   to_dir = A_ * from_dir;
00094   to_dir.normalize();
00095 }
00096 
00097 vnl_matrix<double>
00098 rgrl_trans_similarity::
00099 transfer_error_covar( vnl_vector<double> const& p  ) const
00100 {
00101   assert ( is_covar_set() );
00102   assert ( p.size() == 2);  // only deal with 2D for now
00103   assert ( A_.rows() == 2); // only deal with 2D for now
00104 
00105   vnl_matrix<double> temp( 2, 4, 0.0 );
00106   temp(0,0) = p[0]-from_centre_[0];
00107   temp(0,1) = from_centre_[1] - p[1];
00108   temp(0,2) = 1;
00109   temp(1,0) = p[1]-from_centre_[1];
00110   temp(1,1) = p[0] - from_centre_[0];
00111   temp(1,3) = 1;
00112 
00113   return temp * covar_ * temp.transpose();
00114 }
00115 
00116 vnl_matrix<double> const&
00117 rgrl_trans_similarity::
00118 A() const
00119 {
00120   return A_;
00121 }
00122 
00123 double
00124 rgrl_trans_similarity::
00125 scaling() const
00126 {
00127   assert( A_.rows() && A_.cols() );
00128   vnl_vector<double> tmp = A_.get_column(0);
00129   return tmp.magnitude();
00130 }
00131 
00132 vnl_vector<double>
00133 rgrl_trans_similarity::
00134 t() const
00135 {
00136   return trans_ - A_ * from_centre_;
00137 }
00138 
00139 void
00140 rgrl_trans_similarity::
00141 inv_map( const vnl_vector<double>& to,
00142          bool initialize_next,
00143          const vnl_vector<double>& to_delta,
00144          vnl_vector<double>& from,
00145          vnl_vector<double>& from_next_est) const
00146 {
00147   const double epsilon = 0.01;
00148   vnl_vector<double> to_est = this->map_location(from);
00149 
00150   // compute the inverse of the Jacobian, which is the A_^-1
00151   vnl_svd<double> svd( A_ );
00152   vnl_matrix<double> J_inv = svd.inverse();
00153 
00154   // update from to become true inv_map of to, based on A^-1 and (to - to_est)
00155   if (vnl_vector_ssd(to, to_est) > epsilon*epsilon) {
00156     from += J_inv * (to - to_est);
00157   }
00158   if ( initialize_next ) {
00159     from_next_est = from + (J_inv * to_delta);
00160   }
00161 }
00162 
00163 void
00164 rgrl_trans_similarity::
00165 inv_map( const vnl_vector<double>& to,
00166          vnl_vector<double>& from ) const
00167 {
00168   vnl_svd<double> svd( A_ );
00169   from = svd.inverse()*to - svd.inverse()*trans_ + from_centre_;
00170 }
00171 
00172 rgrl_transformation_sptr
00173 rgrl_trans_similarity::
00174 inverse_transform( ) const
00175 {
00176   vnl_svd<double> svd( A() );
00177   vnl_matrix<double> invA = svd.inverse();
00178   rgrl_transformation_sptr result =  new rgrl_trans_similarity( invA, -invA * t() );
00179 
00180   const unsigned m = scaling_factors_.size();
00181   if ( m > 0 ) {
00182     vnl_vector<double> scaling( m );
00183     for ( unsigned int i=0; i<m; ++i )
00184       scaling[i] = 1.0 / scaling_factors_[i];
00185     result->set_scaling_factors( scaling );
00186   }
00187 
00188   return result;
00189 }
00190 
00191 
00192 void
00193 rgrl_trans_similarity::
00194 jacobian_wrt_loc( vnl_matrix<double>& jac, vnl_vector<double> const& /*from_loc*/ ) const
00195 {
00196   jac = A_;
00197 }
00198 
00199 rgrl_transformation_sptr
00200 rgrl_trans_similarity::
00201 scale_by( double scale ) const
00202 {
00203   rgrl_transformation_sptr xform
00204     = new rgrl_trans_similarity( A_, trans_ * scale,
00205                                  covar_, from_centre_ * scale,
00206                                  vnl_vector<double>(from_centre_.size(), 0.0) );
00207   xform->set_scaling_factors( this->scaling_factors() );
00208   return xform;
00209 }
00210 
00211 void
00212 rgrl_trans_similarity::
00213 write( vcl_ostream& os ) const
00214 {
00215   // tag
00216   os << "SIMILARITY\n"
00217   // parameters
00218      << t().size() << vcl_endl
00219      << A_ << trans_ << ' ' << from_centre_ << vcl_endl;
00220 
00221   // parent
00222   rgrl_transformation::write( os );
00223 }
00224 
00225 bool
00226 rgrl_trans_similarity::
00227 read( vcl_istream& is )
00228 {
00229   int dim;
00230 
00231   // skip empty lines
00232   rgrl_util_skip_empty_lines( is );
00233 
00234   vcl_string str;
00235   vcl_getline( is, str );
00236 
00237   // The token should appear at the beginning of line
00238   if ( str.find( "SIMILARITY" ) != 0 ) {
00239     WarningMacro( "The tag is not SIMILARITY. reading is aborted.\n" );
00240     return false;
00241   }
00242 
00243   // input global xform
00244   dim=-1;
00245   is >> dim;
00246   if ( dim > 0 ) {
00247     A_.set_size( dim, dim );
00248     trans_.set_size( dim );
00249     from_centre_.set_size( dim );
00250     is >> A_ >> trans_ >> from_centre_;
00251   }
00252 
00253   // parent
00254   return is.good() && rgrl_transformation::read( is );
00255 }
00256 
00257 //: make a clone copy
00258 rgrl_transformation_sptr
00259 rgrl_trans_similarity::
00260 clone() const
00261 {
00262   return new rgrl_trans_similarity( *this );
00263 }