contrib/gel/mrc/vpgl/vpgl_calibration_matrix.txx
Go to the documentation of this file.
00001 // This is gel/mrc/vpgl/vpgl_calibration_matrix.txx
00002 #ifndef vpgl_calibration_matrix_txx_
00003 #define vpgl_calibration_matrix_txx_
00004 //:
00005 // \file
00006 
00007 #include "vpgl_calibration_matrix.h"
00008 
00009 #include <vgl/vgl_point_2d.h>
00010 #include <vgl/io/vgl_io_point_2d.h>
00011 #include <vnl/algo/vnl_svd.h>
00012 #include <vcl_cassert.h>
00013 
00014 //--------------------------------------
00015 template <class T>
00016 vpgl_calibration_matrix<T>::vpgl_calibration_matrix() :
00017   focal_length_( (T)1 ),
00018   principal_point_( vgl_point_2d<T>( (T)0, (T)0 ) ),
00019   x_scale_( (T)1 ),
00020   y_scale_( (T)1 ),
00021   skew_( (T)0 )
00022 {
00023 }
00024 
00025 
00026 //--------------------------------------
00027 template <class T>
00028 vpgl_calibration_matrix<T>::vpgl_calibration_matrix(
00029     T focal_length, const vgl_point_2d<T>& principal_point, T x_scale, T y_scale, T skew ) :
00030   focal_length_( focal_length ),
00031   principal_point_( principal_point ),
00032   x_scale_( x_scale ),
00033   y_scale_( y_scale ),
00034   skew_( skew )
00035 {
00036   // Make sure the inputs are valid.
00037   assert( focal_length != 0 );
00038   assert( x_scale > 0 );
00039   assert( y_scale > 0 );
00040 }
00041 
00042 
00043 //--------------------------------------
00044 template <class T>
00045 vpgl_calibration_matrix<T>::vpgl_calibration_matrix( const vnl_matrix_fixed<T,3,3>& K )
00046 {
00047   // Put the supplied matrix into canonical form and check that it could be a
00048   // calibration matrix.
00049   assert( K(2,2) != (T)0 && K(1,0) == (T)0 && K(2,0) == (T)0 && K(2,1) == (T)0 );
00050   double scale_factor = (T)1;
00051   if ( K(2,2) != (T)1 ) scale_factor = ((T)1)/K(2,2);
00052 
00053   focal_length_ = (T)1;
00054   x_scale_ = scale_factor*K(0,0);
00055   y_scale_ = scale_factor*K(1,1);
00056   skew_ = scale_factor*K(0,1);
00057   principal_point_.set( scale_factor*K(0,2), scale_factor*K(1,2) );
00058 
00059   assert( ( x_scale_ > 0 && y_scale_ > 0 ) || ( x_scale_ < 0 && y_scale_ < 0 ) );
00060 }
00061 
00062 
00063 //--------------------------------------
00064 template <class T>
00065 vnl_matrix_fixed<T,3,3> vpgl_calibration_matrix<T>::get_matrix() const
00066 {
00067   // Construct the matrix as in H&Z.
00068   vnl_matrix_fixed<T,3,3> K( (T)0 );
00069   K(0,0) = focal_length_*x_scale_;
00070   K(1,1) = focal_length_*y_scale_;
00071   K(2,2) = (T)1;
00072   K(0,2) = principal_point_.x();
00073   K(1,2) = principal_point_.y();
00074   K(0,1) = skew_;
00075   return K;
00076 }
00077 
00078 
00079 //--------------------------------------
00080 template <class T>
00081 void vpgl_calibration_matrix<T>::set_focal_length( T new_focal_length )
00082 {
00083   assert( new_focal_length != (T)0 );
00084   focal_length_ = new_focal_length;
00085 }
00086 
00087 
00088 //--------------------------------------
00089 template <class T>
00090 void vpgl_calibration_matrix<T>::set_principal_point(
00091   const vgl_point_2d<T>& new_principal_point )
00092 {
00093   assert( !new_principal_point.ideal() );
00094   principal_point_ = new_principal_point;
00095 }
00096 
00097 
00098 //--------------------------------------
00099 template <class T>
00100 void vpgl_calibration_matrix<T>::set_x_scale( T new_x_scale )
00101 {
00102   assert( new_x_scale > 0 );
00103   x_scale_ = new_x_scale;
00104 }
00105 
00106 
00107 //--------------------------------------
00108 template <class T>
00109 void vpgl_calibration_matrix<T>::set_y_scale( T new_y_scale )
00110 {
00111   assert( new_y_scale > 0 );
00112   y_scale_ = new_y_scale;
00113 }
00114 
00115 
00116 //--------------------------------------
00117 template <class T>
00118 void vpgl_calibration_matrix<T>::set_skew( T new_skew )
00119 {
00120   skew_ = new_skew;
00121 }
00122 
00123 //: Equality test
00124 template <class T> bool vpgl_calibration_matrix<T>::
00125 operator==(vpgl_calibration_matrix<T> const &that) const
00126 {
00127   if (this == &that) // same object => equal.
00128     return true;
00129 
00130   return
00131     this->focal_length_ == that.focal_length_ &&
00132     this->principal_point_ == that.principal_point_ &&
00133     this->x_scale_ == that.x_scale_ && this->y_scale_ == that.y_scale_ &&
00134     this->skew_ == that.skew_;
00135 }
00136 
00137 //: Map from image to focal plane.
00138 // (Later may need to cache the svd for efficiency)
00139 template <class T>
00140 vgl_point_2d<T> vpgl_calibration_matrix<T>::
00141 map_to_focal_plane(vgl_point_2d<T> const& p_image) const
00142 {
00143   vnl_vector<T> p(3);
00144   p[0]=p_image.x();   p[1]=p_image.y();   p[2]=1;
00145   vnl_svd<T> svd(this->get_matrix());
00146   vnl_matrix<T> Kinv = svd.inverse();
00147   vnl_vector<T> pf = Kinv*p;
00148   return vgl_point_2d<T>(pf[0]/pf[2], pf[1]/pf[2]);
00149 }
00150 
00151 template <class T>
00152 vgl_point_2d<T> vpgl_calibration_matrix<T>::
00153 map_to_image(vgl_point_2d<T> const& p_focal_plane) const
00154 {
00155   vnl_vector<T> p(3);
00156   p[0]=p_focal_plane.x();   p[1]=p_focal_plane.y();   p[2]=1;
00157   vnl_matrix_fixed<T,3,3> K = this->get_matrix();
00158   vnl_vector<T> pf = K*p;
00159   return vgl_point_2d<T>(pf[0]/pf[2], pf[1]/pf[2]);
00160 }
00161 
00162 
00163 // I/O :------------------------------------------------
00164 
00165 //-------------------------------
00166 template <class T> void vpgl_calibration_matrix<T>::
00167 b_read(vsl_b_istream &is)
00168 {
00169   if (!is) return;
00170 
00171   short ver;
00172   vsl_b_read(is, ver);
00173   switch (ver)
00174   {
00175    case 1:
00176      vsl_b_read(is, focal_length_);
00177      vsl_b_read(is, principal_point_);
00178      vsl_b_read(is, x_scale_);
00179      vsl_b_read(is, y_scale_);
00180      vsl_b_read(is, skew_);
00181     break;
00182    default:
00183     vcl_cerr << "I/O ERROR: vpgl_calibration_matrix::b_read(vsl_b_istream&)\n"
00184              << "           Unknown version number "<< ver << '\n';
00185     is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00186     return;
00187   }
00188 }
00189 
00190 //-------------------------------
00191 //: Binary save self to stream.
00192 // \remark cached_svd_ not written
00193 template <class T> void vpgl_calibration_matrix<T>::
00194 b_write(vsl_b_ostream &os) const
00195 {
00196   vsl_b_write(os, this->version());
00197   vsl_b_write(os, focal_length_);
00198   vsl_b_write(os, principal_point_);
00199   vsl_b_write(os, x_scale_);
00200   vsl_b_write(os, y_scale_);
00201   vsl_b_write(os, skew_);
00202 }
00203 
00204 //: Binary save
00205 template <class T> void
00206 vsl_b_write(vsl_b_ostream &os, const vpgl_calibration_matrix<T> * p)
00207 {
00208   if (p==0) {
00209     vsl_b_write(os, false); // Indicate null pointer stored
00210   }
00211   else{
00212     vsl_b_write(os,true); // Indicate non-null pointer stored
00213     p->b_write(os);
00214   }
00215 }
00216 
00217 
00218 //: Binary load
00219 template <class T> void
00220 vsl_b_read(vsl_b_istream &is, vpgl_calibration_matrix<T>* &p)
00221 {
00222   delete p;
00223   bool not_null_ptr;
00224   vsl_b_read(is, not_null_ptr);
00225   if (not_null_ptr) {
00226     p = new vpgl_calibration_matrix<T>();
00227     p->b_read(is);
00228   }
00229   else
00230     p = 0;
00231 }
00232 
00233 // Code for easy instantiation.
00234 #undef vpgl_CALIBRATION_MATRIX_INSTANTIATE
00235 #define vpgl_CALIBRATION_MATRIX_INSTANTIATE(T) \
00236 template class vpgl_calibration_matrix<T >
00237 
00238 #endif // vpgl_calibration_matrix_txx_