00001 #include "mfpf_mr_point_finder.h"
00002
00003
00004
00005
00006
00007 #include <mfpf/mfpf_prune_overlaps.h>
00008
00009 #include <vimt/vimt_image_pyramid.h>
00010 #include <vil/vil_save.h>
00011 #include <vcl_cmath.h>
00012 #include <vcl_cassert.h>
00013 #include <vcl_cstdlib.h>
00014 #include <vcl_sstream.h>
00015
00016 #include <vsl/vsl_indent.h>
00017 #include <vsl/vsl_binary_loader.h>
00018 #include <vsl/vsl_vector_io.h>
00019
00020
00021
00022
00023
00024 mfpf_mr_point_finder::mfpf_mr_point_finder()
00025 : max_after_pruning_(0)
00026 {
00027 }
00028
00029
00030
00031
00032
00033
00034 mfpf_mr_point_finder::~mfpf_mr_point_finder()
00035 {
00036 }
00037
00038
00039
00040 void mfpf_mr_point_finder::set_max_after_pruning(unsigned max_n)
00041 {
00042 max_after_pruning_=max_n;
00043 }
00044
00045
00046 void mfpf_mr_point_finder::set(const vcl_vector<mfpf_point_finder*>& finders)
00047 {
00048 finders_.resize(finders.size());
00049 for (unsigned i=0;i<finders.size();++i)
00050 finders_[i]=*finders[i];
00051 }
00052
00053
00054
00055
00056 unsigned mfpf_mr_point_finder::image_level(
00057 unsigned i, const mfpf_pose& pose,
00058 const vimt_image_pyramid& im_pyr) const
00059 {
00060 return finder(i).image_level(pose,im_pyr);
00061 }
00062
00063
00064 static unsigned nearest_valid_level(const vimt_image_pyramid& im_pyr,
00065 unsigned level)
00066 {
00067 int L0=int(level);
00068 int bestL=0;
00069 int min_d2=999;
00070 for (int L=0;L<=im_pyr.hi();++L)
00071 {
00072 if (im_pyr(L).image_size()[0]>0)
00073 {
00074 int d2 = (L-L0)*(L-L0);
00075 if (d2<min_d2) { min_d2=d2; bestL=L; }
00076 }
00077 }
00078 return unsigned(bestL);
00079 }
00080
00081
00082 void mfpf_mr_point_finder::get_sample_vector(
00083 const vimt_image_pyramid& image_pyr,
00084 const vgl_point_2d<double>& p,
00085 const vgl_vector_2d<double>& u,
00086 unsigned L,
00087 vcl_vector<double>& v)
00088 {
00089 assert( L<finders_.size() );
00090
00091 unsigned im_L = image_level(L,mfpf_pose(p,u),image_pyr);
00092
00093 if (image_pyr(im_L).image_size()[0]==0)
00094 {
00095 vcl_cerr<<"Image at level "<<im_L<<" in pyramid has not been set up.\n"
00096 <<"This is required for level "<<L<<" of the mfpf model.\n"
00097 <<"Check range for which pyramid is defined.\n";
00098
00099 im_L=nearest_valid_level(image_pyr,im_L);
00100 if (image_pyr(im_L).image_size()[0]==0)
00101 {
00102 vcl_cerr << "No image pyramid levels set up.\n";
00103 vcl_abort();
00104 }
00105 }
00106
00107 assert(image_pyr(im_L).is_a()=="vimt_image_2d_of<float>");
00108 const vimt_image_2d_of<float>& image
00109 = static_cast<const vimt_image_2d_of<float>&>(image_pyr(im_L));
00110
00111 finders_[L]->get_sample_vector(image,p,u,v);
00112 }
00113
00114
00115
00116
00117
00118 double mfpf_mr_point_finder::search(const vimt_image_pyramid& im_pyr,
00119 const mfpf_pose& pose0,
00120 mfpf_pose& best_pose)
00121 {
00122 mfpf_pose pose=pose0;
00123 double fit = 9e99;
00124
00125
00126 for (int L = size()-1; L>=0;--L)
00127 {
00128 unsigned im_L = image_level(L,pose0,im_pyr);
00129 assert(im_pyr(im_L).is_a()=="vimt_image_2d_of<float>");
00130 const vimt_image_2d_of<float>& image
00131 = static_cast<const vimt_image_2d_of<float>&>(im_pyr(im_L));
00132 fit = finder(L).search_with_opt(image,pose.p(),pose.u(),
00133 best_pose.p(),best_pose.u());
00134 pose=best_pose;
00135 }
00136
00137 return fit;
00138 }
00139
00140
00141
00142
00143
00144 double mfpf_mr_point_finder::mr_search(
00145 const vimt_image_pyramid& im_pyr,
00146 mfpf_pose& pose, int L_lo, int L_hi)
00147 {
00148 mfpf_pose pose0=pose;
00149 double fit = 9e99;
00150
00151 assert(L_hi>=L_lo);
00152
00153
00154 for (int L = L_hi; L>=L_lo;--L)
00155 {
00156 unsigned im_L = image_level(L,pose0,im_pyr);
00157 assert(im_pyr(im_L).is_a()=="vimt_image_2d_of<float>");
00158 const vimt_image_2d_of<float>& image
00159 = static_cast<const vimt_image_2d_of<float>&>(im_pyr(im_L));
00160 fit = finder(L).search_with_opt(image,pose0.p(),pose0.u(),
00161 pose.p(),pose.u());
00162 pose0=pose;
00163 }
00164
00165 return fit;
00166 }
00167
00168
00169
00170
00171 void mfpf_mr_point_finder::refine_match(
00172 const vimt_image_pyramid& im_pyr,
00173 mfpf_pose& pose, double& fit, unsigned L)
00174 {
00175 unsigned im_L = image_level(L,pose,im_pyr);
00176 assert(im_pyr(im_L).is_a()=="vimt_image_2d_of<float>");
00177 const vimt_image_2d_of<float>& image
00178 = static_cast<const vimt_image_2d_of<float>&>(im_pyr(im_L));
00179 finder(L).refine_match(image,pose.p(),pose.u(),fit);
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189 void mfpf_mr_point_finder::multi_search(
00190 const vimt_image_pyramid& im_pyr,
00191 const mfpf_pose& pose0,
00192 vcl_vector<mfpf_pose>& poses,
00193 vcl_vector<double>& fits)
00194 {
00195 poses.resize(0); fits.resize(0);
00196
00197
00198 int L=size()-1;
00199 unsigned im_L = image_level(L,pose0,im_pyr);
00200 assert(im_pyr(im_L).is_a()=="vimt_image_2d_of<float>");
00201 const vimt_image_2d_of<float>& image
00202 = static_cast<const vimt_image_2d_of<float>&>(im_pyr(im_L));
00203 finder(L).multi_search(image,pose0.p(),pose0.u(),poses,fits);
00204
00205 if (L==0) return;
00206
00207
00208 for (unsigned i=0;i<poses.size();++i)
00209 {
00210 fits[i] = mr_search(im_pyr,poses[i],0,L-1);
00211 }
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 void mfpf_mr_point_finder::multi_search_and_prune(
00226 const vimt_image_pyramid& im_pyr,
00227 const mfpf_pose& pose0,
00228 vcl_vector<mfpf_pose>& poses,
00229 vcl_vector<double>& fits,
00230 int prune_level)
00231 {
00232 poses.resize(0); fits.resize(0);
00233
00234
00235 prune_level=(prune_level+size())%size();
00236 if (prune_level<0) prune_level+=size();
00237
00238
00239 int L0=size()-1;
00240 unsigned im_L = image_level(L0,pose0,im_pyr);
00241 assert(im_pyr(im_L).is_a()=="vimt_image_2d_of<float>");
00242 const vimt_image_2d_of<float>& image
00243 = static_cast<const vimt_image_2d_of<float>&>(im_pyr(im_L));
00244 finder(L0).multi_search(image,pose0.p(),pose0.u(),poses,fits);
00245
00246 if (poses.size()==0)
00247 {
00248 vcl_cerr<<"Warning: No poses returned by mfpf_point_finder\n";
00249
00250 vgl_point_2d<double> new_p;
00251 double f = finder(L0).search_one_pose(image,pose0.p(),pose0.u(),new_p);
00252 poses.resize(1); poses[0]=mfpf_pose(new_p,pose0.u());
00253 fits.resize(1); fits[0]=f;
00254 }
00255
00256 if (L0==prune_level)
00257 mfpf_prune_and_sort_overlaps(finder(L0),poses,fits,max_after_pruning_);
00258
00259
00260 if (L0==0) return;
00261
00262 for (int L=L0-1;L>=0;--L)
00263 {
00264
00265 for (unsigned i=0;i<poses.size();++i)
00266 {
00267 fits[i] = mr_search(im_pyr,poses[i],L,L);
00268 }
00269
00270
00271 if (L==prune_level)
00272 {
00273 mfpf_prune_and_sort_overlaps(finder(L),poses,fits,max_after_pruning_);
00274
00275 }
00276 }
00277 }
00278
00279
00280
00281 void mfpf_mr_point_finder::save_images_of_models(const vcl_string& basepath) const
00282 {
00283 for (unsigned L=0;L<size();++L)
00284 {
00285 vcl_stringstream s;
00286 s<<basepath<<"_L"<<L<<".png";
00287 vimt_image_2d_of<vxl_byte> image;
00288 finder(L).get_image_of_model(image);
00289 if (vil_save(image.image(),s.str().c_str()))
00290 vcl_cout<<"Saved image to "<<s.str()<<vcl_endl;
00291 else
00292 vcl_cout<<"Failed to save image to "<<s.str()<<vcl_endl;
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301 short mfpf_mr_point_finder::version_no() const
00302 {
00303 return 2;
00304 }
00305
00306
00307
00308
00309
00310
00311 vcl_string mfpf_mr_point_finder::is_a() const
00312 {
00313 return vcl_string("mfpf_mr_point_finder");
00314 }
00315
00316
00317 void mfpf_mr_point_finder::print_summary(vcl_ostream& os) const
00318 {
00319 os<<'\n';
00320 unsigned n=finders_.size();
00321 os<<vsl_indent()<<"n_finders: "<<n<<'\n';
00322 vsl_indent_inc(os);
00323 for (unsigned i=0;i<n;i++)
00324 {
00325 os<<vsl_indent()<<i<<") ";
00326 vsl_indent_inc(os);
00327 os<<finders_[i]<<'\n';
00328 vsl_indent_dec(os);
00329 }
00330 vsl_indent_dec(os);
00331 }
00332
00333
00334
00335
00336
00337 void mfpf_mr_point_finder::b_write(vsl_b_ostream& bfs) const
00338 {
00339 vsl_b_write(bfs,version_no());
00340 vsl_b_write(bfs,finders_.size());
00341 for (unsigned i=0;i<finders_.size();++i)
00342 vsl_b_write(bfs,finders_[i]);
00343 vsl_b_write(bfs,max_after_pruning_);
00344 }
00345
00346
00347
00348
00349
00350 void mfpf_mr_point_finder::b_read(vsl_b_istream& bfs)
00351 {
00352 if (!bfs) return;
00353 short version;
00354 vsl_b_read(bfs,version);
00355 unsigned n;
00356 switch (version)
00357 {
00358 case (1):
00359 case (2):
00360 vsl_b_read(bfs,n);
00361 finders_.resize(n);
00362 for (unsigned i=0;i<n;++i) vsl_b_read(bfs,finders_[i]);
00363 if (version==1) max_after_pruning_=0;
00364 else vsl_b_read(bfs,max_after_pruning_);
00365 break;
00366 default:
00367 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&)\n"
00368 << " Unknown version number "<< version << vcl_endl;
00369 bfs.is().clear(vcl_ios::badbit);
00370 return;
00371 }
00372 }
00373
00374
00375
00376
00377
00378 vcl_ostream& operator<<(vcl_ostream& os,const mfpf_mr_point_finder& b)
00379 {
00380 os << b.is_a() << ": ";
00381 vsl_indent_inc(os);
00382 b.print_summary(os);
00383 vsl_indent_dec(os);
00384 return os;
00385 }
00386
00387
00388 void vsl_b_write(vsl_b_ostream& bfs, const mfpf_mr_point_finder& b)
00389 {
00390 b.b_write(bfs);
00391 }
00392
00393
00394 void vsl_b_read(vsl_b_istream& bfs, mfpf_mr_point_finder& b)
00395 {
00396 b.b_read(bfs);
00397 }
00398
00399