contrib/mul/msm/tools/msm_build_shape_model.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 // \brief Tool to build a shape model from data in files.
00004 // \author Tim Cootes
00005 
00006 #include <mbl/mbl_read_props.h>
00007 #include <mbl/mbl_exception.h>
00008 #include <mbl/mbl_parse_colon_pairs_list.h>
00009 #include <vul/vul_arg.h>
00010 #include <vul/vul_string.h>
00011 #include <vcl_sstream.h>
00012 #include <vcl_fstream.h>
00013 #include <vcl_string.h>
00014 #include <vsl/vsl_quick_file.h>
00015 
00016 #include <msm/msm_shape_model_builder.h>
00017 
00018 #include <msm/msm_add_all_loaders.h>
00019 
00020 /*
00021 Parameter file format:
00022 <START FILE>
00023 //: Aligner for shape model
00024 aligner: msm_similarity_aligner
00025 
00026 //: Object to apply limits to parameters
00027 param_limiter: msm_ellipsoid_limiter { accept_prop: 0.98 }
00028 
00029 // Maximum number of shape modes
00030 max_modes: 99
00031 
00032 // Proportion of shape variation to explain
00033 var_prop: 0.95
00034 
00035 //: File to save model to
00036 shape_model_path: shape_model.bfs
00037 
00038 image_dir: /home/images/
00039 points_dir: /home/points/
00040 images: {
00041   image1.pts : image1.jpg
00042   image2.pts : image2.jpg
00043 }
00044 
00045 <END FILE>
00046 */
00047 
00048 void print_usage()
00049 {
00050   vcl_cout << "msm_build_shape_model -p param_file\n"
00051            << "Builds the shape model from the supplied data.\n"
00052            << vcl_endl;
00053 
00054   vul_arg_display_usage_and_exit();
00055 }
00056 
00057 //: Structure to hold parameters
00058 struct tool_params
00059 {
00060   //: Aligner for shape model
00061   vcl_auto_ptr<msm_aligner> aligner;
00062 
00063   //: Object to apply limits to parameters
00064   vcl_auto_ptr<msm_param_limiter> limiter;
00065 
00066   //: Maximum number of shape modes
00067   unsigned max_modes;
00068 
00069   //: Proportion of shape variation to explain
00070   double var_prop;
00071 
00072   //: Directory containing images
00073   vcl_string image_dir;
00074 
00075   //: Directory containing points
00076   vcl_string points_dir;
00077 
00078   //: File to save shape model to
00079   vcl_string shape_model_path;
00080 
00081   //: List of image names
00082   vcl_vector<vcl_string> image_names;
00083 
00084   //: List of points file names
00085   vcl_vector<vcl_string> points_names;
00086 
00087   //: Parse named text file to read in data
00088   //  Throws a mbl_exception_parse_error if fails
00089   void read_from_file(const vcl_string& path);
00090 };
00091 
00092 //: Parse named text file to read in data
00093 //  Throws a mbl_exception_parse_error if fails
00094 void tool_params::read_from_file(const vcl_string& path)
00095 {
00096   vcl_ifstream ifs(path.c_str());
00097   if (!ifs)
00098   {
00099     vcl_string error_msg = "Failed to open file: "+path;
00100     throw (mbl_exception_parse_error(error_msg));
00101   }
00102 
00103   mbl_read_props_type props = mbl_read_props_ws(ifs);
00104 
00105   max_modes=vul_string_atoi(props.get_optional_property("max_modes","99"));
00106   var_prop=vul_string_atof(props.get_optional_property("var_prop","0.95"));
00107   image_dir=props.get_optional_property("image_dir","./");
00108   points_dir=props.get_optional_property("points_dir","./");
00109   shape_model_path=props.get_optional_property("shape_model_path",
00110                                                "shape_aam.bfs");
00111 
00112   {
00113     vcl_string aligner_str
00114        = props.get_required_property("aligner");
00115     vcl_stringstream ss(aligner_str);
00116     aligner = msm_aligner::create_from_stream(ss);
00117   }
00118 
00119   {
00120     vcl_string limiter_str
00121        = props.get_optional_property("param_limiter",
00122                                      "msm_ellipsoid_limiter { accept_prop: 0.98 }");
00123     vcl_stringstream ss(limiter_str);
00124     limiter = msm_param_limiter::create_from_stream(ss);
00125   }
00126 
00127   mbl_parse_colon_pairs_list(props.get_required_property("images"),
00128                              points_names,image_names);
00129 
00130   // Don't look for unused props so can use a single common parameter file.
00131 }
00132 
00133 int main(int argc, char** argv)
00134 {
00135   vul_arg<vcl_string> param_path("-p","Parameter filename");
00136   vul_arg<vcl_string> mode_var_path("-vp","Path for output of mode variances");
00137   vul_arg_parse(argc,argv);
00138 
00139   msm_add_all_loaders();
00140 
00141   if (param_path()=="")
00142   {
00143     print_usage();
00144     return 0;
00145   }
00146 
00147   tool_params params;
00148   try
00149   {
00150     params.read_from_file(param_path());
00151   }
00152   catch (mbl_exception_parse_error& e)
00153   {
00154     vcl_cerr<<"Error: "<<e.what()<<'\n';
00155     return 1;
00156   }
00157 
00158   msm_shape_model_builder builder;
00159   msm_shape_model shape_model;
00160 
00161   builder.set_aligner(*params.aligner);
00162   builder.set_param_limiter(*params.limiter);
00163   builder.set_mode_choice(0,params.max_modes,params.var_prop);
00164   builder.build_from_files(params.points_dir,
00165                            params.points_names,
00166                            shape_model);
00167 
00168   vcl_cout<<"Built model: "<<shape_model<<vcl_endl;
00169 
00170   if (vsl_quick_file_save(shape_model,params.shape_model_path))
00171   {
00172     vcl_cout<<"Saved shape model to "
00173             <<params.shape_model_path<<vcl_endl;
00174   }
00175   else
00176   {
00177     vcl_cerr<<"Failed to save to "<<params.shape_model_path<<'\n';
00178     return 3;
00179   }
00180 
00181   if (mode_var_path()!="")
00182   {
00183     vcl_ofstream ofs(mode_var_path().c_str());
00184     if (!ofs)
00185     {
00186       vcl_cerr<<"Failed to open "<<mode_var_path()<<" for output.\n";
00187       return 4;
00188     }
00189     for (unsigned i=0;i<shape_model.n_modes();++i)
00190       ofs<<shape_model.mode_var()[i]<<vcl_endl;
00191     ofs.close();
00192     vcl_cout<<"Saved mode variances to "<<mode_var_path()<<vcl_endl;
00193   }
00194 
00195   return 0;
00196 }