00001 #include "mfpf_pose_predictor.h"
00002
00003
00004
00005
00006
00007 #include <mfpf/mfpf_sample_region.h>
00008 #include <mfpf/mfpf_norm_vec.h>
00009 #include <vil/vil_resample_bilin.h>
00010 #include <vsl/vsl_binary_loader.h>
00011 #include <vsl/vsl_vector_io.h>
00012 #include <vsl/vsl_indent.h>
00013 #include <vgl/vgl_point_2d.h>
00014 #include <vgl/vgl_vector_2d.h>
00015 #include <vnl/vnl_vector.h>
00016 #include <vnl/io/vnl_io_vector.h>
00017 #include <vnl/io/vnl_io_matrix.h>
00018 #include <vcl_cmath.h>
00019 #include <vcl_cassert.h>
00020
00021
00022
00023
00024
00025 mfpf_pose_predictor::mfpf_pose_predictor()
00026 {
00027 set_defaults();
00028 }
00029
00030
00031 void mfpf_pose_predictor::set_defaults()
00032 {
00033 step_size_=1.0;
00034 pose_type_=translation;
00035 n_pixels_=0;
00036 roi_.resize(0);
00037 roi_ni_=0;
00038 roi_nj_=0;
00039 ref_x_=0;
00040 ref_y_=0;
00041 norm_method_=1;
00042 var_min_ = 1.0E-6;
00043 }
00044
00045
00046 void mfpf_pose_predictor::set_step_size(double s)
00047 {
00048 step_size_=s;
00049 }
00050
00051
00052 void mfpf_pose_predictor::set_as_box(unsigned ni, unsigned nj,
00053 short norm_method)
00054 {
00055
00056 vcl_vector<mbl_chord> roi(nj);
00057 for (unsigned j=0;j<nj;++j) roi[j]=mbl_chord(0,ni-1,j);
00058
00059 set(roi,0.5*(ni-1),0.5*(nj-1),norm_method);
00060 }
00061
00062
00063
00064 void mfpf_pose_predictor::set_as_ellipse(double ri, double rj,
00065 short norm_method)
00066 {
00067 vcl_vector<mbl_chord> roi;
00068
00069 int ni=int(ri+1e-6);
00070 int nj=int(rj+1e-6);
00071 for (int j = -nj;j<=nj;++j)
00072 {
00073
00074 int x = int(ri*vcl_sqrt(1.0-j*j/(rj*rj)));
00075 roi.push_back(mbl_chord(ni-x,ni+x,nj+j));
00076 }
00077
00078 set(roi,ni,nj,norm_method);
00079 }
00080
00081 void mfpf_pose_predictor::set_pose_type(const mfpf_pose_type& pt)
00082 {
00083 pose_type_=pt;
00084 }
00085
00086
00087
00088
00089 mfpf_pose_predictor::~mfpf_pose_predictor()
00090 {
00091 }
00092
00093
00094 void mfpf_pose_predictor::set(const vcl_vector<mbl_chord>& roi,
00095 double ref_x, double ref_y,
00096 short norm_method)
00097 {
00098 ref_x_ = ref_x;
00099 ref_y_ = ref_y;
00100
00101
00102 if (roi.size()==0) { roi_ni_=0; roi_nj_=0; return; }
00103 int ilo=roi[0].start_x(), ihi=roi[0].end_x();
00104 int jlo=roi[0].y(), jhi=roi[0].y();
00105
00106 for (unsigned k=1;k<roi.size();++k)
00107 {
00108 if (roi[k].start_x()<ilo) ilo=roi[k].start_x();
00109 if (roi[k].end_x()>ihi) ihi=roi[k].end_x();
00110 if (roi[k].y()<jlo) jlo=roi[k].y();
00111 if (roi[k].y()>jhi) jhi=roi[k].y();
00112 }
00113 roi_ni_=1+ihi-ilo;
00114 roi_nj_=1+jhi-jlo;
00115
00116
00117 ref_x_-=ilo; ref_y_-=jlo;
00118 roi_.resize(roi.size());
00119 n_pixels_=0;
00120 for (unsigned k=0;k<roi.size();++k)
00121 {
00122 roi_[k]= mbl_chord(roi[k].start_x()-ilo,
00123 roi[k].end_x()-ilo, roi[k].y()-jlo);
00124 n_pixels_+=1+roi[k].end_x()-roi[k].start_x();
00125 }
00126
00127 assert(norm_method>=0 && norm_method<=1);
00128 norm_method_ = norm_method;
00129 }
00130
00131
00132 void mfpf_pose_predictor::set_predictor(const vnl_matrix<double>& R,
00133 const vnl_vector<double>& dp0)
00134 {
00135 assert(R.rows()==dp0.size());
00136 R_=R;
00137 dp0_=dp0;
00138 }
00139
00140
00141 double mfpf_pose_predictor::radius() const
00142 {
00143
00144 double wx = roi_ni_-1;
00145 double x2 = vcl_max(ref_x_*ref_x_,(ref_x_-wx)*(ref_x_-wx));
00146 double wy = roi_nj_-1;
00147 double y2 = vcl_max(ref_y_*ref_y_,(ref_y_-wy)*(ref_y_-wy));
00148 double r2 = x2+y2;
00149 if (r2<=1) return 1.0;
00150 return vcl_sqrt(r2);
00151 }
00152
00153
00154
00155 void mfpf_pose_predictor::get_sample_vector(const vimt_image_2d_of<float>& image,
00156 const vgl_point_2d<double>& p,
00157 const vgl_vector_2d<double>& u,
00158 vnl_vector<double>& vec)
00159 {
00160 vgl_vector_2d<double> u1=step_size_*u;
00161 vgl_vector_2d<double> v1(-u1.y(),u1.x());
00162
00163 unsigned np=image.image().nplanes();
00164
00165 vil_image_view<float> sample(roi_ni_,roi_nj_,1,np);
00166
00167 const vgl_point_2d<double> p0 = p-ref_x_*u1-ref_y_*v1;
00168
00169 const vimt_transform_2d& s_w2i = image.world2im();
00170 vgl_point_2d<double> im_p0 = s_w2i(p0);
00171 vgl_vector_2d<double> im_u = s_w2i.delta(p0, u1);
00172 vgl_vector_2d<double> im_v = s_w2i.delta(p0, v1);
00173
00174 vil_resample_bilin(image.image(),sample,
00175 im_p0.x(),im_p0.y(),
00176 im_u.x(),im_u.y(),
00177 im_v.x(),im_v.y(),
00178 roi_ni_,roi_nj_);
00179
00180 vec.set_size(n_pixels_*sample.nplanes());
00181 mfpf_sample_region(sample.top_left_ptr(),sample.jstep(),
00182 np,roi_,vec);
00183
00184 if (norm_method_==1) mfpf_norm_vec(vec,var_min_);
00185 }
00186
00187
00188 void mfpf_pose_predictor::new_pose(const vimt_image_2d_of<float>& image,
00189 const mfpf_pose& pose0,
00190 mfpf_pose& new_pose)
00191 {
00192 vnl_vector<double> v;
00193 get_sample_vector(image,pose0.p(),pose0.u(),v);
00194 vnl_vector<double> dp = R_*v+dp0_;
00195
00196
00197 mfpf_pose dpose;
00198 double s;
00199
00200 switch (pose_type_)
00201 {
00202 case translation:
00203 dpose.p().set(dp[0],dp[1]);
00204 break;
00205 case rigid:
00206 dpose.p().set(dp[0],dp[1]);
00207 dpose.u().set(vcl_cos(dp[2]),vcl_sin(dp[2]));
00208 break;
00209 case zoom:
00210 dpose.p().set(dp[0],dp[1]);
00211 dpose.u().set(vcl_exp(dp[2]),0);
00212 break;
00213 case similarity:
00214 dpose.p().set(dp[0],dp[1]);
00215 s=vcl_exp(dp[2]);
00216 dpose.u().set(s*vcl_cos(dp[3]),s*vcl_sin(dp[3]));
00217 break;
00218 default: assert(!"Invalid pose_type_"); break;
00219 }
00220
00221 new_pose=pose0*dpose.inverse();
00222 }
00223
00224
00225
00226
00227
00228 void mfpf_pose_predictor::get_outline(vcl_vector<vgl_point_2d<double> >& pts) const
00229 {
00230 pts.resize(7);
00231 vgl_vector_2d<double> r(ref_x_,ref_y_);
00232 pts[0]=vgl_point_2d<double>(0,roi_nj_)-r;
00233 pts[1]=vgl_point_2d<double>(0,0);
00234 pts[2]=vgl_point_2d<double>(roi_ni_,roi_nj_)-r;
00235 pts[3]=vgl_point_2d<double>(0,roi_nj_)-r;
00236 pts[4]=vgl_point_2d<double>(0,0)-r;
00237 pts[5]=vgl_point_2d<double>(roi_ni_,0)-r;
00238 pts[6]=vgl_point_2d<double>(roi_ni_,roi_nj_)-r;
00239 }
00240
00241
00242
00243
00244
00245
00246 vcl_string mfpf_pose_predictor::is_a() const
00247 {
00248 return vcl_string("mfpf_pose_predictor");
00249 }
00250
00251
00252 mfpf_pose_predictor* mfpf_pose_predictor::clone() const
00253 {
00254 return new mfpf_pose_predictor(*this);
00255 }
00256
00257
00258
00259
00260
00261 void mfpf_pose_predictor::print_summary(vcl_ostream& os) const
00262 {
00263 os << "{ step_size: "<<step_size_
00264 <<" pose_type: "<<pose_type_
00265 <<" size: "<<roi_ni_<<" x "<<roi_nj_
00266 << " n_pixels: "<<n_pixels_
00267 << " ref_pt: ("<<ref_x_<<','<<ref_y_<<')'<<'\n';
00268 vsl_indent_inc(os);
00269 if (norm_method_==0) os<<vsl_indent()<<"norm: none ";
00270 else os<<vsl_indent()<<"norm: linear ";
00271 os << "n_params: "<<R_.rows()<<'\n';
00272 vsl_indent_dec(os);
00273 os<<vsl_indent()<<'}';
00274 }
00275
00276 void mfpf_pose_predictor::print_shape(vcl_ostream& os) const
00277 {
00278 vil_image_view<vxl_byte> im(roi_ni_,roi_nj_);
00279 im.fill(0);
00280 for (unsigned k=0;k<roi_.size();++k)
00281 for (int i=roi_[k].start_x();i<=roi_[k].end_x();++i)
00282 im(i,roi_[k].y())=1;
00283 for (unsigned j=0;j<im.nj();++j)
00284 {
00285 for (unsigned i=0;i<im.ni();++i)
00286 if (im(i,j)==0) os<<' ';
00287 else os<<'X';
00288 os<<'\n';
00289 }
00290 }
00291
00292 short mfpf_pose_predictor::version_no() const
00293 {
00294 return 1;
00295 }
00296
00297
00298 void mfpf_pose_predictor::b_write(vsl_b_ostream& bfs) const
00299 {
00300 vsl_b_write(bfs,version_no());
00301 vsl_b_write(bfs,step_size_);
00302 vsl_b_write(bfs,unsigned(pose_type_));
00303 vsl_b_write(bfs,roi_);
00304 vsl_b_write(bfs,roi_ni_);
00305 vsl_b_write(bfs,roi_nj_);
00306 vsl_b_write(bfs,n_pixels_);
00307 vsl_b_write(bfs,ref_x_);
00308 vsl_b_write(bfs,ref_y_);
00309 vsl_b_write(bfs,norm_method_);
00310 vsl_b_write(bfs,R_);
00311 vsl_b_write(bfs,dp0_);
00312 }
00313
00314
00315
00316
00317
00318 void mfpf_pose_predictor::b_read(vsl_b_istream& bfs)
00319 {
00320 if (!bfs) return;
00321 short version;
00322 unsigned i;
00323 vsl_b_read(bfs,version);
00324 switch (version)
00325 {
00326 case 1:
00327 vsl_b_read(bfs,step_size_);
00328 vsl_b_read(bfs,i); pose_type_=mfpf_pose_type(i);
00329 vsl_b_read(bfs,roi_);
00330 vsl_b_read(bfs,roi_ni_);
00331 vsl_b_read(bfs,roi_nj_);
00332 vsl_b_read(bfs,n_pixels_);
00333 vsl_b_read(bfs,ref_x_);
00334 vsl_b_read(bfs,ref_y_);
00335 vsl_b_read(bfs,norm_method_);
00336 vsl_b_read(bfs,R_);
00337 vsl_b_read(bfs,dp0_);
00338 break;
00339 default:
00340 vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&)\n"
00341 << " Unknown version number "<< version << vcl_endl;
00342 bfs.is().clear(vcl_ios::badbit);
00343 return;
00344 }
00345 }
00346
00347
00348 bool mfpf_pose_predictor::operator==(const mfpf_pose_predictor& nc) const
00349 {
00350 if (vcl_fabs(step_size_-nc.step_size_)>1e-6) return false;
00351 if (pose_type_!=nc.pose_type_) return false;
00352 if (roi_ni_!=nc.roi_ni_) return false;
00353 if (roi_nj_!=nc.roi_nj_) return false;
00354 if (norm_method_!=nc.norm_method_) return false;
00355 if (n_pixels_!=nc.n_pixels_) return false;
00356 if (vcl_fabs(ref_x_-nc.ref_x_)>1e-6) return false;
00357 if (vcl_fabs(ref_y_-nc.ref_y_)>1e-6) return false;
00358 return true;
00359 }
00360
00361
00362
00363
00364
00365 void vsl_b_write(vsl_b_ostream& bfs, const mfpf_pose_predictor& b)
00366 {
00367 b.b_write(bfs);
00368 }
00369
00370
00371
00372
00373
00374 void vsl_b_read(vsl_b_istream& bfs, mfpf_pose_predictor& b)
00375 {
00376 b.b_read(bfs);
00377 }
00378
00379
00380
00381
00382
00383 vcl_ostream& operator<<(vcl_ostream& os,const mfpf_pose_predictor& b)
00384 {
00385 os << b.is_a() << ": ";
00386 vsl_indent_inc(os);
00387 b.print_summary(os);
00388 vsl_indent_dec(os);
00389 return os;
00390 }
00391
00392 vcl_ostream& operator<<(vcl_ostream& os ,const mfpf_pose_type& pt)
00393 {
00394 switch (pt)
00395 {
00396 case translation: os<<"translation"; break;
00397 case rigid: os<<"rigid"; break;
00398 case zoom: os<<"zoom"; break;
00399 case similarity: os<<"similarity"; break;
00400 default: os<<"Invalid"; break;
00401 }
00402 return os;
00403 }
00404