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 * © 2006, Jet Propulsion Laboratory, California Institute of Technology<br> 00017 * © 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