contrib/mul/msm/tools/msm_get_shape_params.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 // \brief Tool to compute shape parameters for each set of points
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 <vcl_sstream.h>
00011 #include <vcl_fstream.h>
00012 #include <vcl_string.h>
00013 #include <vsl/vsl_quick_file.h>
00014 #include <vul/vul_file.h>
00015 #include <msm/msm_shape_model.h>
00016 #include <msm/msm_shape_instance.h>
00017 #include <msm/msm_add_all_loaders.h>
00018 
00019 /*
00020 Parameter file format:
00021 <START FILE>
00022 //: File to containing shape model
00023 shape_model_path: shape_model.bfs
00024 
00025 output_path: shape_params.txt
00026 
00027 //: Directory to save best fit points
00028 //  If parameter is not set then do not write best fit points.
00029 out_points_dir: /home/bestfit_points/
00030 
00031 image_dir: /home/images/
00032 points_dir: /home/points/
00033 images: {
00034   image1.pts : image1.jpg
00035   image2.pts : image2.jpg
00036 }
00037 <END FILE>
00038 
00039 Note: You can use the same file as was used to build the model, defining the output
00040       path using the -o command line option.
00041 */
00042 
00043 void print_usage()
00044 {
00045   vcl_cout << "msm_get_shape_params -p param_file\n"
00046            << "Compute shape parameters for each set of points.\n"
00047            << "Loads in named model and each set of points\n"
00048            << "Fits model to each set of points and saves\n"
00049            << "pose and shape parameters to a text file.\n"
00050            << "One row per shape.\n"
00051            << "Also save best fit points for every image.\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   //: File containing the shape model
00061   vcl_string shape_model_path;
00062 
00063   //: File to save parameters to
00064   vcl_string output_path;
00065 
00066   //: Directory containing images
00067   vcl_string image_dir;
00068 
00069   //: Directory containing points
00070   vcl_string points_dir;
00071 
00072   //: Directory to save best fit points
00073   vcl_string out_points_dir;
00074 
00075   //: List of image names
00076   vcl_vector<vcl_string> image_names;
00077 
00078   //: List of points file names
00079   vcl_vector<vcl_string> points_names;
00080 
00081   //: Parse named text file to read in data
00082   //  Throws a mbl_exception_parse_error if fails
00083   void read_from_file(const vcl_string& path);
00084 };
00085 
00086 //: Parse named text file to read in data
00087 //  Throws a mbl_exception_parse_error if fails
00088 void tool_params::read_from_file(const vcl_string& path)
00089 {
00090   vcl_ifstream ifs(path.c_str());
00091   if (!ifs)
00092   {
00093     vcl_string error_msg = "Failed to open file: "+path;
00094     throw (mbl_exception_parse_error(error_msg));
00095   }
00096 
00097   mbl_read_props_type props = mbl_read_props_ws(ifs);
00098 
00099   shape_model_path=props.get_required_property("shape_model_path");
00100 
00101   image_dir=props.get_optional_property("image_dir","./");
00102   points_dir=props.get_optional_property("points_dir","./");
00103   output_path=props.get_optional_property("output_path",
00104                                           "shape_params.txt");
00105   out_points_dir=props.get_optional_property("out_points_dir","");
00106 
00107   mbl_parse_colon_pairs_list(props.get_required_property("images"),
00108                              points_names,image_names);
00109 
00110   // Don't look for unused props so can use a single common parameter file.
00111 }
00112 
00113 void load_shapes(const vcl_string& points_dir,
00114                  const vcl_vector<vcl_string>& filenames,
00115                  vcl_vector<msm_points>& shapes)
00116 {
00117   unsigned n=filenames.size();
00118 
00119   shapes.resize(n);
00120   for (unsigned i=0;i<n;++i)
00121   {
00122     vcl_string path = points_dir+"/"+filenames[i];
00123     if (!shapes[i].read_text_file(path))
00124     {
00125       mbl_exception_parse_error x("Failed to load points from "+path);
00126       mbl_exception_error(x);
00127     }
00128   }
00129 }
00130 
00131 
00132 int main(int argc, char** argv)
00133 {
00134   vul_arg<vcl_string> param_path("-p","Parameter filename");
00135   vul_arg<vcl_string> out_path("-o","Output path (over-riding param file)");
00136   vul_arg<bool> no_pose("-no_pose","Don't display pose",false);
00137   vul_arg<bool> use_pts_name("-use_pts_name","Include name of points at beginning of the line",false);
00138   vul_arg_parse(argc,argv);
00139 
00140   msm_add_all_loaders();
00141 
00142   if (param_path()=="")
00143   {
00144     print_usage();
00145     return 0;
00146   }
00147 
00148   tool_params params;
00149   try
00150   {
00151     params.read_from_file(param_path());
00152   }
00153   catch (mbl_exception_parse_error& e)
00154   {
00155     vcl_cerr<<"Error: "<<e.what()<<'\n';
00156     return 1;
00157   }
00158 
00159   if (out_path()!="") params.output_path = out_path();
00160 
00161   msm_shape_model shape_model;
00162 
00163   if (!vsl_quick_file_load(shape_model,params.shape_model_path))
00164   {
00165     vcl_cerr<<"Failed to load shape model from "
00166             <<params.shape_model_path<<'\n';
00167     return 2;
00168   }
00169 
00170   msm_shape_instance sm_instance(shape_model);
00171 
00172   // Load in all the shapes
00173   vcl_vector<msm_points> shapes;
00174   load_shapes(params.points_dir,params.points_names,shapes);
00175 
00176   // Open the text file for output
00177   vcl_ofstream ofs(params.output_path.c_str());
00178   if (!ofs)
00179   {
00180     vcl_cerr<<"Failed to open "<<params.output_path <<" for output.\n";
00181     return 1;
00182   }
00183 
00184   bool write_bestfitpts = true;
00185   if (params.out_points_dir == "")
00186     write_bestfitpts = false;
00187   else
00188     vcl_cout << "Write best fit points to " << params.out_points_dir << vcl_endl;
00189 
00190   for (unsigned i=0;i<shapes.size();++i)
00191   {
00192     sm_instance.fit_to_points(shapes[i]);
00193 
00194     if (use_pts_name()) ofs<<params.points_names[i]<<' ';
00195 
00196     if (!no_pose())
00197     {
00198       // Write pose parameters
00199       for (unsigned j=0;j<sm_instance.pose().size();++j)
00200         ofs<<sm_instance.pose()[j]<<' ';
00201     }
00202 
00203     // Write shape parameters
00204     for (unsigned j=0;j<sm_instance.params().size();++j)
00205       ofs<<sm_instance.params()[j]<<' ';
00206 
00207     ofs<<vcl_endl;
00208 
00209     // Write best fit points
00210     if (write_bestfitpts)
00211     {
00212       // Check that the directory exists (points_name may include a dir)
00213       vcl_string out_pts_dir = vul_file::dirname(params.out_points_dir+"/"+params.points_names[i]);
00214       if (!vul_file::is_directory(out_pts_dir))
00215       {
00216         vcl_cout<<"Directory "<<out_pts_dir
00217                 <<" does not exist. Creating it."<<vcl_endl;
00218         if (!vul_file::make_directory_path(out_pts_dir))
00219         {
00220           vcl_cerr<<"Unable to create it.\n";
00221           return 12;
00222         }
00223       }
00224       sm_instance.points().write_text_file(params.out_points_dir+"/"+params.points_names[i]);
00225     }
00226   }
00227   ofs.close();
00228 
00229   vcl_cout<<"Wrote parameters for "<<shapes.size()<<" shapes to "<<params.output_path<<vcl_endl;
00230   if (use_pts_name()) vcl_cout<<"Each line starts with filename."<<vcl_endl;
00231   if (!no_pose()) vcl_cout<<"First "<<sm_instance.pose().size()<<" values are pose."<<vcl_endl;
00232   vcl_cout<<"Next "<<sm_instance.params().size()<<" values are shape."<<vcl_endl;
00233 
00234   return 0;
00235 }