core/vpgl/vpgl_rational_camera.h
Go to the documentation of this file.
00001 // This is core/vpgl/vpgl_rational_camera.h
00002 #ifndef vpgl_rational_camera_h_
00003 #define vpgl_rational_camera_h_
00004 //:
00005 // \file
00006 // \brief A camera model based on ratios of cubic polynomials
00007 // \author Joseph Mundy
00008 // \date Oct 2006
00009 //
00010 //
00011 //  A camera that projects 3-d world points according to ratios of
00012 //  cubic polynomials. That is,
00013 // \verbatim
00014 //           neu_u(X,Y,Z)      neu_v(X,Y,Z)
00015 //       u = ------------  v = ------------
00016 //           den_u(X,Y,Z)      den_v(X,Y,X)
00017 // \endverbatim
00018 //  where u is the image column index and v is the image row index.
00019 //
00020 //  neu_u(X,Y,Z),den_u(X,Y,Z), neu_v(X,Y,Z), den_v(X,Y,Z) are
00021 //  cubic polynomials in three variables and there are 20 coefficients each,
00022 //  e.g.,
00023 //
00024 //  R(X,Y,Z) = a300 x^3 + a210 x^2y + a201 x^2z + a200 x^2 + ... + a001z + a000
00025 //
00026 //  The normal ordering of multi-variate polynomial coefficients is as
00027 //  shown above, the highest powers in x followed by highest powers in y,
00028 //  followed by powers in z. The full monomial sequence is:
00029 //   0   1    2    3   4    5  6   7   8  9 10  11   12   13  14 15 16 17 18 19
00030 //  x^3 x^2y x^2z x^2 xy^2 xyz xy xz^2 xz x y^3 y^2z y^2 yz^2 yz y z^3 z^2 z 1
00031 //  The highest powers are in the lowest index of the coefficient vector.
00032 //
00033 //  Polynomial calculations are often ill-conditioned if the variables are not
00034 //  normalized. Common practice is to normalize all variables to the
00035 //  range [-1, 1]. This normalization requires 10 additional offset and scale
00036 //  parameters for a total of 90 parameters.
00037 //
00038 //  The scale and offset transformation is applied to (X,Y,Z)
00039 //  before applying the polynomial mapping. The resulting (u,v) is normalized
00040 //  and must be mapped back (un-normalized) to the image coordinate
00041 //  system to obtain the actual projection.
00042 //
00043 //  In order to facilitate the scale offset transformation process, a helper
00044 //  class, scale_offset, is defined to process the forward and reverse
00045 //  normalizations.
00046 //
00047 #include <vgl/vgl_fwd.h>
00048 #include <vcl_iostream.h>
00049 #include <vcl_vector.h>
00050 #include <vcl_string.h>
00051 #include <vnl/vnl_vector_fixed.h>
00052 #include <vnl/vnl_matrix_fixed.h>
00053 #include <vpgl/vpgl_camera.h>
00054 
00055 // Represent scale and offset transformations used in normalization
00056 //
00057 template <class T>
00058 class vpgl_scale_offset
00059 {
00060  public:
00061   vpgl_scale_offset() :
00062     scale_(1), offset_(0) {}
00063   vpgl_scale_offset(const T scale, const T offset) :
00064     scale_(scale), offset_(offset) {}
00065 
00066   //mutators/accessors
00067   void set_scale(const T scale) {scale_ = scale;}
00068   void set_offset(const T offset) {offset_ = offset;}
00069   T scale() const {return scale_;}
00070   T offset() const {return offset_;}
00071 
00072   // normalize a coordinate value
00073   T normalize(const T value) const
00074   {
00075     if (scale_==0)
00076       return 0;
00077     else
00078       return (value-offset_)/scale_;
00079   }
00080 
00081   // un-normalize a coordinate value
00082   T un_normalize(const T value) const
00083   {
00084     T temp = value*scale_;
00085     return temp + offset_;
00086   }
00087   //: Equality test
00088   inline bool operator==(vpgl_scale_offset<T> const &that) const
00089   { return this == &that ||
00090            (this->scale()==that.scale() &&
00091             this->offset() == that.offset() );
00092   }
00093  private:
00094   //members
00095   T scale_;
00096   T offset_;
00097 };
00098 
00099 //
00100 //--------------------=== rational camera ===---------------------------
00101 //
00102 template <class T>
00103 class vpgl_rational_camera : public vpgl_camera<T>
00104 {
00105  public:
00106   //: enumeration for indexing coordinates
00107   enum coor_index{X_INDX = 0, Y_INDX, Z_INDX, U_INDX, V_INDX};
00108   //: enumeration for indexing polynomials
00109   enum poly_index{NEU_U = 0, DEN_U, NEU_V, DEN_V};
00110 
00111   //: default constructor
00112   vpgl_rational_camera();
00113   //: Constructor from 4 coefficient vectors and 5 scale, offset pairs.
00114   vpgl_rational_camera(vcl_vector<T> const& neu_u,
00115                        vcl_vector<T> const& den_u,
00116                        vcl_vector<T> const& neu_v,
00117                        vcl_vector<T> const& den_v,
00118                        const T x_scale, const T x_off,
00119                        const T y_scale, const T y_off,
00120                        const T z_scale, const T z_off,
00121                        const T u_scale, const T u_off,
00122                        const T v_scale, const T v_off
00123                       );
00124 
00125   //: Constructor from 4 coefficient arrays and 5 scale, offset pairs.
00126   vpgl_rational_camera(const double*  neu_u,
00127                        const double* den_u,
00128                        const double* neu_v,
00129                        const double* den_v,
00130                        const T x_scale, const T x_off,
00131                        const T y_scale, const T y_off,
00132                        const T z_scale, const T z_off,
00133                        const T u_scale, const T u_off,
00134                        const T v_scale, const T v_off
00135                       );
00136 
00137 
00138   //: Constructor with everything wrapped up in an array and vector.
00139   vpgl_rational_camera(vcl_vector<vcl_vector<T> > const& rational_coeffs,
00140                        vcl_vector<vpgl_scale_offset<T> > const& scale_offsets);
00141 
00142   //: Constructor with a coefficient matrix
00143   vpgl_rational_camera(vnl_matrix_fixed<T, 4, 20> const& rational_coeffs,
00144                        vcl_vector<vpgl_scale_offset<T> > const& scale_offsets)
00145     : rational_coeffs_(rational_coeffs), scale_offsets_(scale_offsets) {}
00146 
00147   virtual ~vpgl_rational_camera() {}
00148 
00149   virtual vcl_string type_name() const { return "vpgl_rational_camera"; }
00150 
00151   //: Clone `this': creation of a new object and initialization
00152   //  See Prototype pattern
00153   virtual vpgl_rational_camera<T>* clone(void) const;
00154 
00155   //: Equality test
00156   inline bool operator==(vpgl_rational_camera<T> const &that) const
00157   { return this == &that ||
00158       ((this->coefficient_matrix()==that.coefficient_matrix())&&
00159        (this->scale_offsets() == that.scale_offsets()) );}
00160 
00161   // --- Mutators/Accessors ---
00162 
00163   //: set rational polynomial coefficients
00164   void set_coefficients(vcl_vector<vcl_vector<T> > const& rational_coeffs);
00165   void set_coefficients(vnl_matrix_fixed<T, 4, 20> const& rational_coeffs)
00166     {rational_coeffs_ = rational_coeffs;}
00167   //: set coordinate scale and offsets
00168   void set_scale_offsets(vcl_vector<vpgl_scale_offset<T> > const& scale_offsets);
00169   //: get the rational polynomial coefficients in a vnl matrix
00170   vnl_matrix_fixed<T, 4, 20> coefficient_matrix() const
00171     {return rational_coeffs_;}
00172   //: get the rational polynomial coefficients in a vcl array
00173   vcl_vector<vcl_vector<T> > coefficients() const;
00174   //: get the scale and offsets in a vector
00175   vcl_vector<vpgl_scale_offset<T> > scale_offsets() const
00176     {return scale_offsets_;}
00177   //:set a specific scale value
00178   void set_scale(const coor_index coor_index, const T scale)
00179     {scale_offsets_[coor_index].set_scale(scale);}
00180   //:set a specific scale value
00181   void set_offset(const coor_index coor_index, const T offset)
00182     {scale_offsets_[coor_index].set_offset(offset);}
00183   //: get a specific scale value
00184   T scale(const coor_index coor_index) const
00185     {return scale_offsets_[coor_index].scale();}
00186   //: get a specific offset value
00187   T offset(const coor_index coor_index) const
00188     {return scale_offsets_[coor_index].offset();}
00189   //: get a specific scale_offset
00190   vpgl_scale_offset<T> scl_off(const coor_index coor_index) const
00191     {return scale_offsets_[coor_index];}
00192 
00193         // --- Often useful for adjusting the camera ---
00194 
00195   //:set u-v translation offset
00196   void set_image_offset(const T u_off, const T v_off)
00197   { scale_offsets_[U_INDX].set_offset(u_off);
00198     scale_offsets_[V_INDX].set_offset(v_off); }
00199 
00200   //:get u-v translation offset
00201   void image_offset(T& u_off, T& v_off)
00202     {u_off = offset(U_INDX); v_off = offset(V_INDX);}
00203 
00204    //:set u-v scale
00205   void set_image_scale(const T u_scale, const T v_scale)
00206   { scale_offsets_[U_INDX].set_scale(u_scale);
00207     scale_offsets_[V_INDX].set_scale(v_scale); }
00208 
00209   //:get u-v  scale
00210   void image_scale(T& u_scale, T& v_scale)
00211     {u_scale = scale(U_INDX); v_scale = scale(V_INDX);}
00212   //: The generic camera interface. u represents image column, v image row.
00213   virtual void project(const T x, const T y, const T z, T& u, T& v) const;
00214 
00215         // --- Interface for vnl ---
00216 
00217   //: Project a world point onto the image
00218   virtual vnl_vector_fixed<T, 2> project(vnl_vector_fixed<T, 3> const& world_point) const;
00219 
00220         // --- Interface for vgl ---
00221 
00222   //: Project a world point onto the image
00223   virtual vgl_point_2d<T> project(vgl_point_3d<T> world_point) const;
00224 
00225   //: print the camera parameters
00226   virtual void print(vcl_ostream& s = vcl_cout) const;
00227 
00228   virtual bool save(vcl_string cam_path);
00229 
00230 
00231  protected:
00232   // utilities
00233   vnl_vector_fixed<T, 20> power_vector(const T x, const T y, const T z) const;
00234   // members
00235   vnl_matrix_fixed<T, 4, 20> rational_coeffs_;
00236   vcl_vector<vpgl_scale_offset<T> > scale_offsets_;
00237 };
00238 
00239 //: Write to stream
00240 // \relatesalso vpgl_rational_camera
00241 template <class T>
00242 vcl_ostream& operator<<(vcl_ostream& s, const vpgl_rational_camera<T>& p);
00243 
00244 //: Read from stream
00245 // \relatesalso vpgl_rational_camera
00246 template <class T>
00247 vcl_istream& operator>>(vcl_istream& is, vpgl_rational_camera<T>& p);
00248 
00249 //: Creates a rational camera from a file
00250 // \relatesalso vpgl_rational_camera
00251 template <class T>
00252 vpgl_rational_camera<T>* read_rational_camera(vcl_string cam_path);
00253 
00254 //: Creates a rational camera from a stream
00255 // \relatesalso vpgl_rational_camera
00256 template <class T>
00257 vpgl_rational_camera<T>* read_rational_camera(vcl_istream& istr);
00258 
00259 #define VPGL_RATIONAL_CAMERA_INSTANTIATE(T) extern "please include vgl/vpgl_rational_camera.txx first"
00260 
00261 
00262 #endif // vpgl_rational_camera_h_