contrib/mul/mfpf/tools/mfpf_test_finder.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 // \brief Tool to test a finder on a set of annotated images
00004 // \author Tim Cootes
00005 // Loads a model of patch around a given point (from mfpf_build_finder tool)
00006 // For simplicity, assumes fixed scale and orientation across all data.
00007 // Uses the patch model to search the images and measures how good best
00008 // fit is.
00009 // Input data file format:
00010 // \code
00011 // pt_index: 31 // Which point to use
00012 // res_level: 1
00013 // model_path: patch_model.bfs
00014 //
00015 // image_dir: ../images/
00016 // points_dir: ../points/
00017 // images: {
00018 //   image1.pts : image1.jpg
00019 //   image2.pts : image2.jpg
00020 // }
00021 // \endcode
00022 
00023 #include <mbl/mbl_parse_colon_pairs_list.h>
00024 #include <mbl/mbl_read_props.h>
00025 #include <mbl/mbl_exception.h>
00026 
00027 #include <vul/vul_arg.h>
00028 #include <vul/vul_string.h>
00029 #include <vsl/vsl_quick_file.h>
00030 #include <vsl/vsl_binary_loader.h>
00031 
00032 #include <mfpf/mfpf_point_finder.h>
00033 #include <mfpf/mfpf_point_finder_builder.h>
00034 #include <mfpf/mfpf_add_all_loaders.h>
00035 #include <mfpf/mfpf_sort_matches.h>
00036 
00037 #include <vil/vil_load.h>
00038 #include <vil/vil_convert.h>
00039 #include <vimt/vimt_image_2d_of.h>
00040 #include <vimt/vimt_image_pyramid.h>
00041 #include <vimt/vimt_gaussian_pyramid_builder_2d.h>
00042 
00043 #include <msm/msm_points.h>
00044 #include <mbl/mbl_stats_1d.h>
00045 #include <vcl_cmath.h>
00046 #include <vcl_cassert.h>
00047 
00048 //: Structure to hold parameters
00049 struct tool_params
00050 {
00051   //: Path to which to save the model
00052   vcl_string model_path;
00053 
00054   //: Resolution level at which to build model
00055   unsigned res_level;
00056 
00057   //: Index of point to use to train model
00058   unsigned pt_index;
00059 
00060   //: Image directory
00061   vcl_string image_dir;
00062 
00063   //: Points directory
00064   vcl_string points_dir;
00065 
00066   //: List of image filenames
00067   vcl_vector<vcl_string> image_names;
00068 
00069   //: List of points filenames
00070   vcl_vector<vcl_string> points_names;
00071 
00072   // Constructor to set defaults
00073   tool_params();
00074 
00075   //: Parse named text file to read in data
00076   //  Throws a upf_exception_parse_error if fails
00077   void read_from_file(const vcl_string& path);
00078 };
00079 
00080 tool_params::tool_params()
00081 {
00082 }
00083 
00084 //: Parse named text file to read in data
00085 //  Throws a upf_exception_parse_error if fails
00086 void tool_params::read_from_file(const vcl_string& path)
00087 {
00088   vcl_ifstream ifs(path.c_str());
00089   if (!ifs)
00090   {
00091     vcl_string error_msg = "Failed to open file: "+path;
00092     throw (mbl_exception_parse_error(error_msg));
00093   }
00094 
00095   mbl_read_props_type props;
00096   props = mbl_read_props_ws(ifs);
00097 
00098   model_path=props.get_required_property("model_path");
00099   image_dir=props.get_required_property("image_dir");
00100   points_dir=props.get_required_property("points_dir");
00101 
00102   mbl_parse_colon_pairs_list(props.get_required_property("images"),
00103                              points_names,image_names);
00104 
00105   res_level = vul_string_atoi(props.get_optional_property("res_level","0"));
00106   pt_index = vul_string_atoi(props.get_optional_property("pt_index","0"));
00107 
00108   try {
00109     mbl_read_props_look_for_unused_props(
00110       "::read_from_file", props, mbl_read_props_type());
00111   }
00112   catch (mbl_exception_unused_props& e)
00113   {
00114     throw (mbl_exception_parse_error(e.what()));
00115   }
00116 }
00117 
00118 void print_usage()
00119 {
00120   vcl_cout<<"mfpf_test_finder -p param_file\n"
00121           <<"Tool to test a finder from a set of annotated images\n"
00122           <<vcl_endl;
00123 }
00124 
00125 int main(int argc, char** argv)
00126 {
00127   vul_arg<vcl_string> param_path("-p","Parameter filename");
00128 
00129   vul_arg_parse(argc,argv);
00130 
00131   if (param_path()=="")
00132   {
00133     print_usage();
00134     return 0;
00135   }
00136 
00137   mfpf_add_all_loaders();
00138 
00139   tool_params params;
00140   try { params.read_from_file(param_path()); }
00141   catch (mbl_exception_parse_error& e)
00142   {
00143     vcl_cerr<<"Error: "<<e.what()<<vcl_endl;
00144     return 1;
00145   }
00146 
00147   unsigned n_images = params.image_names.size();
00148 
00149   vimt_gaussian_pyramid_builder_2d<float> pyr_builder;
00150 
00151   vgl_vector_2d<double> u(1,0);  // Default to unit scale and fixed angle
00152 
00153   mfpf_point_finder *finder = 0;
00154   vsl_quick_file_load(finder,params.model_path);
00155   vcl_cout<<"Finder: "<<*finder<<vcl_endl;
00156 
00157   finder->set_search_area(10,10);
00158 
00159   mbl_stats_1d d_stats,rank_stats,min_d_stats;
00160 
00161   vcl_vector<mfpf_pose> poses;
00162   vcl_vector<double> fits;
00163 
00164   for (unsigned i=0;i<n_images;++i)
00165   {
00166     // Load in image
00167     vil_image_view<vxl_byte> byte_image;
00168     vcl_string image_path = params.image_dir+"/"+params.image_names[i];
00169     byte_image = vil_load(image_path.c_str());
00170     if (byte_image.size()==0)
00171     {
00172       vcl_cerr<<"Failed to load in image from "<<image_path<<vcl_endl;
00173       return 2;
00174     }
00175 
00176     // Convert to float image and build pyramid
00177     vimt_image_2d_of<float> image;
00178     if (byte_image.nplanes()==1)
00179       vil_convert_cast(byte_image,image.image());
00180     else
00181       vil_convert_planes_to_grey(byte_image,image.image());
00182 
00183     vimt_image_pyramid image_pyr;
00184     pyr_builder.build(image_pyr,image);
00185 
00186     assert(int(params.res_level)<=image_pyr.hi());
00187 
00188     // Select relevant level from pyramid
00189     const vimt_image_2d_of<float>& imageL
00190       = static_cast<const vimt_image_2d_of<float>&>(image_pyr(params.res_level));
00191 
00192     // Load in points
00193     msm_points points;
00194     vcl_string points_path = params.points_dir+"/"
00195                               +params.points_names[i];
00196 
00197     if (!points.read_text_file(points_path))
00198     {
00199       vcl_cerr<<"Failed to load points from "<<points_path<<vcl_endl;
00200       return 3;
00201     }
00202 
00203     vgl_point_2d<double> p = points[params.pt_index];
00204 
00205     // Search image and evaluate match
00206     vgl_point_2d<double> new_p;
00207     vgl_vector_2d<double> new_u;
00208 
00209     // Slight fudge since it searches around the true point
00210     /* double fit = */ finder->search(imageL,p,u,new_p,new_u);
00211 
00212     d_stats.obs((new_p-p).length());
00213 
00214     poses.resize(0); fits.resize(0);
00215     finder->multi_search(imageL,p,u,poses,fits);
00216     mfpf_sort_matches(poses,fits);
00217 
00218     // Find the index of the closest point to p
00219     if (poses.size()>0)
00220     {
00221       double min_d = (p-poses[0].p()).length();
00222       unsigned best_j = 0;
00223       for (unsigned j=1;j<poses.size();++j)
00224       {
00225         double d = (p-poses[j].p()).length();
00226         if (d<min_d) { min_d=d; best_j=j; }
00227       }
00228       rank_stats.obs(best_j);
00229       min_d_stats.obs(min_d);
00230     }
00231   }
00232 
00233   vcl_cout<<"d_stats: "<<d_stats<<vcl_endl
00234           <<"rank_stats: "<<rank_stats<<vcl_endl
00235           <<"min_d_stats: "<<min_d_stats<<vcl_endl;
00236 
00237   delete finder;
00238 
00239   return 0;
00240 }
00241