contrib/mul/msm/tools/msm_plot_aligned_shapes.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 // \brief Tool to generate EPS file containing aligned shape 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 <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_aligner.h>
00017 
00018 #include <msm/msm_add_all_loaders.h>
00019 #include <msm/utils/msm_draw_shape_to_eps.h>
00020 
00021 /*
00022 Parameter file format:
00023 <START FILE>
00024 //: Aligner for shape model
00025 aligner: msm_similarity_aligner
00026 
00027 //: Radius of points to display (if <0, then don't draw points)
00028 point_radius: 0.5
00029 
00030 point_colour: black
00031 mean_colour: red
00032 
00033 // Approximate width of region to display shape
00034 display_width: 256
00035 
00036 // When supplied, draw curves for mean shape
00037 curves_path: face_front.crvs
00038 line_colour: green
00039 
00040 output_path: sim_aligned.eps
00041 
00042 image_dir: /home/images/
00043 points_dir: /home/points/
00044 images: {
00045   image1.pts : image1.jpg
00046   image2.pts : image2.jpg
00047 }
00048 
00049 <END FILE>
00050 */
00051 
00052 void print_usage()
00053 {
00054   vcl_cout << "msm_plot_aligned_shapes -p param_file\n"
00055            << "Generate EPS file containing aligned shape points.\n"
00056            << vcl_endl;
00057 
00058   vul_arg_display_usage_and_exit();
00059 }
00060 
00061 //: Structure to hold parameters
00062 struct tool_params
00063 {
00064   //: Aligner for shape model
00065   vcl_auto_ptr<msm_aligner> aligner;
00066 
00067   vcl_string curves_path;
00068 
00069   //: Colour to draw curves
00070   vcl_string line_colour;
00071 
00072   //: Directory containing images
00073   vcl_string image_dir;
00074 
00075   //: Directory containing points
00076   vcl_string points_dir;
00077 
00078   //: Approximate width of region to display shape
00079   int display_width;
00080 
00081   //: Point colour
00082   vcl_string point_colour;
00083   vcl_string mean_colour;
00084 
00085   //: Radius of points to display (if <0, then don't draw points)
00086   double point_radius;
00087 
00088   //: File to save EPS file to
00089   vcl_string output_path;
00090 
00091   //: List of image names
00092   vcl_vector<vcl_string> image_names;
00093 
00094   //: List of points file names
00095   vcl_vector<vcl_string> points_names;
00096 
00097   //: Parse named text file to read in data
00098   //  Throws a mbl_exception_parse_error if fails
00099   void read_from_file(const vcl_string& path);
00100 };
00101 
00102 //: Parse named text file to read in data
00103 //  Throws a mbl_exception_parse_error if fails
00104 void tool_params::read_from_file(const vcl_string& path)
00105 {
00106   vcl_ifstream ifs(path.c_str());
00107   if (!ifs)
00108   {
00109     vcl_string error_msg = "Failed to open file: "+path;
00110     throw (mbl_exception_parse_error(error_msg));
00111   }
00112 
00113   mbl_read_props_type props = mbl_read_props_ws(ifs);
00114 
00115   curves_path=props["curves_path"];
00116 
00117   point_radius=vul_string_atof(props.get_optional_property("point_radius","1.5"));
00118   display_width=vul_string_atoi(props.get_optional_property("display_width","100"));
00119   point_colour=props.get_optional_property("point_colour","black");
00120   mean_colour=props.get_optional_property("mean_colour","red");
00121   line_colour=props.get_optional_property("line_colour","green");
00122 
00123   image_dir=props.get_optional_property("image_dir","./");
00124   points_dir=props.get_optional_property("points_dir","./");
00125   output_path=props.get_optional_property("output_path",
00126                                           "aligned.eps");
00127 
00128   {
00129     vcl_string aligner_str = props.get_required_property("aligner");
00130     vcl_stringstream ss(aligner_str);
00131     aligner = msm_aligner::create_from_stream(ss);
00132   }
00133 
00134   mbl_parse_colon_pairs_list(props.get_required_property("images"),
00135                              points_names,image_names);
00136 
00137   // Don't look for unused props so can use a single common parameter file.
00138 }
00139 
00140 void load_shapes(const vcl_string& points_dir,
00141                  const vcl_vector<vcl_string>& filenames,
00142                  vcl_vector<msm_points>& shapes)
00143 {
00144   unsigned n=filenames.size();
00145 
00146   shapes.resize(n);
00147   for (unsigned i=0;i<n;++i)
00148   {
00149     vcl_string path = points_dir+"/"+filenames[i];
00150     if (!shapes[i].read_text_file(path))
00151     {
00152       mbl_exception_parse_error x("Failed to load points from "+path);
00153       mbl_exception_error(x);
00154     }
00155   }
00156 }
00157 
00158 
00159 int main(int argc, char** argv)
00160 {
00161   vul_arg<vcl_string> param_path("-p","Parameter filename");
00162   vul_arg_parse(argc,argv);
00163 
00164   msm_add_all_loaders();
00165 
00166   if (param_path()=="")
00167   {
00168     print_usage();
00169     return 0;
00170   }
00171 
00172   tool_params params;
00173   try
00174   {
00175     params.read_from_file(param_path());
00176   }
00177   catch (mbl_exception_parse_error& e)
00178   {
00179     vcl_cerr<<"Error: "<<e.what()<<'\n';
00180     return 1;
00181   }
00182 
00183   msm_curves curves;
00184   if (params.curves_path!="")
00185   {
00186     if (!curves.read_text_file(params.curves_path))
00187       vcl_cerr<<"Failed to read in curves from " <<params.curves_path<<'\n';
00188   }
00189 
00190   // Load in all the shapes
00191   vcl_vector<msm_points> shapes;
00192   load_shapes(params.points_dir,params.points_names,shapes);
00193 
00194   msm_points mean_shape;
00195   vcl_vector<vnl_vector<double> > pose_to_ref;
00196   vnl_vector<double> average_pose;
00197 
00198   params.aligner->align_set(shapes,mean_shape,pose_to_ref,average_pose);
00199 
00200   // Apply pose_to_ref to map each to the reference frame
00201   vgl_box_2d<double> bounds;
00202   for (unsigned i=0;i<shapes.size();++i)
00203   {
00204     params.aligner->apply_transform(shapes[i],pose_to_ref[i],shapes[i]);
00205     bounds.add(shapes[i].bounds());
00206   }
00207 
00208   int d_width=params.display_width;
00209   double b=0.05;
00210   double s = (1.0-2*b)*d_width/bounds.width();
00211   int d_height=int(s*bounds.height()/(1.0-2*b));
00212 
00213   double tx = b*bounds.width()-bounds.min_x();
00214   double ty = b*bounds.height()-bounds.min_y();
00215 
00216   mbl_eps_writer writer(params.output_path.c_str(),
00217                         d_width,d_height);
00218 
00219   writer.set_colour(params.point_colour);
00220   for (unsigned i=0;i<shapes.size();++i)
00221   {
00222     msm_points points = shapes[i];
00223     points.translate_by(tx,ty);
00224     points.scale_by(s);
00225     msm_draw_points_to_eps(writer,points,
00226                            params.point_radius);
00227   }
00228 
00229   // Draw mean points
00230   msm_points points = mean_shape;
00231   points.translate_by(tx,ty);
00232   points.scale_by(s);
00233   writer.set_colour(params.mean_colour);
00234   msm_draw_points_to_eps(writer,points,3.0*params.point_radius);
00235 
00236   // Draw curves if available
00237   writer.set_colour(params.line_colour);
00238   msm_draw_shape_to_eps(writer,points,curves);
00239 
00240   writer.close();
00241   vcl_cout<<"Plotted shapes to "<<params.output_path<<vcl_endl;
00242 
00243   return 0;
00244 }