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