00001 #include "mfpf_hog_box_finder_builder.h"
00002
00003
00004
00005
00006
00007 #include <mfpf/mfpf_hog_box_finder.h>
00008 #include <vsl/vsl_binary_loader.h>
00009 #include <vul/vul_string.h>
00010 #include <vcl_cmath.h>
00011 #include <vcl_sstream.h>
00012 #include <vcl_cassert.h>
00013
00014 #include <mbl/mbl_parse_block.h>
00015 #include <mbl/mbl_read_props.h>
00016 #if 0
00017 #include <mbl/mbl_exception.h>
00018 #endif
00019
00020 #include <vil/vil_resample_bilin.h>
00021 #include <vil/vil_image_view.h>
00022 #include <vsl/vsl_vector_io.h>
00023 #include <vsl/vsl_indent.h>
00024 #include <vcl_algorithm.h>
00025
00026 #include <mipa/mipa_orientation_histogram.h>
00027 #include <mipa/mipa_sample_histo_boxes.h>
00028 #include <mipa/mipa_identity_normaliser.h>
00029 #include <mipa/mipa_block_normaliser.h>
00030 #include <mipa/mipa_ms_block_normaliser.h>
00031
00032
00033
00034 inline void mfpf_norm_histo_vec(vnl_vector<double>& v, unsigned nA)
00035 {
00036 unsigned n=v.size();
00037 double sum = 0.0;
00038 for (unsigned i=1;i<=nA;++i) sum+=v[n-i];
00039 v/=sum;
00040 }
00041
00042
00043
00044
00045
00046 mfpf_hog_box_finder_builder::mfpf_hog_box_finder_builder():normaliser_(mipa_identity_normaliser())
00047 {
00048 set_defaults();
00049 }
00050
00051
00052 void mfpf_hog_box_finder_builder::set_defaults()
00053 {
00054 step_size_=1.0;
00055 search_ni_=5;
00056 search_nj_=5;
00057 nA_=0;
00058 dA_=0.0;
00059
00060 nA_bins_=8;
00061 full360_=true;
00062 nc_=2;
00063 ni_=0;
00064 nj_=0;
00065 ref_x_=0;
00066 ref_y_=0;
00067
00068 overlap_f_=1.0;
00069 }
00070
00071
00072
00073
00074
00075 mfpf_hog_box_finder_builder::~mfpf_hog_box_finder_builder()
00076 {
00077 }
00078
00079
00080 mfpf_point_finder* mfpf_hog_box_finder_builder::new_finder() const
00081 {
00082 return new mfpf_hog_box_finder();
00083 }
00084
00085 void mfpf_hog_box_finder_builder::set_angle_bins(unsigned nA_bins,
00086 bool full360, unsigned cell_size)
00087 {
00088 nA_bins_ = nA_bins;
00089 full360_ = full360;
00090 nc_ = cell_size;
00091 reconfigure_normaliser();
00092 }
00093
00094
00095
00096
00097 void mfpf_hog_box_finder_builder::set_region_size(double wi, double wj)
00098 {
00099 wi/=(2*nc_*step_size());
00100 wj/=(2*nc_*step_size());
00101 int ni = vcl_max(2,int(0.99+wi));
00102 int nj = vcl_max(2,int(0.99+wj));
00103 set_as_box(unsigned(ni),unsigned(nj),0.5*(ni-1),0.5*(nj-1));
00104 }
00105
00106
00107
00108 void mfpf_hog_box_finder_builder::set_as_box(unsigned ni, unsigned nj,
00109 double ref_x, double ref_y,
00110 const mfpf_vec_cost_builder& builder)
00111 {
00112 set_as_box(ni,nj,ref_x,ref_y);
00113 cost_builder_ = builder.clone();
00114 reconfigure_normaliser();
00115 }
00116
00117
00118 void mfpf_hog_box_finder_builder::set_as_box(unsigned ni, unsigned nj,
00119 double ref_x, double ref_y)
00120 {
00121 ni_=ni; nj_=nj;
00122
00123 ref_x_=ref_x;
00124 ref_y_=ref_y;
00125 reconfigure_normaliser();
00126 }
00127
00128
00129
00130 void mfpf_hog_box_finder_builder::set_as_box(unsigned ni, unsigned nj,
00131 const mfpf_vec_cost_builder& builder)
00132 {
00133 set_as_box(ni,nj, 0.5*(ni-1),0.5*(nj-1), builder);
00134 reconfigure_normaliser();
00135 }
00136
00137
00138
00139
00140 void mfpf_hog_box_finder_builder::clear(unsigned n_egs)
00141 {
00142 unsigned n_per_eg = (1+2*nA_);
00143 cost_builder().clear(n_egs*n_per_eg);
00144 }
00145
00146
00147 void mfpf_hog_box_finder_builder::add_one_example(
00148 const vimt_image_2d_of<float>& image,
00149 const vgl_point_2d<double>& p,
00150 const vgl_vector_2d<double>& u)
00151 {
00152 vgl_vector_2d<double> u1=step_size_*u;
00153 vgl_vector_2d<double> v1(-u1.y(),u1.x());
00154
00155 assert(image.image().nplanes()==1);
00156
00157
00158 unsigned sni = 2+2*nc_*ni_;
00159 unsigned snj = 2+2*nc_*nj_;
00160 vil_image_view<float> sample(sni,snj);
00161
00162 const vgl_point_2d<double> p0 = p-(1+nc_*ref_x_)*u1-(1+nc_*ref_y_)*v1;
00163
00164 const vimt_transform_2d& s_w2i = image.world2im();
00165 vgl_point_2d<double> im_p0 = s_w2i(p0);
00166 vgl_vector_2d<double> im_u = s_w2i.delta(p0, u1);
00167 vgl_vector_2d<double> im_v = s_w2i.delta(p0, v1);
00168
00169 vil_resample_bilin(image.image(),sample,
00170 im_p0.x(),im_p0.y(), im_u.x(),im_u.y(),
00171 im_v.x(),im_v.y(),
00172 sni,snj);
00173
00174 vil_image_view<float> histo_im;
00175 mipa_orientation_histogram(sample,histo_im,nA_bins_,nc_,full360_);
00176
00177 vnl_vector<double> v;
00178 mipa_sample_histo_boxes_3L(histo_im,0,0,v,ni_,nj_);
00179
00180 normaliser_->normalise(v);
00181
00182
00183 cost_builder().add_example(v);
00184 }
00185
00186
00187 void mfpf_hog_box_finder_builder::add_example(const vimt_image_2d_of<float>& image,
00188 const vgl_point_2d<double>& p,
00189 const vgl_vector_2d<double>& u)
00190 {
00191 if (nA_==0)
00192 {
00193 add_one_example(image,p,u);
00194 return;
00195 }
00196
00197 vgl_vector_2d<double> v(-u.y(),u.x());
00198 for (int iA=-int(nA_);iA<=(int)nA_;++iA)
00199 {
00200 double A = iA*dA_;
00201 vgl_vector_2d<double> uA = u*vcl_cos(A)+v*vcl_sin(A);
00202 add_one_example(image,p,uA);
00203 }
00204 }
00205
00206
00207 void mfpf_hog_box_finder_builder::build(mfpf_point_finder& pf)
00208 {
00209 assert(pf.is_a()=="mfpf_hog_box_finder");
00210 mfpf_hog_box_finder& rp = static_cast<mfpf_hog_box_finder&>(pf);
00211
00212 mfpf_vec_cost *cost = cost_builder().new_cost();
00213
00214 cost_builder().build(*cost);
00215
00216 rp.set(nA_bins_,full360_,ni_,nj_,nc_,
00217 ref_x_,ref_y_,*cost,normaliser_);
00218 set_base_parameters(rp);
00219 rp.set_overlap_f(overlap_f_);
00220
00221 vcl_cout<<"Model: "<<rp<<vcl_endl;
00222
00223
00224 delete cost;
00225 }
00226
00227
00228
00229
00230
00231
00232 bool mfpf_hog_box_finder_builder::set_from_stream(vcl_istream &is)
00233 {
00234
00235 vcl_string s = mbl_parse_block(is);
00236 vcl_istringstream ss(s);
00237 mbl_read_props_type props = mbl_read_props_ws(ss);
00238
00239 set_defaults();
00240
00241
00242 parse_base_props(props);
00243
00244 nc_=vul_string_atoi(props.get_optional_property("nc","2"));
00245 nA_bins_=vul_string_atoi(props.get_optional_property("nA_bins","8"));
00246 full360_=vul_string_to_bool(props.get_optional_property("full360","true"));
00247 ni_=vul_string_atoi(props.get_optional_property("ni","4"));
00248 nj_=vul_string_atoi(props.get_optional_property("nj","4"));
00249
00250 bool reonfigureNormaliser=false;
00251 if (props.find("norm")!=props.end())
00252 {
00253 vcl_istringstream ss2(props["norm"]);
00254 mbl_read_props_type dummy_extra_props;
00255 vcl_auto_ptr<mipa_vector_normaliser> norm = mipa_vector_normaliser::new_normaliser_from_stream(ss2, dummy_extra_props);
00256 normaliser_=norm.release();
00257 reonfigureNormaliser=true;
00258 #if 0
00259 if (props["norm"]=="none") norm_method_=0;
00260 else
00261 if (props["norm"]=="linear") norm_method_=1;
00262 else throw mbl_exception_parse_error("Unknown norm: "+props["norm"]);
00263 #endif
00264
00265 props.erase("norm");
00266 }
00267
00268 overlap_f_=vul_string_atof(props.get_optional_property("overlap_f","1.0"));
00269
00270 if (props.find("ref_x")!=props.end())
00271 {
00272 ref_x_=vul_string_atof(props["ref_x"]);
00273 props.erase("ref_x");
00274 }
00275 else ref_x_=0.5*(ni_-1);
00276
00277 if (props.find("ref_y")!=props.end())
00278 {
00279 ref_y_=vul_string_atof(props["ref_y"]);
00280 props.erase("ref_y");
00281 }
00282 else ref_y_=0.5*(nj_-1);
00283
00284 if (props.find("nA")!=props.end())
00285 {
00286 nA_=vul_string_atoi(props["nA"]);
00287 props.erase("nA");
00288 }
00289
00290 if (props.find("dA")!=props.end())
00291 {
00292 dA_=vul_string_atof(props["dA"]);
00293 props.erase("dA");
00294 }
00295
00296 if (props.find("cost_builder")!=props.end())
00297 {
00298 vcl_istringstream b_ss(props["cost_builder"]);
00299 vcl_auto_ptr<mfpf_vec_cost_builder> bb =
00300 mfpf_vec_cost_builder::create_from_stream(b_ss);
00301 cost_builder_ = bb->clone();
00302 props.erase("cost_builder");
00303 }
00304
00305
00306 if (reonfigureNormaliser)
00307 {
00308 reconfigure_normaliser();
00309 }
00310
00311 mbl_read_props_look_for_unused_props(
00312 "mfpf_hog_box_finder_builder::set_from_stream", props, mbl_read_props_type());
00313 return true;
00314 }
00315
00316 void mfpf_hog_box_finder_builder::reconfigure_normaliser()
00317 {
00318 mipa_vector_normaliser* pNormaliser=normaliser_.ptr();
00319 mipa_block_normaliser* pBlockNormaliser= dynamic_cast<mipa_block_normaliser*>(pNormaliser);
00320 if (pBlockNormaliser)
00321 {
00322 pBlockNormaliser->set_region(2*ni_,2*nj_);
00323 pBlockNormaliser->set_nbins(nA_bins_);
00324
00325 mipa_ms_block_normaliser* pMSBlockNormaliser= dynamic_cast<mipa_ms_block_normaliser*>(pNormaliser);
00326 if (pMSBlockNormaliser)
00327 {
00328 pMSBlockNormaliser->set_nscales(2);
00329 pMSBlockNormaliser->set_include_overall_histogram(true);
00330 }
00331 else
00332 {
00333 vcl_cerr<<"WARNING from fpf_hog_box_finder_builder::reconfigure_normaliser...\n"
00334 <<"The normaliser may not be multi-scale but this HOG Builder uses multi-scale histograms\n";
00335 }
00336 }
00337 }
00338
00339
00340
00341
00342
00343 vcl_string mfpf_hog_box_finder_builder::is_a() const
00344 {
00345 return vcl_string("mfpf_hog_box_finder_builder");
00346 }
00347
00348
00349 mfpf_point_finder_builder* mfpf_hog_box_finder_builder::clone() const
00350 {
00351 return new mfpf_hog_box_finder_builder(*this);
00352 }
00353
00354
00355
00356
00357
00358 void mfpf_hog_box_finder_builder::print_summary(vcl_ostream& os) const
00359 {
00360 os << "{ "<<'\n';
00361 vsl_indent_inc(os);
00362 os << vsl_indent()<<"size: " << ni_ << 'x' << nj_
00363 << " nc: " << nc_ <<" nA_bins: "<<nA_bins_
00364 << " ref_pt: (" << ref_x_ << ',' << ref_y_ << ')' <<'\n';
00365 if (full360_) os<<vsl_indent()<<"Angle range: 0-360"<<'\n';
00366 else os<<vsl_indent()<<"Angle range: 0-180"<<'\n';
00367 vcl_cout<<"The HOG's normaliser is:"<<'\n';
00368 normaliser_->print_summary(os);
00369
00370
00371 os <<vsl_indent()<< "cost_builder: ";
00372 if (cost_builder_.ptr()==0) os << '-'<<'\n';
00373 else os << cost_builder_<<'\n';
00374 os <<vsl_indent()<< "nA: " << nA_ << " dA: " << dA_ << ' '<<'\n'
00375 <<vsl_indent();
00376 mfpf_point_finder_builder::print_summary(os);
00377 os <<'\n'
00378 <<vsl_indent()<<"overlap_f: "<<overlap_f_<<'\n';
00379 vsl_indent_dec(os);
00380 os <<vsl_indent()<< '}';
00381 }
00382
00383
00384 short mfpf_hog_box_finder_builder::version_no() const
00385 {
00386 return 2;
00387 }
00388
00389 void mfpf_hog_box_finder_builder::b_write(vsl_b_ostream& bfs) const
00390 {
00391 vsl_b_write(bfs,version_no());
00392 mfpf_point_finder_builder::b_write(bfs);
00393 vsl_b_write(bfs,nc_);
00394 vsl_b_write(bfs,ni_);
00395 vsl_b_write(bfs,nj_);
00396 vsl_b_write(bfs,nA_bins_);
00397 vsl_b_write(bfs,full360_);
00398 vsl_b_write(bfs,ref_x_);
00399 vsl_b_write(bfs,ref_y_);
00400 vsl_b_write(bfs,nA_);
00401 vsl_b_write(bfs,dA_);
00402 vsl_b_write(bfs,cost_builder_);
00403 vsl_b_write(bfs,normaliser_);
00404 vsl_b_write(bfs,overlap_f_);
00405 }
00406
00407
00408
00409
00410
00411 void mfpf_hog_box_finder_builder::b_read(vsl_b_istream& bfs)
00412 {
00413 if (!bfs) return;
00414 short version;
00415 vsl_b_read(bfs,version);
00416 switch (version)
00417 {
00418 case (1):
00419 case (2):
00420 mfpf_point_finder_builder::b_read(bfs);
00421 vsl_b_read(bfs,nc_);
00422 vsl_b_read(bfs,ni_);
00423 vsl_b_read(bfs,nj_);
00424 vsl_b_read(bfs,nA_bins_);
00425 vsl_b_read(bfs,full360_);
00426 vsl_b_read(bfs,ref_x_);
00427 vsl_b_read(bfs,ref_y_);
00428 vsl_b_read(bfs,nA_);
00429 vsl_b_read(bfs,dA_);
00430 vsl_b_read(bfs,cost_builder_);
00431 vsl_b_read(bfs,normaliser_);
00432 if (version==1) overlap_f_=1.0;
00433 else vsl_b_read(bfs,overlap_f_);
00434 break;
00435 default:
00436 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&)\n"
00437 << " Unknown version number "<< version << '\n';
00438 bfs.is().clear(vcl_ios::badbit);
00439 return;
00440 }
00441 }