contrib/gel/mrc/vpgl/vpgl_rational_camera.h
Go to the documentation of this file.
00001 // This is gel/mrc/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 appying 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 <vsl/vsl_binary_io.h>
00050 #include <vcl_vector.h>
00051 #include <vcl_string.h>
00052 #include <vnl/vnl_vector_fixed.h>
00053 #include <vnl/vnl_matrix_fixed.h>
00054 #include <vpgl/vpgl_camera.h>
00055 
00056 // Represent scale and offset transformations used in normalization
00057 //
00058 template <class T>
00059 class vpgl_scale_offset
00060 {
00061  public:
00062   vpgl_scale_offset() :
00063     scale_(1), offset_(0) {}
00064   vpgl_scale_offset(const T scale, const T offset) :
00065     scale_(scale), offset_(offset) {}
00066 
00067   //mutators/accessors
00068   void set_scale(const T scale) {scale_ = scale;}
00069   void set_offset(const T offset) {offset_ = offset;}
00070   T scale() const {return scale_;}
00071   T offset() const {return offset_;}
00072 
00073   // normalize a coordinate value
00074   T normalize(const T value) const
00075   {
00076     if (scale_==0)
00077       return 0;
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 
00088  private:
00089   //members
00090   T scale_;
00091   T offset_;
00092 };
00093 
00094 //
00095 //--------------------=== rational camera ===---------------------------
00096 //
00097 template <class T>
00098 class vpgl_rational_camera : public vpgl_camera<T>
00099 {
00100  public:
00101   //: enumeration for indexing coordinates
00102   enum coor_index{X_INDX = 0, Y_INDX, Z_INDX, U_INDX, V_INDX};
00103   //: enumeration for indexing polynomials
00104   enum poly_index{NEU_U = 0, DEN_U, NEU_V, DEN_V};
00105 
00106   //: default constructor
00107   vpgl_rational_camera();
00108   //: Constructor from 4 coefficient vectors and 5 scale, offset pairs.
00109   vpgl_rational_camera(vcl_vector<T> const& neu_u,
00110                        vcl_vector<T> const& den_u,
00111                        vcl_vector<T> const& neu_v,
00112                        vcl_vector<T> const& den_v,
00113                        const T x_scale, const T x_off,
00114                        const T y_scale, const T y_off,
00115                        const T z_scale, const T z_off,
00116                        const T u_scale, const T u_off,
00117                        const T v_scale, const T v_off
00118                       );
00119 
00120   //: Constructor from 4 coefficient arrays and 5 scale, offset pairs.
00121   vpgl_rational_camera(const double*  neu_u,
00122                        const double* den_u,
00123                        const double* neu_v,
00124                        const double* den_v,
00125                        const T x_scale, const T x_off,
00126                        const T y_scale, const T y_off,
00127                        const T z_scale, const T z_off,
00128                        const T u_scale, const T u_off,
00129                        const T v_scale, const T v_off
00130                       );
00131 
00132 
00133   //: Constructor with everything wrapped up in an array and vector.
00134   vpgl_rational_camera(vcl_vector<vcl_vector<T> > const& rational_coeffs,
00135                        vcl_vector<vpgl_scale_offset<T> > const& scale_offsets);
00136 
00137   //: Constructor with a coefficient matrix
00138   vpgl_rational_camera(vnl_matrix_fixed<T, 4, 20> const& rational_coeffs,
00139                        vcl_vector<vpgl_scale_offset<T> > const& scale_offsets)
00140     : rational_coeffs_(rational_coeffs), scale_offsets_(scale_offsets) {}
00141 
00142   virtual ~vpgl_rational_camera() {}
00143 
00144   virtual vcl_string type_name() const { return "vpgl_rational_camera"; }
00145 
00146   //: Clone `this': creation of a new object and initialization
00147   //  See Prototype pattern
00148   virtual vpgl_rational_camera<T>* clone(void) const;
00149 
00150         // --- Mutators/Accessors ---
00151 
00152   //: set rational polynomial coefficients
00153   void set_coefficients(vcl_vector<vcl_vector<T> > const& rational_coeffs);
00154   void set_coefficients(vnl_matrix_fixed<T, 4, 20> const& rational_coeffs)
00155     {rational_coeffs_ = rational_coeffs;}
00156   //: set coordinate scale and offsets
00157   void set_scale_offsets(vcl_vector<vpgl_scale_offset<T> > const& scale_offsets);
00158   //: get the rational polynomial coefficients in a vnl matrix
00159   vnl_matrix_fixed<T, 4, 20> coefficient_matrix() const
00160     {return rational_coeffs_;}
00161   //: get the rational polynomial coefficients in a vcl array
00162   vcl_vector<vcl_vector<T> > coefficients() const;
00163   //: get the scale and offsets in a vector
00164   vcl_vector<vpgl_scale_offset<T> > scale_offsets() const
00165     {return scale_offsets_;}
00166   //:set a specific scale value
00167   void set_scale(const coor_index coor_index, const T scale)
00168     {scale_offsets_[coor_index].set_scale(scale);}
00169   //:set a specific scale value
00170   void set_offset(const coor_index coor_index, const T offset)
00171     {scale_offsets_[coor_index].set_offset(offset);}
00172   //: get a specific scale value
00173   T scale(const coor_index coor_index) const
00174     {return scale_offsets_[coor_index].scale();}
00175   //: get a specific offset value
00176   T offset(const coor_index coor_index) const
00177     {return scale_offsets_[coor_index].offset();}
00178   //: get a specific scale_offset
00179   vpgl_scale_offset<T> scl_off(const coor_index coor_index) const
00180     {return scale_offsets_[coor_index];}
00181 
00182         // --- Often useful for adjusting the camera ---
00183 
00184   //:set u-v translation offset
00185   void set_image_offset(const T u_off, const T v_off)
00186   { scale_offsets_[U_INDX].set_offset(u_off);
00187     scale_offsets_[V_INDX].set_offset(v_off); }
00188 
00189   //:get u-v translation offset
00190   void image_offset(T& u_off, T& v_off)
00191     {u_off = offset(U_INDX); v_off = offset(V_INDX);}
00192 
00193    //:set u-v scale
00194   void set_image_scale(const T u_scale, const T v_scale)
00195   { scale_offsets_[U_INDX].set_scale(u_scale);
00196     scale_offsets_[V_INDX].set_scale(v_scale); }
00197 
00198   //:get u-v  scale
00199   void image_scale(T& u_scale, T& v_scale)
00200     {u_scale = scale(U_INDX); v_scale = scale(V_INDX);}
00201   //: The generic camera interface. u represents image column, v image row.
00202   virtual void project(const T x, const T y, const T z, T& u, T& v) const;
00203 
00204         // --- Interface for vnl ---
00205 
00206   //: Project a world point onto the image
00207   virtual vnl_vector_fixed<T, 2> project(vnl_vector_fixed<T, 3> const& world_point) const;
00208 
00209         // --- Interface for vgl ---
00210 
00211   //: Project a world point onto the image
00212   virtual vgl_point_2d<T> project(vgl_point_3d<T> world_point) const;
00213 
00214   //: print the camera parameters
00215   virtual void print(vcl_ostream& s = vcl_cout) const;
00216 
00217   virtual bool save(vcl_string cam_path);
00218 
00219         // --- binary IO ---
00220 
00221   //: Binary save self to stream.
00222   virtual void b_write(vsl_b_ostream &os) const;
00223 
00224   //: Binary load self from stream.
00225   virtual void b_read(vsl_b_istream &is);
00226 
00227  protected:
00228   // utilities
00229   vnl_vector_fixed<T, 20> power_vector(const T x, const T y, const T z) const;
00230   // members
00231   vnl_matrix_fixed<T, 4, 20> rational_coeffs_;
00232   vcl_vector<vpgl_scale_offset<T> > scale_offsets_;
00233 };
00234 
00235 //: Write to stream
00236 // \relatesalso vpgl_rational_camera
00237 template <class T>
00238 vcl_ostream& operator<<(vcl_ostream& s, const vpgl_rational_camera<T>& p);
00239 
00240 //: Read from stream
00241 // \relatesalso vpgl_rational_camera
00242 template <class T>
00243 vcl_istream& operator>>(vcl_istream& is, vpgl_rational_camera<T>& p);
00244 
00245 //: Creates a rational camera from a file
00246 // \relatesalso vpgl_rational_camera
00247 template <class T>
00248 vpgl_rational_camera<T>* read_rational_camera(vcl_string cam_path);
00249 
00250 //: Creates a rational camera from a stream
00251 // \relatesalso vpgl_rational_camera
00252 template <class T>
00253 vpgl_rational_camera<T>* read_rational_camera(vcl_istream& istr);
00254 
00255 #define VPGL_RATIONAL_CAMERA_INSTANTIATE(T) extern "please include vgl/vpgl_rational_camera.txx first"
00256 
00257 
00258 #endif // vpgl_rational_camera_h_