00001 #include "mfpf_region_finder.h"
00002
00003
00004
00005
00006
00007 #include <vsl/vsl_binary_loader.h>
00008 #include <vcl_cmath.h>
00009 #include <vcl_cassert.h>
00010
00011 #include <vil/vil_resample_bilin.h>
00012 #include <vil/io/vil_io_image_view.h>
00013 #include <vsl/vsl_vector_io.h>
00014 #include <vsl/vsl_indent.h>
00015
00016 #include <vgl/vgl_point_2d.h>
00017 #include <vgl/vgl_vector_2d.h>
00018 #include <mfpf/mfpf_sample_region.h>
00019 #include <mfpf/mfpf_norm_vec.h>
00020 #include <vnl/vnl_vector.h>
00021 #include <vnl/vnl_c_vector.h>
00022
00023
00024
00025
00026
00027 mfpf_region_finder::mfpf_region_finder()
00028 {
00029 set_defaults();
00030 }
00031
00032
00033 void mfpf_region_finder::set_defaults()
00034 {
00035 step_size_=1.0;
00036 search_ni_=5;
00037 search_nj_=5;
00038 nA_=0; dA_=0.0;
00039 ns_=0; ds_=1.0;
00040 n_pixels_=0;
00041 roi_.resize(0);
00042 roi_ni_=0;
00043 roi_nj_=0;
00044 ref_x_=0;
00045 ref_y_=0;
00046 norm_method_=1;
00047 overlap_f_=1.0;
00048 var_min_ = 1.0E-6;
00049 draw_only_1st_plane_=true;
00050 }
00051
00052
00053
00054
00055
00056 mfpf_region_finder::~mfpf_region_finder()
00057 {
00058 }
00059
00060
00061 void mfpf_region_finder::set(const vcl_vector<mbl_chord>& roi,
00062 double ref_x, double ref_y,
00063 const mfpf_vec_cost& cost,
00064 short norm_method)
00065 {
00066 cost_ = cost.clone();
00067 ref_x_ = ref_x;
00068 ref_y_ = ref_y;
00069
00070
00071 if (roi.size()==0) { roi_ni_=0; roi_nj_=0; return; }
00072 int ilo=roi[0].start_x(), ihi=roi[0].end_x();
00073 int jlo=roi[0].y(), jhi=roi[0].y();
00074
00075 for (unsigned k=1;k<roi.size();++k)
00076 {
00077 if (roi[k].start_x()<ilo) ilo=roi[k].start_x();
00078 if (roi[k].end_x()>ihi) ihi=roi[k].end_x();
00079 if (roi[k].y()<jlo) jlo=roi[k].y();
00080 if (roi[k].y()>jhi) jhi=roi[k].y();
00081 }
00082 roi_ni_=1+ihi-ilo;
00083 roi_nj_=1+jhi-jlo;
00084
00085
00086 ref_x_-=ilo; ref_y_-=jlo;
00087 roi_.resize(roi.size());
00088 n_pixels_=0;
00089 for (unsigned k=0;k<roi.size();++k)
00090 {
00091 roi_[k]= mbl_chord(roi[k].start_x()-ilo,
00092 roi[k].end_x()-ilo, roi[k].y()-jlo);
00093 n_pixels_+=1+roi[k].end_x()-roi[k].start_x();
00094 }
00095
00096 assert(norm_method>=0 && norm_method<=1);
00097 norm_method_ = norm_method;
00098 }
00099
00100
00101
00102 void mfpf_region_finder::set_overlap_f(double f)
00103 {
00104 overlap_f_=f;
00105 }
00106
00107
00108
00109 double mfpf_region_finder::radius() const
00110 {
00111
00112 double wx = roi_ni_-1;
00113 double x2 = vcl_max(ref_x_*ref_x_,(ref_x_-wx)*(ref_x_-wx));
00114 double wy = roi_nj_-1;
00115 double y2 = vcl_max(ref_y_*ref_y_,(ref_y_-wy)*(ref_y_-wy));
00116 double r2 = x2+y2;
00117 if (r2<=1) return 1.0;
00118 return vcl_sqrt(r2);
00119 }
00120
00121
00122
00123
00124 double mfpf_region_finder::evaluate(const vimt_image_2d_of<float>& image,
00125 const vgl_point_2d<double>& p,
00126 const vgl_vector_2d<double>& u)
00127 {
00128 vgl_vector_2d<double> u1=step_size_*u;
00129 vgl_vector_2d<double> v1(-u1.y(),u1.x());
00130
00131 unsigned np=image.image().nplanes();
00132
00133 vil_image_view<float> sample(roi_ni_,roi_nj_,1,np);
00134
00135 const vgl_point_2d<double> p0 = p-ref_x_*u1-ref_y_*v1;
00136
00137 const vimt_transform_2d& s_w2i = image.world2im();
00138 vgl_point_2d<double> im_p0 = s_w2i(p0);
00139 vgl_vector_2d<double> im_u = s_w2i.delta(p0, u1);
00140 vgl_vector_2d<double> im_v = s_w2i.delta(p0, v1);
00141
00142 vil_resample_bilin(image.image(),sample,
00143 im_p0.x(),im_p0.y(),
00144 im_u.x(),im_u.y(),
00145 im_v.x(),im_v.y(),
00146 roi_ni_,roi_nj_);
00147
00148 vnl_vector<double> v(n_pixels_*sample.nplanes());
00149 mfpf_sample_region(sample.top_left_ptr(),sample.jstep(),
00150 np,roi_,v);
00151
00152 if (norm_method_==1) mfpf_norm_vec(v,var_min_);
00153 return cost().evaluate(v);
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163 void mfpf_region_finder::evaluate_region(
00164 const vimt_image_2d_of<float>& image,
00165 const vgl_point_2d<double>& p,
00166 const vgl_vector_2d<double>& u,
00167 vimt_image_2d_of<double>& response)
00168 {
00169 int ni=1+2*search_ni_;
00170 int nj=1+2*search_nj_;
00171 int nsi = 2*search_ni_ + roi_ni_;
00172 int nsj = 2*search_nj_ + roi_nj_;
00173
00174 unsigned np=image.image().nplanes();
00175
00176 vil_image_view<float> sample(nsi,nsj,1,np);
00177 vgl_vector_2d<double> u1=step_size_*u;
00178 vgl_vector_2d<double> v1(-u1.y(),u1.x());
00179 const vgl_point_2d<double> p0 = p-(search_ni_+ref_x_)*u1
00180 -(search_nj_+ref_y_)*v1;
00181
00182 const vimt_transform_2d& s_w2i = image.world2im();
00183 vgl_point_2d<double> im_p0 = s_w2i(p0);
00184 vgl_vector_2d<double> im_u = s_w2i.delta(p0, u1);
00185 vgl_vector_2d<double> im_v = s_w2i.delta(p0, v1);
00186
00187 vil_resample_bilin(image.image(),sample,
00188 im_p0.x(),im_p0.y(),
00189 im_u.x(),im_u.y(),
00190 im_v.x(),im_v.y(),
00191 nsi,nsj);
00192
00193 vnl_vector<double> v(n_pixels_*np);
00194
00195 response.image().set_size(ni,nj);
00196 double* r = response.image().top_left_ptr();
00197 const float* s = sample.top_left_ptr();
00198 vcl_ptrdiff_t r_jstep = response.image().jstep();
00199 vcl_ptrdiff_t s_jstep = sample.jstep();
00200
00201 for (unsigned j=0;j<(unsigned)nj;++j,r+=r_jstep,s+=s_jstep)
00202 {
00203 for (int i=0;i<ni;++i)
00204 {
00205 mfpf_sample_region(s+i*np,s_jstep,np,roi_,v);
00206 if (norm_method_==1) mfpf_norm_vec(v,var_min_);
00207 r[i] = cost().evaluate(v);
00208 }
00209 }
00210
00211
00212
00213
00214
00215 const vgl_point_2d<double> p1 = p-search_ni_*u1-search_nj_*v1;
00216
00217 vimt_transform_2d i2w;
00218 i2w.set_similarity(vgl_point_2d<double>(u1.x(),u1.y()),p1);
00219 response.set_world2im(i2w.inverse());
00220 }
00221
00222
00223
00224
00225
00226 double mfpf_region_finder::search_one_pose(const vimt_image_2d_of<float>& image,
00227 const vgl_point_2d<double>& p,
00228 const vgl_vector_2d<double>& u,
00229 vgl_point_2d<double>& new_p)
00230 {
00231 int ni=1+2*search_ni_;
00232 int nj=1+2*search_nj_;
00233 int nsi = 2*search_ni_ + roi_ni_;
00234 int nsj = 2*search_nj_ + roi_nj_;
00235
00236 unsigned np=image.image().nplanes();
00237
00238 vil_image_view<float> sample(nsi,nsj,1,np);
00239 vgl_vector_2d<double> u1=step_size_*u;
00240 vgl_vector_2d<double> v1(-u1.y(),u1.x());
00241 const vgl_point_2d<double> p0 = p-(search_ni_+ref_x_)*u1
00242 -(search_nj_+ref_y_)*v1;
00243
00244 const vimt_transform_2d& s_w2i = image.world2im();
00245 vgl_point_2d<double> im_p0 = s_w2i(p0);
00246 vgl_vector_2d<double> im_u = s_w2i.delta(p0, u1);
00247 vgl_vector_2d<double> im_v = s_w2i.delta(p0, v1);
00248
00249 vil_resample_bilin(image.image(),sample,
00250 im_p0.x(),im_p0.y(), im_u.x(),im_u.y(),
00251 im_v.x(),im_v.y(),
00252 nsi,nsj);
00253
00254 vnl_vector<double> v(n_pixels_*np);
00255
00256 const float* s = sample.top_left_ptr();
00257 vcl_ptrdiff_t s_jstep = sample.jstep();
00258
00259 double best_r=9.99e9;
00260 int best_i=0,best_j=0;
00261 for (unsigned j=0;j<(unsigned)nj;++j,s+=s_jstep)
00262 {
00263 for (int i=0;i<ni;++i)
00264 {
00265 mfpf_sample_region(s+i*np,s_jstep,np,roi_,v);
00266 if (norm_method_==1) mfpf_norm_vec(v,var_min_);
00267 double r = cost().evaluate(v);
00268 if (r<best_r) { best_r=r; best_i=i; best_j=j; }
00269 }
00270 }
00271
00272
00273 new_p = p+(best_i-search_ni_)*u1+(best_j-search_nj_)*v1;
00274 return best_r;
00275 }
00276
00277
00278 bool mfpf_region_finder::is_inside(const mfpf_pose& pose,
00279 const vgl_point_2d<double>& p,
00280 double f) const
00281 {
00282
00283 vimt_transform_2d t1;
00284 t1.set_similarity(step_size()*pose.u(),pose.p());
00285
00286 vgl_point_2d<double> q=t1.inverse()(p);
00287 q.x()/=f; q.y()/=f;
00288 q.x()+=ref_x_;
00289 if (q.x()<0 || q.x()>(roi_ni_-1)) return false;
00290 q.y()+=ref_y_;
00291 if (q.y()<0 || q.y()>(roi_nj_-1)) return false;
00292 return true;
00293 }
00294
00295
00296
00297 bool mfpf_region_finder::overlap(const mfpf_pose& pose1,
00298 const mfpf_pose& pose2) const
00299 {
00300 if (is_inside(pose1,pose2.p(),overlap_f_)) return true;
00301 if (is_inside(pose2,pose1.p(),overlap_f_)) return true;
00302 return false;
00303 }
00304
00305
00306
00307
00308 void mfpf_region_finder::get_outline(vcl_vector<vgl_point_2d<double> >& pts) const
00309 {
00310 pts.resize(7);
00311 vgl_vector_2d<double> r(ref_x_,ref_y_);
00312 pts[0]=vgl_point_2d<double>(0,roi_nj_)-r;
00313 pts[1]=vgl_point_2d<double>(0,0);
00314 pts[2]=vgl_point_2d<double>(roi_ni_,roi_nj_)-r;
00315 pts[3]=vgl_point_2d<double>(0,roi_nj_)-r;
00316 pts[4]=vgl_point_2d<double>(0,0)-r;
00317 pts[5]=vgl_point_2d<double>(roi_ni_,0)-r;
00318 pts[6]=vgl_point_2d<double>(roi_ni_,roi_nj_)-r;
00319 }
00320
00321
00322 void mfpf_region_finder::get_image_of_model(vimt_image_2d_of<vxl_byte>& image) const
00323 {
00324 vnl_vector<double> mean;
00325 cost().get_average(mean);
00326
00327 assert(mean.size()>=n_pixels_);
00328
00329
00330 vnl_vector<double> meanL2;
00331 unsigned nplanes=mean.size()/n_pixels_;
00332
00333 double min1=1.0E30;
00334 double max1=-1.0E30;
00335 if (nplanes==1)
00336 {
00337 min1=mean.min_value();
00338 max1=mean.max_value();
00339 }
00340 else if (draw_only_1st_plane_)
00341 {
00342 double* pData=mean.data_block();
00343 double* pDataEnd=mean.data_block()+mean.size();
00344 while (pData != pDataEnd)
00345 {
00346 double z=*pData;
00347 min1=vcl_min(z,min1);
00348 max1=vcl_max(z,max1);
00349 pData += nplanes;
00350 }
00351 }
00352 else
00353 {
00354 meanL2.set_size(n_pixels_);
00355 double* pData=mean.data_block();
00356 double* pDataEnd=mean.data_block()+mean.size();
00357 unsigned i=0;
00358
00359 while (pData != pDataEnd)
00360 {
00361 double z = vnl_c_vector<double>::two_norm(pData, nplanes);
00362
00363 min1=vcl_min(z,min1);
00364 max1=vcl_max(z,max1);
00365 meanL2[i++]=z;
00366 pData += nplanes;
00367 }
00368 }
00369
00370 double s =255/(max1-min1);
00371 image.image().set_size(roi_ni_,roi_nj_);
00372 image.image().fill(0);
00373 unsigned q=0;
00374 if (nplanes==1)
00375 {
00376 for (unsigned k=0;k<roi_.size();++k)
00377 {
00378 for (int i=roi_[k].start_x();i<=roi_[k].end_x();++i,++q)
00379 image.image()(i,roi_[k].y())=vxl_byte(s*(mean[q]-min1));
00380 }
00381 }
00382 else if (draw_only_1st_plane_)
00383 {
00384 for (unsigned k=0;k<roi_.size();++k)
00385 {
00386 for (int i=roi_[k].start_x();i<=roi_[k].end_x();++i,q+=nplanes)
00387 image.image()(i,roi_[k].y())=vxl_byte(s*(mean[q]-min1));
00388 }
00389 }
00390 else
00391 {
00392
00393 for (unsigned k=0;k<roi_.size();++k)
00394 {
00395 for (int i=roi_[k].start_x();i<=roi_[k].end_x();++i,++q)
00396 image.image()(i,roi_[k].y())=vxl_byte(s*(meanL2[q]-min1));
00397 }
00398 }
00399
00400 vimt_transform_2d ref2im;
00401 ref2im.set_zoom_only(1.0/step_size_,ref_x_,ref_y_);
00402 image.set_world2im(ref2im);
00403 }
00404
00405
00406
00407
00408
00409 vcl_string mfpf_region_finder::is_a() const
00410 {
00411 return vcl_string("mfpf_region_finder");
00412 }
00413
00414
00415 mfpf_point_finder* mfpf_region_finder::clone() const
00416 {
00417 return new mfpf_region_finder(*this);
00418 }
00419
00420
00421
00422
00423
00424 void mfpf_region_finder::print_summary(vcl_ostream& os) const
00425 {
00426 os << "{ size: "<<roi_ni_<<" x "<<roi_nj_
00427 << " n_pixels: "<<n_pixels_
00428 << " ref_pt: ("<<ref_x_<<','<<ref_y_<<')'<<'\n';
00429 vsl_indent_inc(os);
00430 if (norm_method_==0) os<<vsl_indent()<<"norm: none"<<'\n';
00431 else os<<vsl_indent()<<"norm: linear"<<'\n';
00432 os <<vsl_indent()<< "cost: ";
00433 if (cost_.ptr()==0) os << "--"<<vcl_endl; else os << cost_<<'\n';
00434 os<<vsl_indent();
00435 mfpf_point_finder::print_summary(os);
00436 os <<vcl_endl <<vsl_indent()<<"overlap_f: "<<overlap_f_<<'\n';
00437 vsl_indent_dec(os);
00438 os<<vsl_indent()<<'}';
00439 }
00440
00441 void mfpf_region_finder::print_shape(vcl_ostream& os) const
00442 {
00443 vil_image_view<vxl_byte> im(roi_ni_,roi_nj_);
00444 im.fill(0);
00445 for (unsigned k=0;k<roi_.size();++k)
00446 for (int i=roi_[k].start_x();i<=roi_[k].end_x();++i)
00447 im(i,roi_[k].y())=1;
00448 for (unsigned j=0;j<im.nj();++j)
00449 {
00450 for (unsigned i=0;i<im.ni();++i)
00451 if (im(i,j)==0) os<<' ';
00452 else os<<'X';
00453 os<<'\n';
00454 }
00455 }
00456
00457 short mfpf_region_finder::version_no() const
00458 {
00459 return 2;
00460 }
00461
00462
00463 void mfpf_region_finder::b_write(vsl_b_ostream& bfs) const
00464 {
00465 vsl_b_write(bfs,version_no());
00466 mfpf_point_finder::b_write(bfs);
00467 vsl_b_write(bfs,roi_);
00468 vsl_b_write(bfs,roi_ni_);
00469 vsl_b_write(bfs,roi_nj_);
00470 vsl_b_write(bfs,n_pixels_);
00471 vsl_b_write(bfs,cost_);
00472 vsl_b_write(bfs,ref_x_);
00473 vsl_b_write(bfs,ref_y_);
00474 vsl_b_write(bfs,norm_method_);
00475 vsl_b_write(bfs,overlap_f_);
00476 }
00477
00478
00479
00480
00481
00482 void mfpf_region_finder::b_read(vsl_b_istream& bfs)
00483 {
00484 if (!bfs) return;
00485 short version;
00486 vsl_b_read(bfs,version);
00487 switch (version)
00488 {
00489 case (1):
00490 case (2):
00491 mfpf_point_finder::b_read(bfs);
00492 vsl_b_read(bfs,roi_);
00493 vsl_b_read(bfs,roi_ni_);
00494 vsl_b_read(bfs,roi_nj_);
00495 vsl_b_read(bfs,n_pixels_);
00496 vsl_b_read(bfs,cost_);
00497 vsl_b_read(bfs,ref_x_);
00498 vsl_b_read(bfs,ref_y_);
00499 vsl_b_read(bfs,norm_method_);
00500 if (version==1) overlap_f_=1.0;
00501 else vsl_b_read(bfs,overlap_f_);
00502 break;
00503 default:
00504 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&)\n"
00505 << " Unknown version number "<< version << vcl_endl;
00506 bfs.is().clear(vcl_ios::badbit);
00507 return;
00508 }
00509 }
00510
00511
00512 bool mfpf_region_finder::operator==(const mfpf_region_finder& nc) const
00513 {
00514 if (!base_equality(nc)) return false;
00515 if (roi_ni_!=nc.roi_ni_) return false;
00516 if (roi_nj_!=nc.roi_nj_) return false;
00517 if (norm_method_!=nc.norm_method_) return false;
00518 if (n_pixels_!=nc.n_pixels_) return false;
00519 if (vcl_fabs(ref_x_-nc.ref_x_)>1e-6) return false;
00520 if (vcl_fabs(ref_y_-nc.ref_y_)>1e-6) return false;
00521 if (vcl_fabs(overlap_f_-nc.overlap_f_)>1e-6) return false;
00522
00523 return true;
00524 }
00525
00526