00001
00002
00003
00004
00005
00006 #include <mbl/mbl_read_props.h>
00007 #include <mbl/mbl_exception.h>
00008 #include <vul/vul_arg.h>
00009 #include <vul/vul_string.h>
00010 #include <vcl_sstream.h>
00011 #include <vcl_fstream.h>
00012 #include <vcl_string.h>
00013 #include <vcl_algorithm.h>
00014 #include <vsl/vsl_quick_file.h>
00015
00016 #include <msm/msm_shape_model.h>
00017 #include <msm/msm_shape_instance.h>
00018 #include <msm/msm_curve.h>
00019
00020 #include <msm/msm_add_all_loaders.h>
00021 #include <msm/utils/msm_draw_shape_to_eps.h>
00022 #include <msm/utils/msm_shape_mode_view.h>
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 void print_usage()
00077 {
00078 vcl_cout << "msm_draw_shape_modes -p param_file\n"
00079 << "Tool to write eps files showing modes of model.\n"
00080 << vcl_endl;
00081
00082 vul_arg_display_usage_and_exit();
00083 }
00084
00085
00086 struct tool_params
00087 {
00088
00089 vcl_string shape_model_path;
00090 vcl_string curves_path;
00091
00092
00093 unsigned max_modes;
00094
00095
00096 double n_sds;
00097
00098
00099 unsigned n_per_mode;
00100
00101
00102 bool make_movie;
00103
00104
00105 bool overlap_shapes;
00106
00107
00108 double width;
00109
00110
00111 vcl_string subspace_mode_path;
00112
00113
00114 vcl_string subspace_var_path;
00115
00116
00117 vcl_string base_name;
00118
00119
00120 vcl_string output_dir;
00121
00122
00123 vcl_string line_colour;
00124
00125
00126 vcl_string point_colour;
00127
00128
00129 double point_radius;
00130
00131
00132 double line_width;
00133
00134
00135
00136 void read_from_file(const vcl_string& path);
00137 };
00138
00139
00140
00141 void tool_params::read_from_file(const vcl_string& path)
00142 {
00143 vcl_ifstream ifs(path.c_str());
00144 if (!ifs)
00145 {
00146 vcl_string error_msg = "Failed to open file: "+path;
00147 throw (mbl_exception_parse_error(error_msg));
00148 }
00149
00150 mbl_read_props_type props = mbl_read_props_ws(ifs);
00151
00152 curves_path=props["curves_path"];
00153 n_per_mode=vul_string_atoi(props.get_optional_property("n_per_mode","3"));
00154 max_modes=vul_string_atoi(props.get_optional_property("max_modes","5"));
00155 overlap_shapes=vul_string_to_bool(props.get_optional_property("overlap_shapes","false"));
00156 make_movie=vul_string_to_bool(props.get_optional_property("make_movie","false"));
00157 n_sds=vul_string_atof(props.get_optional_property("n_sds","3.0"));
00158 point_radius=vul_string_atof(props.get_optional_property("point_radius","1.5"));
00159 line_width=vul_string_atof(props.get_optional_property("line_width","1"));
00160 width=vul_string_atof(props.get_optional_property("width","100"));
00161 line_colour=props.get_optional_property("line_colour","black");
00162 point_colour=props.get_optional_property("point_colour","red");
00163 base_name=props.get_optional_property("base_name","./");
00164 output_dir=props.get_optional_property("output_dir","./");
00165 shape_model_path=props.get_optional_property("shape_model_path",
00166 "shape_aam.bfs");
00167
00168 if (make_movie) overlap_shapes=true;
00169
00170 subspace_mode_path = props["subspace_mode_path"];
00171 if (subspace_mode_path=="-") subspace_mode_path="";
00172
00173 subspace_var_path = props["subspace_var_path"];
00174 if (subspace_var_path=="-") subspace_var_path="";
00175
00176
00177 }
00178
00179
00180 void draw_mode(msm_shape_mode_view& mode_view,
00181 const msm_curves& curves,
00182 tool_params& params)
00183 {
00184 mode_view.compute_shapes();
00185 unsigned m = mode_view.mode();
00186 vgl_box_2d<int> win_box = mode_view.display_window();
00187
00188 vcl_stringstream ss;
00189 ss<<params.output_dir<<'/'<<params.base_name<<"_s"<<m<<".eps";
00190 mbl_eps_writer writer(ss.str().c_str(),
00191 win_box.width(),win_box.height());
00192
00193 unsigned n_shapes = mode_view.points().size();
00194 for (unsigned i=0;i<n_shapes;++i)
00195 {
00196 writer.set_colour(params.point_colour);
00197 if (params.point_radius>0)
00198 msm_draw_points_to_eps(writer,mode_view.points()[i],
00199 params.point_radius);
00200 writer.set_colour(params.line_colour);
00201 writer.set_line_width(params.line_width);
00202 if (params.overlap_shapes)
00203 {
00204
00205 if (i<n_shapes/2) writer.ofs()<<"[3 2] 0 setdash"<<vcl_endl;
00206 else
00207 if (i==n_shapes/2) writer.ofs()<<"[1 0] 0 setdash"<<vcl_endl;
00208 else
00209 writer.ofs()<<"[1 2] 0 setdash"<<vcl_endl;
00210 }
00211 msm_draw_shape_to_eps(writer,mode_view.points()[i],curves);
00212 }
00213 writer.close();
00214 vcl_cout<<"Saved to "<<ss.str()<<vcl_endl;
00215 }
00216
00217
00218 void draw_mode_frames(msm_shape_mode_view& mode_view,
00219 const msm_curves& curves,
00220 tool_params& params)
00221 {
00222 mode_view.compute_shapes();
00223 unsigned m = mode_view.mode();
00224 vgl_box_2d<int> win_box = mode_view.display_window();
00225
00226 unsigned n_shapes = mode_view.points().size();
00227 for (unsigned i=0;i<2*n_shapes-2;++i)
00228 {
00229
00230 unsigned f=i;
00231 if (i>=n_shapes) f=2*n_shapes-2-i;
00232
00233 vcl_stringstream ss;
00234 ss<<params.output_dir<<'/'<<params.base_name<<"_s"<<m<<'_';
00235 if (i<10) ss<<'0';
00236 ss<<i<<".eps";
00237 mbl_eps_writer writer(ss.str().c_str(),
00238 win_box.width(),win_box.height());
00239
00240 writer.set_colour(params.point_colour);
00241 if (params.point_radius>0)
00242 msm_draw_points_to_eps(writer,mode_view.points()[f],
00243 params.point_radius);
00244 writer.set_colour(params.line_colour);
00245 writer.set_line_width(params.line_width);
00246 msm_draw_shape_to_eps(writer,mode_view.points()[f],curves);
00247
00248 writer.close();
00249 }
00250 vcl_cout<<"Saved "<<2*n_shapes-2<<" frames to "
00251 <<params.base_name<<"_s"<<m<<"_XX.eps"<<vcl_endl;
00252 }
00253
00254
00255
00256
00257
00258 msm_shape_model create_subspace_model(
00259 const msm_shape_model& shape_model,
00260 const vcl_string& mode_path,
00261 const vcl_string& var_path)
00262 {
00263
00264 vnl_matrix<double> Q;
00265 vcl_ifstream Qs(mode_path.c_str());
00266 if (!Qs)
00267 {
00268 vcl_cout<<"Failed to open "<<mode_path<<vcl_endl;
00269 vcl_abort();
00270 }
00271
00272 if (!Q.read_ascii(Qs))
00273 {
00274 vcl_cerr<<"Failed to read matrix from "<<mode_path<<'\n';
00275 vcl_abort();
00276 }
00277 Qs.close();
00278
00279 vnl_vector<double> new_var;
00280 vcl_ifstream Vs(var_path.c_str());
00281 if (!Vs)
00282 {
00283 vcl_cout<<"Failed to open "<<var_path<<vcl_endl;
00284 vcl_abort();
00285 }
00286 if (!new_var.read_ascii(Vs))
00287 {
00288 vcl_cerr<<"Failed to read vector from "<<var_path<<'\n';
00289 vcl_abort();
00290 }
00291 Vs.close();
00292
00293 vcl_cout<<"new_var: "<<new_var<<vcl_endl;
00294
00295 vcl_cerr<<"Number of subspace modes = "<<Q.columns()<<'\n';
00296
00297 if (Q.columns()!=new_var.size())
00298 {
00299 vcl_cerr<<"Number of variances = "<<new_var.size()<<'\n'
00300 <<"Numbers differ."<<'\n';
00301 vcl_abort();
00302 }
00303
00304 if (Q.rows()>shape_model.n_modes())
00305 {
00306 vcl_cerr<<"More rows in matrix than number of modes available."<<'\n';
00307 vcl_abort();
00308 }
00309
00310 const vnl_matrix<double>& allP = shape_model.modes();
00311 vnl_matrix<double> subP = allP.extract(allP.rows(),Q.rows());
00312
00313 vnl_matrix<double> newP = subP * Q;
00314
00315 msm_shape_model new_model;
00316 new_model.set(shape_model.mean_points(),newP,new_var,
00317 shape_model.default_pose(),
00318 shape_model.aligner(),
00319 shape_model.param_limiter());
00320
00321 return new_model;
00322 }
00323
00324 int main(int argc, char** argv)
00325 {
00326 vul_arg<vcl_string> param_path("-p","Parameter filename");
00327 vul_arg_parse(argc,argv);
00328
00329 msm_add_all_loaders();
00330
00331 if (param_path()=="")
00332 {
00333 print_usage();
00334 return 0;
00335 }
00336
00337 tool_params params;
00338 try
00339 {
00340 params.read_from_file(param_path());
00341 }
00342 catch (mbl_exception_parse_error& e)
00343 {
00344 vcl_cerr<<"Error: "<<e.what()<<'\n';
00345 return 1;
00346 }
00347
00348 msm_shape_model shape_model;
00349
00350 if (!vsl_quick_file_load(shape_model,params.shape_model_path))
00351 {
00352 vcl_cerr<<"Failed to load shape model from "
00353 <<params.shape_model_path<<'\n';
00354 return 2;
00355 }
00356
00357 vcl_cout<<"Model: "<<shape_model<<vcl_endl;
00358 vcl_cerr<<"First mode variances are ";
00359 for (unsigned i=0;i<8;++i)
00360 if (i<shape_model.n_modes())
00361 vcl_cout<<shape_model.mode_var()[i]<<' ';
00362 vcl_cout<<vcl_endl;
00363
00364 if (params.subspace_mode_path!="")
00365 shape_model = create_subspace_model(shape_model,
00366 params.subspace_mode_path,
00367 params.subspace_var_path);
00368
00369 msm_curves curves;
00370 if (!curves.read_text_file(params.curves_path))
00371 vcl_cerr<<"Failed to read in curves from "<<params.curves_path<<'\n';
00372
00373 msm_shape_mode_view mode_view;
00374 mode_view.set_shape_model(shape_model);
00375 #if 0
00376
00377 vgl_box_2d<double> bounds = shape_model.mean_points().bounds();
00378 double asp=bounds.height()/(1e-3+bounds.width());
00379
00380 int win_width;
00381 if (params.overlap_shapes)
00382 win_width=int(params.width);
00383 else
00384 win_width=int(params.width*params.n_per_mode);
00385
00386 int win_height=int(asp*params.width);
00387 mode_view.set_display_window(vgl_box_2d<int>(0,win_width, 0,win_height));
00388 #endif // 0
00389 mode_view.set_range(params.n_sds);
00390 mode_view.set_n_per_mode(params.n_per_mode);
00391 mode_view.set_overlap_shapes(params.overlap_shapes);
00392 mode_view.set_display_width(params.width);
00393 vgl_box_2d<int> win_box = mode_view.display_window();
00394
00395 unsigned n_modes = vcl_min(params.max_modes,shape_model.n_modes());
00396
00397 for (unsigned m=0;m<n_modes;++m)
00398 {
00399 mode_view.set_mode(1+m);
00400
00401 if (params.make_movie)
00402 draw_mode_frames(mode_view,curves,params);
00403 else
00404 draw_mode(mode_view,curves,params);
00405 }
00406 return 0;
00407 }