00001 #include "mfpf_region_finder_builder.h"
00002
00003
00004
00005
00006
00007 #include <mfpf/mfpf_region_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 #include <mbl/mbl_exception.h>
00017
00018 #include <vil/vil_resample_bilin.h>
00019 #include <vsl/vsl_vector_io.h>
00020 #include <vsl/vsl_indent.h>
00021
00022 #include <vgl/vgl_point_2d.h>
00023 #include <vgl/vgl_vector_2d.h>
00024 #include <mfpf/mfpf_sample_region.h>
00025 #include <mfpf/mfpf_norm_vec.h>
00026
00027
00028
00029
00030
00031 mfpf_region_finder_builder::mfpf_region_finder_builder()
00032 {
00033 set_defaults();
00034 }
00035
00036
00037 void mfpf_region_finder_builder::set_defaults()
00038 {
00039 step_size_=1.0;
00040 search_ni_=5;
00041 search_nj_=5;
00042 n_pixels_=0;
00043 roi_.resize(0);
00044 roi_ni_=0;
00045 roi_nj_=0;
00046 ref_x_=0;
00047 ref_y_=0;
00048 nA_=0;
00049 dA_=0.0;
00050 norm_method_=1;
00051 overlap_f_=1.0;
00052 var_min_ = 1.0E-6;
00053 tvar_min_=1.0E30;
00054 num_examples_=0;
00055 estimate_var_min_=true;
00056 }
00057
00058
00059
00060
00061
00062 mfpf_region_finder_builder::~mfpf_region_finder_builder()
00063 {
00064 }
00065
00066
00067 mfpf_point_finder* mfpf_region_finder_builder::new_finder() const
00068 {
00069 return new mfpf_region_finder();
00070 }
00071
00072
00073
00074
00075
00076 void mfpf_region_finder_builder::set_region(const mfpf_region_form& form)
00077 {
00078 step_size_ = form.pose().scale();
00079
00080 if (form.form()=="box")
00081 {
00082 int ni = vcl_max(1,int(0.99+form.wi()));
00083 int nj = vcl_max(1,int(0.99+form.wj()));
00084 set_as_box(unsigned(ni),unsigned(nj),0.5*ni,0.5*nj);
00085 }
00086 else
00087 if (form.form()=="ellipse")
00088 {
00089 double ri = vcl_max(1.0,form.wi());
00090 double rj = vcl_max(1.0,form.wj());
00091 set_as_ellipse(ri,rj);
00092 }
00093 else
00094 {
00095 vcl_cerr<<"mfpf_region_finder_builder::set_region : Unknown form: "<<form<<vcl_endl;
00096 vcl_abort();
00097 }
00098 }
00099
00100
00101
00102
00103 void mfpf_region_finder_builder::set_region_size(double wi, double wj)
00104 {
00105 wi/=step_size();
00106 wj/=step_size();
00107 int ni = vcl_max(1,int(0.99+wi));
00108 int nj = vcl_max(1,int(0.99+wj));
00109 set_as_box(unsigned(ni),unsigned(nj),0.5*(ni-1),0.5*(nj-1));
00110 }
00111
00112
00113
00114 void mfpf_region_finder_builder::set_as_box(unsigned ni, unsigned nj,
00115 double ref_x, double ref_y,
00116 const mfpf_vec_cost_builder& builder)
00117 {
00118 set_as_box(ni,nj,ref_x,ref_y);
00119 cost_builder_ = builder.clone();
00120 }
00121
00122
00123 void mfpf_region_finder_builder::set_as_box(unsigned ni, unsigned nj,
00124 double ref_x, double ref_y)
00125 {
00126 roi_ni_=ni; roi_nj_=nj;
00127 n_pixels_ = ni*nj;
00128
00129
00130 roi_.resize(nj);
00131 for (unsigned j=0;j<nj;++j) roi_[j]=mbl_chord(0,ni-1,j);
00132
00133 ref_x_=ref_x;
00134 ref_y_=ref_y;
00135 }
00136
00137
00138
00139 void mfpf_region_finder_builder::set_as_box(unsigned ni, unsigned nj,
00140 const mfpf_vec_cost_builder& builder)
00141 {
00142 set_as_box(ni,nj, 0.5*(ni-1),0.5*(nj-1), builder);
00143 }
00144
00145
00146
00147 void mfpf_region_finder_builder::set_as_ellipse(double ri, double rj,
00148 const mfpf_vec_cost_builder& builder)
00149 {
00150 set_as_ellipse(ri,rj);
00151 cost_builder_ = builder.clone();
00152 }
00153
00154
00155
00156 void mfpf_region_finder_builder::set_as_ellipse(double ri, double rj)
00157 {
00158 ri+=1e-6; rj+=1e-6;
00159 int ni=int(ri);
00160 int nj=int(rj);
00161 roi_.resize(0);
00162 n_pixels_=0;
00163 for (int j = -nj;j<=nj;++j)
00164 {
00165
00166 int x = int(ri*vcl_sqrt(1.0-j*j/(rj*rj)));
00167 roi_.push_back(mbl_chord(ni-x,ni+x,nj+j));
00168 n_pixels_+=2*x+1;
00169 }
00170
00171 ref_x_=ni;
00172 ref_y_=nj;
00173 roi_ni_=2*ni+1;
00174 roi_nj_=2*nj+1;
00175 }
00176
00177
00178 unsigned mfpf_region_finder_builder::model_dim()
00179 {
00180 return n_pixels_;
00181 }
00182
00183
00184
00185 void mfpf_region_finder_builder::clear(unsigned n_egs)
00186 {
00187 unsigned n_per_eg = (1+2*nA_);
00188 cost_builder().clear(n_egs*n_per_eg);
00189 }
00190
00191
00192 void mfpf_region_finder_builder::add_one_example(
00193 const vimt_image_2d_of<float>& image,
00194 const vgl_point_2d<double>& p,
00195 const vgl_vector_2d<double>& u)
00196 {
00197 vgl_vector_2d<double> u1=step_size_*u;
00198 vgl_vector_2d<double> v1(-u1.y(),u1.x());
00199
00200 unsigned np=image.image().nplanes();
00201
00202 vil_image_view<float> sample(roi_ni_,roi_nj_,1,np);
00203
00204 const vgl_point_2d<double> p0 = p-ref_x_*u1-ref_y_*v1;
00205
00206 const vimt_transform_2d& s_w2i = image.world2im();
00207 vgl_point_2d<double> im_p0 = s_w2i(p0);
00208 vgl_vector_2d<double> im_u = s_w2i.delta(p0, u1);
00209 vgl_vector_2d<double> im_v = s_w2i.delta(p0, v1);
00210
00211 vil_resample_bilin(image.image(),sample,
00212 im_p0.x(),im_p0.y(), im_u.x(),im_u.y(),
00213 im_v.x(),im_v.y(),roi_ni_,roi_nj_);
00214
00215 vnl_vector<double> v(n_pixels_*sample.nplanes());
00216 mfpf_sample_region(sample.top_left_ptr(),sample.jstep(),
00217 np,roi_,v);
00218
00219 if (norm_method_==1)
00220 {
00221 double var=var_min_;
00222 mfpf_norm_vec(v,var_min_,&var);
00223 if (var<tvar_min_)
00224 tvar_min_ = var;
00225 }
00226 cost_builder().add_example(v);
00227 ++num_examples_;
00228 }
00229
00230
00231 void mfpf_region_finder_builder::add_example(const vimt_image_2d_of<float>& image,
00232 const vgl_point_2d<double>& p,
00233 const vgl_vector_2d<double>& u)
00234 {
00235 if (nA_==0)
00236 {
00237 add_one_example(image,p,u);
00238 return;
00239 }
00240
00241 vgl_vector_2d<double> v(-u.y(),u.x());
00242 for (int iA=-int(nA_);iA<=(int)nA_;++iA)
00243 {
00244 double A = iA*dA_;
00245 vgl_vector_2d<double> uA = u*vcl_cos(A)+v*vcl_sin(A);
00246 add_one_example(image,p,uA);
00247 }
00248 }
00249
00250
00251 void mfpf_region_finder_builder::build(mfpf_point_finder& pf)
00252 {
00253 assert(pf.is_a()=="mfpf_region_finder");
00254 mfpf_region_finder& rp = static_cast<mfpf_region_finder&>(pf);
00255
00256 mfpf_vec_cost *cost = cost_builder().new_cost();
00257
00258 cost_builder().build(*cost);
00259
00260 rp.set(roi_,ref_x_,ref_y_,*cost,norm_method_);
00261 set_base_parameters(rp);
00262 rp.set_overlap_f(overlap_f_);
00263
00264 if (estimate_var_min_ && norm_method_==1 && num_examples_>0)
00265 {
00266
00267
00268 double dn=double(num_examples_);
00269 if (dn>0.0)
00270 {
00271 double r=0.925;
00272 double alpha=1.0;
00273 if (dn>50.0)
00274 alpha=0.98;
00275 else
00276 {
00277 alpha=1-vcl_pow(r,dn);
00278 alpha=vcl_min(alpha,0.98);
00279 }
00280 tvar_min_ *= alpha;
00281 var_min_ = vcl_max(var_min_,tvar_min_);
00282 }
00283 rp.set_var_min(var_min_);
00284 }
00285
00286
00287 delete cost;
00288 }
00289
00290
00291
00292 void mfpf_region_finder_builder::config_as_box(vcl_istream &is)
00293 {
00294
00295 vcl_string s = mbl_parse_block(is);
00296 vcl_istringstream ss(s);
00297 mbl_read_props_type props = mbl_read_props_ws(ss);
00298
00299 unsigned ni=5,nj=5;
00300
00301 if (props.find("ni")!=props.end())
00302 {
00303 ni=vul_string_atoi(props["ni"]);
00304 props.erase("ni");
00305 }
00306 if (props.find("nj")!=props.end())
00307 {
00308 nj=vul_string_atoi(props["nj"]);
00309 props.erase("nj");
00310 }
00311
00312 if (props.find("ref_x")!=props.end())
00313 {
00314 ref_x_=vul_string_atof(props["ref_x"]);
00315 props.erase("ref_x");
00316 }
00317 else ref_x_=0.5*(ni-1.0);
00318
00319 if (props.find("ref_y")!=props.end())
00320 {
00321 ref_y_=vul_string_atof(props["ref_y"]);
00322 props.erase("ref_y");
00323 }
00324 else ref_y_=0.5*(nj-1.0);
00325
00326
00327 mbl_read_props_look_for_unused_props(
00328 "mfpf_region_finder_builder::config_as_box",
00329 props, mbl_read_props_type());
00330
00331 set_as_box(ni,nj,ref_x_,ref_y_);
00332 }
00333
00334
00335
00336 void mfpf_region_finder_builder::config_as_ellipse(vcl_istream &is)
00337 {
00338
00339 vcl_string s = mbl_parse_block(is);
00340 vcl_istringstream ss(s);
00341 mbl_read_props_type props = mbl_read_props_ws(ss);
00342
00343 double ri=3.1,rj=3.1;
00344 if (props.find("ri")!=props.end())
00345 {
00346 ri=vul_string_atof(props["ri"]);
00347 props.erase("ri");
00348 }
00349
00350 if (props.find("rj")!=props.end())
00351 {
00352 rj=vul_string_atof(props["rj"]);
00353 props.erase("rj");
00354 }
00355
00356
00357 mbl_read_props_look_for_unused_props(
00358 "mfpf_region_finder_builder::config_as_ellipse",
00359 props, mbl_read_props_type());
00360
00361 set_as_ellipse(ri,rj);
00362 }
00363
00364
00365
00366
00367
00368
00369 bool mfpf_region_finder_builder::set_from_stream(vcl_istream &is)
00370 {
00371
00372 vcl_string s = mbl_parse_block(is);
00373 vcl_istringstream ss(s);
00374 mbl_read_props_type props = mbl_read_props_ws(ss);
00375
00376 set_defaults();
00377
00378
00379 parse_base_props(props);
00380
00381 if (props.find("shape")!=props.end())
00382 {
00383 vcl_istringstream shape_s(props["shape"]);
00384 shape_s>>shape_;
00385 if (shape_=="box")
00386 {
00387
00388 config_as_box(shape_s);
00389 }
00390 else
00391 if (shape_=="ellipse")
00392 {
00393
00394 config_as_ellipse(shape_s);
00395 }
00396 else throw mbl_exception_parse_error("Unknown shape: "+shape_);
00397
00398 props.erase("shape");
00399 }
00400
00401 if (props.find("norm")!=props.end())
00402 {
00403 if (props["norm"]=="none") norm_method_=0;
00404 else
00405 if (props["norm"]=="linear") norm_method_=1;
00406 else throw mbl_exception_parse_error("Unknown norm: "+props["norm"]);
00407
00408 props.erase("norm");
00409 }
00410 if (props.find("estimate_var_min") !=props.end())
00411 {
00412 vcl_string strEstimate=props["estimate_var_min"];
00413 if (strEstimate[0]=='f' || strEstimate[0]=='F' || strEstimate[0]=='0')
00414 estimate_var_min_=false;
00415 else
00416 estimate_var_min_=true;
00417
00418 props.erase("estimate_var_min");
00419 }
00420
00421 overlap_f_=vul_string_atof(props.get_optional_property("overlap_f",
00422 "1.0"));
00423
00424 if (props.find("nA")!=props.end())
00425 {
00426 nA_=vul_string_atoi(props["nA"]);
00427 props.erase("nA");
00428 }
00429
00430 if (props.find("dA")!=props.end())
00431 {
00432 dA_=vul_string_atof(props["dA"]);
00433 props.erase("dA");
00434 }
00435
00436 if (props.find("cost_builder")!=props.end())
00437 {
00438 vcl_istringstream b_ss(props["cost_builder"]);
00439 vcl_auto_ptr<mfpf_vec_cost_builder> bb =
00440 mfpf_vec_cost_builder::create_from_stream(b_ss);
00441 cost_builder_ = bb->clone();
00442 props.erase("cost_builder");
00443 }
00444
00445
00446 mbl_read_props_look_for_unused_props(
00447 "mfpf_region_finder_builder::set_from_stream", props, mbl_read_props_type());
00448 return true;
00449 }
00450
00451
00452
00453
00454
00455 vcl_string mfpf_region_finder_builder::is_a() const
00456 {
00457 return vcl_string("mfpf_region_finder_builder");
00458 }
00459
00460
00461 mfpf_point_finder_builder* mfpf_region_finder_builder::clone() const
00462 {
00463 return new mfpf_region_finder_builder(*this);
00464 }
00465
00466
00467
00468
00469
00470 void mfpf_region_finder_builder::print_summary(vcl_ostream& os) const
00471 {
00472 os << "{ size: " << roi_ni_ << 'x' << roi_nj_
00473 << " n_pixels: " << n_pixels_
00474 << " ref_pt: (" << ref_x_ << ',' << ref_y_ << ')' <<'\n';
00475 vsl_indent_inc(os);
00476 if (norm_method_==0) os<<vsl_indent()<<"norm: none"<<'\n';
00477 else os<<vsl_indent()<<"norm: linear"<<'\n';
00478 os <<vsl_indent()<< "cost_builder: ";
00479 if (cost_builder_.ptr()==0) os << '-'<<'\n';
00480 else os << cost_builder_<<'\n';
00481 os <<vsl_indent()<< "nA: " << nA_ << " dA: " << dA_ << ' '<<'\n'
00482 <<vsl_indent();
00483 mfpf_point_finder_builder::print_summary(os);
00484 os <<'\n' <<vsl_indent()<<"overlap_f: "<<overlap_f_<<'\n';
00485 vsl_indent_dec(os);
00486 os <<vsl_indent()<< '}';
00487 }
00488
00489 void mfpf_region_finder_builder::print_shape(vcl_ostream& os) const
00490 {
00491 vil_image_view<vxl_byte> im(roi_ni_,roi_nj_);
00492 im.fill(0);
00493 for (unsigned k=0;k<roi_.size();++k)
00494 for (int i=roi_[k].start_x();i<=roi_[k].end_x();++i)
00495 im(i,roi_[k].y())=1;
00496 for (unsigned j=0;j<im.nj();++j)
00497 {
00498 for (unsigned i=0;i<im.ni();++i)
00499 if (im(i,j)==0) os<<' ';
00500 else os<<'X';
00501 os<<'\n';
00502 }
00503 }
00504
00505
00506 short mfpf_region_finder_builder::version_no() const
00507 {
00508 return 3;
00509 }
00510
00511 void mfpf_region_finder_builder::b_write(vsl_b_ostream& bfs) const
00512 {
00513 vsl_b_write(bfs,version_no());
00514 mfpf_point_finder_builder::b_write(bfs);
00515 vsl_b_write(bfs,roi_);
00516 vsl_b_write(bfs,roi_ni_);
00517 vsl_b_write(bfs,roi_nj_);
00518 vsl_b_write(bfs,n_pixels_);
00519 vsl_b_write(bfs,ref_x_);
00520 vsl_b_write(bfs,ref_y_);
00521 vsl_b_write(bfs,nA_);
00522 vsl_b_write(bfs,dA_);
00523 vsl_b_write(bfs,cost_builder_);
00524 vsl_b_write(bfs,norm_method_);
00525 vsl_b_write(bfs,overlap_f_);
00526 if (version_no()>2)
00527 vsl_b_write(bfs,var_min_);
00528 }
00529
00530
00531
00532
00533
00534 void mfpf_region_finder_builder::b_read(vsl_b_istream& bfs)
00535 {
00536 if (!bfs) return;
00537 short version;
00538 vsl_b_read(bfs,version);
00539 switch (version)
00540 {
00541 case (1):
00542 case (2):
00543 case (3):
00544 mfpf_point_finder_builder::b_read(bfs);
00545 vsl_b_read(bfs,roi_);
00546 vsl_b_read(bfs,roi_ni_);
00547 vsl_b_read(bfs,roi_nj_);
00548 vsl_b_read(bfs,n_pixels_);
00549 vsl_b_read(bfs,ref_x_);
00550 vsl_b_read(bfs,ref_y_);
00551 vsl_b_read(bfs,nA_);
00552 vsl_b_read(bfs,dA_);
00553 vsl_b_read(bfs,cost_builder_);
00554 vsl_b_read(bfs,norm_method_);
00555 if (version==1)
00556 overlap_f_=1.0;
00557 else
00558 vsl_b_read(bfs,overlap_f_);
00559 if (version>2)
00560 vsl_b_read(bfs,var_min_);
00561 else
00562 var_min_=1.0E-6;
00563 break;
00564 default:
00565 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&)\n"
00566 << " Unknown version number "<< version << vcl_endl;
00567 bfs.is().clear(vcl_ios::badbit);
00568 return;
00569 }
00570 }