Follow this link to skip to the main content

camera_model.cc

Go to the documentation of this file.
00001 // -*-c++-*- 
00002 //---------------------------< /-/ CLARAty /-/ >------------------------------
00003 /** 
00004  * @file  camera_model.cc
00005  *
00006  * This is the pure abstract base class for building camera models.
00007  *
00008  * <br>@b Designer(s):  Clay Kunz, Issa A.D. Nesnas
00009  * <br>@b Author(s):    Clay Kunz
00010  * <br>@b Date:         December 13, 2001
00011  *
00012  * <b>Software License:</b><br>
00013  * <code>  http://claraty.jpl.nasa.gov/license/open_src/  or
00014  *         file: license/open_src.txt  </code>
00015  *
00016  * &copy; 2006, Jet Propulsion Laboratory, California Institute of Technology<br>
00017  * &copy; 2006, NASA Ames Research Center
00018  *
00019  * $Revision: 1.5 $
00020  */ 
00021 //-----------------------------------------------------------------------------
00022 
00023 #include "claraty/camera_model.h"
00024 
00025 #include <fstream>
00026 #include <iostream>
00027 
00028 //#include "claraty/frame.h"
00029 //#include "claraty/parse_tree.h"
00030 #include "claraty/fdm_parse_tree.h"
00031 #include "claraty/point.h"
00032 #include "claraty/matrix.h"
00033 #include "claraty/2d_point.h"
00034 
00035 using namespace std;
00036 
00037 namespace claraty {
00038 
00039 //-----------------------------------------------------------------------------
00040 
00041 Camera_Model::
00042 Camera_Model()  
00043   : _mounting_frame ( NULL )
00044 {
00045 }
00046 
00047 //-----------------------------------------------------------------------------
00048 
00049 Camera_Model::
00050 Camera_Model(Frame * f)
00051   : _mounting_frame ( f )
00052 {
00053 }
00054 
00055 //-----------------------------------------------------------------------------
00056 
00057 Camera_Model::
00058 Camera_Model(const Camera_Model& rhs)
00059   : _mounting_frame ( rhs._mounting_frame),
00060     _name ( rhs._name )
00061 {
00062 }
00063 
00064 //-----------------------------------------------------------------------------
00065 
00066 Camera_Model::
00067 ~Camera_Model()
00068 {
00069 }
00070 
00071 //-----------------------------------------------------------------------------
00072 
00073 bool Camera_Model::
00074 operator==(const Camera_Model & rhs) const 
00075 {
00076   return _mounting_frame == rhs._mounting_frame && _name == rhs._name;
00077 }
00078 
00079 //-----------------------------------------------------------------------------
00080 
00081 Camera_Model & Camera_Model::
00082 operator=(const Camera_Model & rhs)
00083 {
00084   if (this != &rhs) {
00085     _mounting_frame = rhs._mounting_frame;
00086     _name = rhs._name;
00087   }
00088   return *this;
00089 }
00090 
00091 //-----------------------------------------------------------------------------
00092 /**
00093  * Assign frame to the camera model
00094  *
00095  * @param[in] f The frame coordinate transformation that defines the mounting
00096  *              of the camera relative to other coordinate frames
00097  */
00098 void Camera_Model::
00099 set_frame(Frame * f)
00100 { 
00101   _mounting_frame = f; 
00102 }
00103 
00104 //-----------------------------------------------------------------------------
00105 /**
00106  * Most camera models deal with lens distortion by mapping raw images
00107  * that contain lens distortion to some form of "ideal" images that
00108  * filter out this distortion.  This function maps coordinates from
00109  * the raw image to the processed (linearized) image.  For mapping between
00110  * raw (unrectified) images and their processed (rectified/linearized)
00111  * versions, subclasses should override this function. Default
00112  * implementation models no distortion at all.  
00113  *
00114  * @param[in] unmapped_coord The (x,y) coordinates of the pixel in the 
00115  *                           raw unmapped image
00116  * @return                   The corresponding (x,y) pixel coordinates
00117  *                           in the mapped processed image.
00118  */
00119 Pixel_Coord Camera_Model::
00120 get_mapped_coordinates(Pixel_Coord unmapped_coord) const
00121 { 
00122   return unmapped_coord;
00123 }
00124 
00125 //-----------------------------------------------------------------------------
00126 /**
00127  * Most camera models deal with lens distortion by mapping raw images
00128  * that contain lens distortion to some form of "ideal" images that
00129  * filter out this distortion.  This function maps coordinates from
00130  * the processed (linearized) image back to the original raw image.
00131  * For mapping between processed and raw images, subclasses should
00132  * override this function. Default implementation models no distortion
00133  * at all.  This function provides the inverse mapping of the above
00134  * function. Lens distortion models are often difficult to invert, and
00135  * must be inverted numerically. So typically one of these two
00136  * functions is going significantly more expensive to call than the
00137  * other. Map_Op assumes that the previous function is low-cost;
00138  * subclasses should document complexity of both.
00139  * 
00140  * @param[in] mapped_coord The (x,y) coordinates of the pixel in the 
00141  *                         mapped image.
00142  * @return The (x,y) pixel coordinates of the original raw (or unrectified)
00143  *         image.
00144  */
00145 Pixel_Coord Camera_Model::
00146 get_unmapped_coordinates(Pixel_Coord mapped_coord) const
00147 { 
00148   return mapped_coord;
00149 }
00150 //-----------------------------------------------------------------------------
00151 /**
00152  * Subsample the internal model so that the ray-to-pixel and
00153  * pixel-to-ray functions work on images subsampled by the same
00154  * amount. This way image algorithms can work with subsampled images
00155  * and still have correct camera models to work with.  The
00156  * subsample_factor is a factor; images are sampled to 1/factor, so a
00157  * factor of 3 means 1/3 the image height & width.  Default behavior
00158  * is to print a warning message and return.
00159 */
00160 void Camera_Model::subsample(int factor)
00161 {
00162   cerr << AT_FUNCTION << "subsamping not supported in this camera model type" 
00163        << endl;
00164 }
00165 
00166 //-----------------------------------------------------------------------------
00167 /**
00168  * This function provides a way for the user to correct models and
00169  * images for lens distortion. Subclasses should do the right thing to
00170  * ensure that a reasonable new camera model is built and returned in
00171  * the mapped_model argument.  This should return true if it's
00172  * possible to build a processed model and mapping op for this model,
00173  * and false otherwise. Pretty much all subclasses should have a
00174  * function here that returns true.
00175  *
00176  * @param[in] mapped_model     The linearized model.
00177  * @param[in] map_op           The rectified map.
00178  * @return    False under all input conditions.
00179  */
00180 bool Camera_Model::
00181 map_model(Camera_Model & mapped_model,
00182           Map_Op       & map_op) const 
00183 {
00184   return false;
00185 }
00186 
00187 //-----------------------------------------------------------------------------
00188 /**
00189  * Serializes a camera model. 
00190  *
00191  * @param[in] m A map that holds the content of a serialized camera model
00192  */
00193 bool Camera_Model::
00194 io(FDM_Map m)
00195 {
00196   std::string type = get_typename();
00197   bool ok = m.field("type", type);
00198   assert(type == get_typename());
00199   
00200   const unsigned int latest_version = 1;
00201   unsigned int this_version = latest_version;
00202 
00203   if (m.is_read() && m.peekfield("camera_model_version", this_version)) {
00204     ok &= m.field("camera_model_version", this_version);
00205     assert(this_version <= latest_version);
00206     ok &= m.field("name", _name);
00207   }
00208 
00209   if (m.is_write()) {
00210     ok &= m.field("camera_model_version", this_version);
00211     ok &= m.field("name", _name);
00212   }
00213 
00214   //ok &= map.field("frame", *_mounting_frame);
00215 
00216   return ok;
00217 }
00218 //-----------------------------------------------------------------------------
00219 
00220 bool io_object(FDM_Map map, auto_ptr<Camera_Model>& model)
00221 {
00222   bool ok = true;
00223 
00224   if (map.is_read()) {
00225     // build the underlying pointer via the factory
00226     std::string type_name;
00227     ok &= map.peekfield("type", type_name);
00228     if (type_name == "none") {
00229       model.reset(NULL);
00230       return ok;
00231     }
00232     model.reset(Camera_Model::build_from_typename(type_name));
00233     if(model.get()==NULL) {
00234       cerr << "Unable to construct camera model of type " 
00235            << type_name << endl;
00236       return(false);
00237     }
00238   }
00239   if (map.is_write() && model.get() == NULL) {
00240     std::string type_name= "none";
00241     ok &= map.field("type", type_name);
00242     return ok;
00243   }
00244   ok &= model->io(map);
00245   return ok;
00246 }
00247 
00248 //-----------------------------------------------------------------------------
00249 
00250 Camera_Model * Camera_Model::
00251 build_from_file(const char *filename)
00252 {
00253   ifstream stream(filename);
00254   if (!stream) {
00255     cerr << AT_FUNCTION << " : unable to open file " << filename 
00256          << " for reading camera model" << endl;
00257     return NULL;
00258   }
00259   return build_from_stream(stream);
00260 }
00261 
00262 //-----------------------------------------------------------------------------
00263 
00264 Camera_Model * Camera_Model::
00265 build_from_stream(istream& stream)
00266 {
00267   auto_ptr<Camera_Model> model;
00268 
00269   bool ok = FDM_Parse_Tree::read_object(model, stream);
00270   if (!ok || model.get()==NULL) return NULL;
00271 
00272   return model.release();
00273 }
00274 
00275 //-----------------------------------------------------------------------------
00276 //-----------------------------------------------------------------------------
00277 /**
00278  * Align_models is the function that does epipolar alignment with
00279  * another camera. Two new camera models are produced as the output,
00280  * as well as two rectify_op objects which can be used to warp images
00281  * from this camera model and the other camera model into the new
00282  * ones. Typically this operation would both remove lens distortion
00283  * ("linearize" the models) and warp the images to make epipolar lines
00284  * horizontal and at the same y-coordinate ("align" the models).  This
00285  * function should return true if the alignment can happen, and false
00286  * otherwise (if for example the camera model types are incompatible).
00287  */
00288 bool 
00289 align_models(const Camera_Model & model1,
00290              const Camera_Model & model2,
00291              Camera_Model * & new_model1, 
00292              Camera_Model * & new_model2,
00293              Map_Op & map1,
00294              Map_Op & map2)
00295 { 
00296   return false; 
00297 }
00298 //-----------------------------------------------------------------------------
00299 
00300 
00301 } // namespace claraty