contrib/brl/bseg/strk/strk_tracking_face_2d.cxx
Go to the documentation of this file.
00001 // This is brl/bseg/strk/strk_tracking_face_2d.cxx
00002 #include "strk_tracking_face_2d.h"
00003 //:
00004 // \file
00005 // See strk_tracking_face_2d.h
00006 //
00007 //-----------------------------------------------------------------------------
00008 #include <vcl_cmath.h> // for log(), exp() ..
00009 #include <vcl_cstdlib.h> // for rand()
00010 #include <vnl/vnl_math.h>
00011 #include <vgl/vgl_polygon.h>
00012 #include <vgl/vgl_polygon_scan_iterator.h>
00013 #include <bsta/bsta_joint_histogram.h>
00014 #include <vsol/vsol_point_2d.h>
00015 #include <vtol/vtol_vertex_2d.h>
00016 #include <btol/btol_face_algs.h>
00017 
00018 //#define DEBUG
00019 
00020 //
00021 //======================== TRACKING FACE IMPLEMENTATION =============
00022 //
00023 void strk_tracking_face_2d::centroid(double& x, double& y) const
00024 {
00025   if (!intf_)
00026   {
00027     x = 0;
00028     y = 0;
00029   }
00030   vtol_face_2d_sptr f = intf_->cast_to_face_2d();
00031   vsol_point_2d_sptr p = btol_face_algs::centroid(f);
00032   x = p->x();
00033   y = p->y();
00034 }
00035 
00036 static vnl_matrix_fixed<double,3,3> ident()
00037 {
00038   vnl_matrix_fixed<double,3,3> M;
00039   M[0][0] = 1.0;   M[0][1] = 0.0;   M[0][2] = 0.0;
00040   M[1][0] = 0.0;   M[1][1] = 1.0;   M[1][2] = 0.0;
00041   M[2][0] = 0.0;   M[2][1] = 0.0;   M[2][2] = 1.0;
00042   return M;
00043 }
00044 
00045 void strk_tracking_face_2d::init_bins()
00046 {
00047   intensity_hist_bins_=16;
00048   gradient_dir_hist_bins_=8;
00049   color_hist_bins_=8;
00050 }
00051 
00052 strk_tracking_face_2d::
00053 strk_tracking_face_2d(vtol_face_2d_sptr const& face,
00054                       vil1_memory_image_of<float> const& image,
00055                       vil1_memory_image_of<float> const& Ix,
00056                       vil1_memory_image_of<float> const& Iy,
00057                       vil1_memory_image_of<float> const& hue,
00058                       vil1_memory_image_of<float> const& sat,
00059                       const float min_gradient,
00060                       const float parzen_sigma,
00061                       const unsigned int intensity_hist_bins,
00062                       const unsigned int gradient_dir_hist_bins,
00063                       const unsigned int color_hist_bins,
00064                       const float max_intensity)
00065 {
00066   intensity_hist_bins_ = intensity_hist_bins;
00067   gradient_dir_hist_bins_=gradient_dir_hist_bins;
00068   color_hist_bins_=color_hist_bins;
00069   min_gradient_ = min_gradient;
00070   parzen_sigma_ = parzen_sigma;
00071   max_intensity_ = max_intensity;
00072   intf_ = 0;
00073   Ix_ = 0;
00074   Iy_ = 0;
00075   hue_ = 0;
00076   sat_ = 0;
00077   intensity_mi_=0;
00078   gradient_dir_mi_=0;
00079   color_mi_=0;
00080   model_intensity_entropy_=0;
00081   model_gradient_dir_entropy_=0;
00082   model_color_entropy_=0;
00083   intensity_entropy_=0;
00084   gradient_dir_entropy_=0;
00085   color_entropy_=0;
00086   intensity_joint_entropy_=0;
00087   model_intensity_joint_entropy_=0;
00088   gradient_joint_entropy_=0;
00089   color_joint_entropy_=0;
00090   intensity_info_diff_ = 0;
00091   color_info_diff_ = 0;
00092   gradient_info_ = Ix&&Iy;
00093   color_info_ = hue&&sat;
00094   renyi_joint_entropy_ = false;
00095   this->init_intensity_info(face, image);
00096   //cases
00097   if (gradient_info_)
00098     this->init_gradient_info(Ix, Iy);
00099 
00100   if (color_info_)
00101     this->init_color_info(hue, sat);
00102   trans_ = ident();
00103 }
00104 
00105 strk_tracking_face_2d::strk_tracking_face_2d(vtol_intensity_face_sptr const& intf,
00106                                              const unsigned int intensity_hist_bins,
00107                                              const unsigned int gradient_dir_hist_bins,
00108                                              const unsigned int color_hist_bins,
00109                                              const float max_intensity)
00110 {
00111   intensity_hist_bins_ = intensity_hist_bins;
00112   gradient_dir_hist_bins_=gradient_dir_hist_bins;
00113   color_hist_bins_=color_hist_bins;
00114   max_intensity_ = max_intensity;
00115   if (!intf)
00116     return;
00117   intf_ = intf;
00118   Ix_ = 0;
00119   Iy_ = 0;
00120   gradient_info_ = false;
00121   color_info_ = false;
00122   renyi_joint_entropy_ = false;
00123   intensity_mi_=0;
00124   gradient_dir_mi_=0;
00125   color_mi_=0;
00126   model_intensity_entropy_=0;
00127   model_gradient_dir_entropy_=0;
00128   model_color_entropy_=0;
00129   intensity_entropy_=0;
00130   gradient_dir_entropy_=0;
00131   color_entropy_=0;
00132   intensity_joint_entropy_=0;
00133   model_intensity_joint_entropy_=0;
00134   gradient_joint_entropy_=0;
00135   color_joint_entropy_=0;
00136   intensity_info_diff_ = 0;
00137   color_info_diff_ = 0;
00138   trans_ = ident();
00139 }
00140 
00141 strk_tracking_face_2d::strk_tracking_face_2d(strk_tracking_face_2d_sptr const& tf)
00142 {
00143   intensity_hist_bins_ = tf->intensity_hist_bins_;
00144   gradient_dir_hist_bins_= tf->gradient_dir_hist_bins_;
00145   color_hist_bins_= tf->color_hist_bins_;
00146   vtol_intensity_face_sptr intf = tf->face();
00147   vtol_face_2d_sptr f2d = new vtol_face_2d(intf->cast_to_face_2d());
00148   intf_= new vtol_intensity_face(f2d, intf->Npix(),
00149                                  intf->Xj(), intf->Yj(),
00150                                  intf->Ij());
00151 
00152   Ix_ = 0;
00153   Iy_ = 0;
00154   gradient_info_ = tf->gradient_info_;
00155   if (gradient_info_)
00156   {
00157     int n = intf_->Npix();
00158     Ix_ = new float[n];
00159     Iy_ = new float[n];
00160     for (int i =0; i<n; ++i)
00161     {
00162       Ix_[i]=tf->Ix(i);
00163       Iy_[i]=tf->Iy(i);
00164     }
00165   }
00166   hue_ = 0;
00167   sat_ = 0;
00168   color_info_ = tf->color_info_;
00169   if (color_info_)
00170   {
00171     int n = intf_->Npix();
00172     hue_ = new float[n];
00173     sat_ = new float[n];
00174     for (int i =0; i<n; ++i)
00175     {
00176       hue_[i]=tf->hue(i);
00177       sat_[i]=tf->sat(i);
00178     }
00179   }
00180   renyi_joint_entropy_ = tf->renyi_joint_entropy_;
00181   intensity_mi_ = tf->int_mutual_info();
00182   gradient_dir_mi_ = tf->grad_mutual_info();
00183   color_mi_ = tf->color_mutual_info();
00184   model_intensity_entropy_=tf->model_intensity_entropy_;
00185   model_gradient_dir_entropy_=tf->model_gradient_dir_entropy_;
00186   model_color_entropy_=tf->model_color_entropy_;
00187   intensity_entropy_=tf->intensity_entropy_;
00188   gradient_dir_entropy_=tf->gradient_dir_entropy_;
00189   color_entropy_=tf->color_entropy_;
00190   intensity_joint_entropy_=tf->intensity_joint_entropy_;
00191   model_intensity_joint_entropy_=tf->model_intensity_joint_entropy_;
00192   gradient_joint_entropy_=tf->gradient_joint_entropy_;
00193   color_joint_entropy_=tf->color_joint_entropy_;
00194   intensity_info_diff_ = tf->intensity_info_diff_;
00195   color_info_diff_ = tf->color_info_diff_;
00196   min_gradient_ = tf->min_gradient_;
00197   parzen_sigma_ = tf->parzen_sigma_;
00198   trans_ = tf->trans_;
00199   max_intensity_ = tf->max_intensity_;
00200 }
00201 
00202 strk_tracking_face_2d::strk_tracking_face_2d(strk_tracking_face_2d const& tf)
00203   : vbl_ref_count()
00204 {
00205   vtol_intensity_face_sptr intf = tf.face();
00206   vtol_face_2d_sptr f2d = new vtol_face_2d(intf->cast_to_face_2d());
00207   intf_= new vtol_intensity_face(f2d, intf->Npix(),
00208                                  intf->Xj(), intf->Yj(),
00209                                  intf->Ij());
00210 
00211   Ix_ = 0;
00212   Iy_ = 0;
00213   gradient_info_ = tf.gradient_info_;
00214   if (gradient_info_)
00215   {
00216     int n = intf_->Npix();
00217     Ix_ = new float[n];
00218     Iy_ = new float[n];
00219     for (int i =0; i<n; ++i)
00220     {
00221       Ix_[i]=tf.Ix(i);
00222       Iy_[i]=tf.Iy(i);
00223     }
00224   }
00225   hue_ = 0;
00226   sat_ = 0;
00227   color_info_ = tf.color_info_;
00228   if (color_info_)
00229   {
00230     int n = intf_->Npix();
00231     hue_ = new float[n];
00232     sat_ = new float[n];
00233     for (int i =0; i<n; ++i)
00234     {
00235       hue_[i]=tf.hue(i);
00236       sat_[i]=tf.sat(i);
00237     }
00238   }
00239   renyi_joint_entropy_ = tf.renyi_joint_entropy_;
00240   intensity_mi_ = tf.int_mutual_info();
00241   gradient_dir_mi_ = tf.grad_mutual_info();
00242   color_mi_ = tf.color_mutual_info();
00243   model_intensity_entropy_=tf.model_intensity_entropy_;
00244   model_gradient_dir_entropy_=tf.model_gradient_dir_entropy_;
00245   model_color_entropy_=tf.model_color_entropy_;
00246   intensity_entropy_=tf.intensity_entropy_;
00247   gradient_dir_entropy_=tf.gradient_dir_entropy_;
00248   color_entropy_=tf.color_entropy_;
00249   intensity_joint_entropy_=tf.intensity_joint_entropy_;
00250   model_intensity_joint_entropy_=tf.model_intensity_joint_entropy_;
00251   gradient_joint_entropy_=tf.gradient_joint_entropy_;
00252   color_joint_entropy_=tf.color_joint_entropy_;
00253   intensity_info_diff_ = tf.intensity_info_diff_;
00254   color_info_diff_ = tf.color_info_diff_;
00255   min_gradient_ = tf.min_gradient_;
00256   parzen_sigma_ = tf.parzen_sigma_;
00257   trans_ = tf.trans_;
00258   intensity_hist_bins_=tf.intensity_hist_bins_;
00259   gradient_dir_hist_bins_=tf.gradient_dir_hist_bins_;
00260   color_hist_bins_=tf.color_hist_bins_;
00261   max_intensity_ = tf.max_intensity_;
00262 }
00263 
00264 strk_tracking_face_2d::~strk_tracking_face_2d()
00265 {
00266   delete [] Ix_;
00267   delete [] Iy_;
00268   delete [] hue_;
00269   delete [] sat_;
00270 }
00271 
00272 void strk_tracking_face_2d::set_gradient(vil1_memory_image_of<float> const& Ix,
00273                                          vil1_memory_image_of<float> const& Iy)
00274 {
00275     int i = 0;
00276     if (!intf_||!Ix_||!Iy_)
00277       return;
00278     for (intf_->reset(); intf_->next(); ++i)
00279     {
00280       int x = int(intf_->X()), y = int(intf_->Y());
00281       this->set_Ix(i, Ix(x,y));
00282       this->set_Iy(i, Iy(x,y));
00283     }
00284 }
00285 
00286 void strk_tracking_face_2d::set_color(vil1_memory_image_of<float> const& hue,
00287                                       vil1_memory_image_of<float> const& sat)
00288 {
00289     int i = 0;
00290     if (!intf_||!hue_||!sat_)
00291       return;
00292     for (intf_->reset(); intf_->next(); ++i)
00293     {
00294       int x = int(intf_->X()), y = int(intf_->Y());
00295       this->set_hue(i, hue(x,y));
00296       this->set_sat(i, sat(x,y));
00297     }
00298 }
00299 
00300 void strk_tracking_face_2d::
00301 init_intensity_info(vtol_face_2d_sptr const& face,
00302                     vil1_memory_image_of<float> const& image)
00303 {
00304   if (!face||!image)
00305     return;
00306   intf_ = new vtol_intensity_face(face);
00307   int width = image.width(), height = image.height();
00308   intf_->ResetPixelData();
00309   vgl_polygon<double> p;
00310   if (!btol_face_algs::vtol_to_vgl(intf_->cast_to_face_2d(), p))
00311     return;
00312   vgl_polygon_scan_iterator<double> psi(p, true);
00313 
00314   //go throught the pixels once to gather statistics for the face Npix etc.
00315   for (psi.reset(); psi.next();)
00316     for (int x = psi.startx(); x<=psi.endx(); ++x)
00317     {
00318       int y = psi.scany();
00319       if (x<0||x>=width||y<0||y>=height)
00320         continue;
00321 
00322       unsigned short v = (unsigned short)image(x, y);
00323       intf_->IncrementMeans(float(x), float(y), v);
00324     }
00325   if (!intf_->Npix())
00326   {
00327     vcl_cout << "In strk_tracking_face_2d::strk_tracking_face_2d(..) -"
00328              << " no pixels\n";
00329     return;
00330   }
00331   intf_->InitPixelArrays();
00332 
00333   bsta_histogram<float> model_intensity_hist(max_intensity_, intensity_hist_bins_);
00334   intensity_hist_bins_ = model_intensity_hist.nbins();
00335 
00336   //Got through the pixels again to actually set the face arrays X(), Y() etc
00337   for (psi.reset(); psi.next();)
00338     for (int x = psi.startx(); x<=psi.endx(); ++x)
00339     {
00340       int y = psi.scany();
00341       if (x<0||x>=width||y<0||y>=height)
00342         continue;
00343       unsigned short v = (unsigned short)image(x, y);
00344       model_intensity_hist.upcount(v, 1.0f);
00345       intf_->InsertInPixelArrays(float(x), float(y), v);
00346     }
00347   //apply parzen window to histogram
00348 #ifdef DEBUG
00349   vcl_cout << "\n\n Before Parzen(1d) - npix ="
00350            << model_intensity_hist.area() << vcl_endl;
00351 
00352   model_intensity_hist.print();
00353 #endif //DEBUG
00354 
00355   model_intensity_hist.parzen(parzen_sigma_);
00356 
00357 #ifdef DEBUG
00358   vcl_cout << "After Parzen(1d)\n";
00359   model_intensity_hist.print();
00360 #endif //DEBUG
00361   //compute the model entropy
00362   model_intensity_entropy_ = model_intensity_hist.entropy();
00363 }
00364 
00365 //: fill the gradient values in the face
00366 //  Assumes that the intensity face parent has already been initialized.
00367 void strk_tracking_face_2d::
00368 init_gradient_info(vil1_memory_image_of<float> const& Ix,
00369                    vil1_memory_image_of<float> const& Iy)
00370 {
00371   if (!intf_||!Ix||!Iy)
00372     return;
00373   int n = intf_->Npix();
00374   Ix_ = new float[n];
00375   Iy_ = new float[n];
00376   bsta_histogram<float> model_gradient_dir_hist(360, gradient_dir_hist_bins_);
00377   gradient_dir_hist_bins_ = model_gradient_dir_hist.nbins();
00378   int i = 0;
00379   double deg_rad = 180.0/vnl_math::pi;
00380   for (intf_->reset(); intf_->next(); ++i)
00381   {
00382     int x = int(intf_->X()), y = int(intf_->Y());
00383     float Ixi = Ix(x,y), Iyi = Iy(x,y);
00384     // set the gradient values
00385     Ix_[i] = Ixi;  Iy_[i] = Iyi;
00386     float ang = float(deg_rad*vcl_atan2(Iyi, Ixi))+180.f;
00387     float mag = vcl_abs(Ixi)+vcl_abs(Iyi);
00388     if (mag>min_gradient_)
00389       model_gradient_dir_hist.upcount(ang, mag);
00390   }
00391 
00392   //apply parzen window to histogram
00393   model_gradient_dir_hist.parzen(parzen_sigma_);
00394 
00395   //compute the gradient direction entropy
00396   model_gradient_dir_entropy_= model_gradient_dir_hist.entropy();
00397 }
00398 
00399 //: fill the color values in the face
00400 //  Assumes that the intensity face parent has already been initialized.
00401 void strk_tracking_face_2d::
00402 init_color_info(vil1_memory_image_of<float> const& hue,
00403                 vil1_memory_image_of<float> const& sat)
00404 {
00405   if (!intf_||!hue||!sat)
00406     return;
00407   int n = intf_->Npix();
00408   hue_ = new float[n];
00409   sat_ = new float[n];
00410   bsta_histogram<float> model_color_hist(360, color_hist_bins_);
00411   color_hist_bins_ = model_color_hist.nbins();
00412   int i = 0;
00413   for (intf_->reset(); intf_->next(); ++i)
00414   {
00415     int x = int(intf_->X()), y = int(intf_->Y());
00416     float hue_i = hue(x,y), sat_i = sat(x,y);
00417     // set the gradient values
00418     hue_[i] = hue_i;  sat_[i] = sat_i;
00419     if (sat_i>0)
00420       model_color_hist.upcount(hue_i, sat_i);
00421   }
00422 
00423   //apply parzen window to histogram
00424   model_color_hist.parzen(parzen_sigma_);
00425 
00426   //compute the color entropy
00427   model_color_entropy_= model_color_hist.entropy();
00428 }
00429 
00430 void strk_tracking_face_2d::set_int_mutual_info(float mi)
00431 {
00432   intensity_mi_ = mi;
00433   total_info_= mi + gradient_dir_mi_+color_mi_;
00434 }
00435 
00436 void strk_tracking_face_2d::set_grad_mutual_info(float mi)
00437 {
00438   gradient_dir_mi_ = mi;
00439   total_info_= mi + intensity_mi_ + color_mi_;
00440 }
00441 
00442 void strk_tracking_face_2d::set_color_mutual_info(float mi)
00443 {
00444   color_mi_ = mi;
00445   total_info_= mi + intensity_mi_+ gradient_dir_mi_;
00446 }
00447 
00448 #if 0
00449 // rotate gradients and recompute gradient mutual information
00450 void strk_tracking_face_2d::transform_gradients(double theta)
00451 {
00452   double deg_rad = 180.0/vnl_math::pi;
00453   double c = vcl_cos(theta), s = vcl_sin(theta);
00454 
00455   bsta_histogram<float> model_gradient_dir_hist(360, gradient_dir_hist_bins_);
00456   gradient_dir_hist_bins_ = model_gradient_dir_hist.nbins();
00457 
00458   // step through points in face
00459   int i=0;
00460   for (this->reset(); this->next(); ++i)
00461   {
00462     float Ix0 = Ix_[i];
00463     float Iy0 = Iy_[i];
00464     Ix_[i] = float(Ix0*c - Iy0*s);
00465     Iy_[i] = float(Ix0*s + Iy0*c);
00466     float ang = float(deg_rad*vcl_atan2(Iy_[i],Ix_[i]))+180.f;
00467     float mag = vcl_abs(Ix_[i])+vcl_abs(Iy_[i]);
00468     if (mag>min_gradient_)
00469       model_gradient_dir_hist.upcount(ang, mag);
00470   }
00471 
00472   //apply parzen window to histogram
00473   model_gradient_dir_hist.parzen(parzen_sigma_);
00474 
00475   //compute the gradient direction entropy
00476   float ent = 0;
00477   for (unsigned int m = 0; m<gradient_dir_hist_bins_; ++m)
00478   {
00479     float pm = model_gradient_dir_hist.p(m);
00480     if (!pm)
00481       continue;
00482     ent -= pm*vcl_log(pm);
00483   }
00484   model_gradient_dir_entropy_= float(ent/vcl_log(2.0));
00485 }
00486 #endif // 0
00487 
00488 // rotate gradients
00489 void strk_tracking_face_2d::transform_gradients(double theta)
00490 {
00491   double c = vcl_cos(theta), s = vcl_sin(theta);
00492 
00493   // step through gradient values in face
00494   int i=0;
00495   for (this->reset(); this->next(); ++i)
00496   {
00497     float Ix0 = Ix_[i];
00498     float Iy0 = Iy_[i];
00499     Ix_[i] = float(Ix0*c - Iy0*s);
00500     Iy_[i] = float(Ix0*s + Iy0*c);
00501   }
00502 }
00503 
00504 void strk_tracking_face_2d::transform(double tx, double ty, double theta, double scale)
00505 {
00506   double xo = 0, yo =0;
00507   this->centroid(xo, yo);
00508   double c = vcl_cos(theta), s = vcl_sin(theta);
00509   vcl_vector<vtol_vertex_sptr> verts;
00510   this->face()->vertices(verts);
00511   for (vcl_vector<vtol_vertex_sptr>::iterator vit = verts.begin();
00512        vit != verts.end(); ++vit)
00513   {
00514     vtol_vertex_2d_sptr v = (*vit)->cast_to_vertex_2d();
00515     if (!v)
00516       continue;
00517     double x = v->x(), y = v->y();
00518     double xp =(x-xo)*scale, yp =(y-yo)*scale;
00519     v->set_x(xp*c - yp*s + xo + tx);
00520     v->set_y(xp*s + yp*c + yo + ty);
00521   }
00522   for (this->reset(); this->next();)
00523   {
00524     double x = this->X(), y = this->Y();
00525     double xp =(x-xo)*scale, yp =(y-yo)*scale;
00526     this->set_X(float(xp*c - yp*s + xo + tx));
00527     this->set_Y(float(xp*s + yp*c + yo + ty));
00528   }
00529   //update global transform
00530   vnl_matrix_fixed<double,3,3> Mt, Mt_inv, M, Mf;
00531   Mt[0][0] = 1.0;   Mt[0][1] = 0.0;   Mt[0][2] = -xo;
00532   Mt[1][0] = 0.0;   Mt[1][1] = 1.0;   Mt[1][2] = -yo;
00533   Mt[2][0] = 0.0;   Mt[2][1] = 0.0;   Mt[2][2] = 1.0;
00534 
00535   Mt_inv[0][0] = 1.0;   Mt_inv[0][1] = 0.0;   Mt_inv[0][2] = xo+tx;
00536   Mt_inv[1][0] = 0.0;   Mt_inv[1][1] = 1.0;   Mt_inv[1][2] = yo+ty;
00537   Mt_inv[2][0] = 0.0;   Mt_inv[2][1] = 0.0;   Mt_inv[2][2] = 1.0;
00538 
00539   double scc = c*scale, scs = s*scale;
00540   M[0][0] =scc ;   M[0][1] = -scs;   M[0][2] = 0;
00541   M[1][0] = scs;   M[1][1] = scc;    M[1][2] = 0;
00542   M[2][0] = 0.0;   M[2][1] = 0.0;    M[2][2] = 1.0;
00543   trans_ = Mt_inv*M*Mt*trans_;
00544 
00545   if (gradient_info_)
00546     this->transform_gradients(theta);
00547 }
00548 
00549 //:  Note this transform call does not currently transform gradient directions
00550 void strk_tracking_face_2d::transform(vnl_matrix_fixed<double,3,3> const& T)
00551 {
00552   vcl_vector<vtol_vertex_sptr> verts;
00553   this->face()->vertices(verts);
00554   for (vcl_vector<vtol_vertex_sptr>::iterator vit = verts.begin();
00555        vit != verts.end(); ++vit)
00556   {
00557     vtol_vertex_2d_sptr v = (*vit)->cast_to_vertex_2d();
00558     if (!v)
00559       continue;
00560     double x = v->x(), y = v->y();
00561     vnl_vector_fixed<double, 3> X(x, y, 1.0), Xp;
00562     Xp = T*X;
00563     v->set_x(Xp[0]);
00564     v->set_y(Xp[1]);
00565   }
00566   for (this->reset(); this->next();)
00567   {
00568     double x = this->X(), y = this->Y();
00569     vnl_vector_fixed<double, 3> X(x, y, 1.0), Xp;
00570     Xp = T*X;
00571     this->set_X(float(Xp[0]));
00572     this->set_Y(float(Xp[1]));
00573   }
00574   trans_ = T*trans_;
00575 }
00576 
00577 float strk_tracking_face_2d::
00578 compute_intensity_mutual_information(vil1_memory_image_of<float> const& image)
00579 {
00580   if (!intf_)
00581     return 0;
00582   int width = image.width(), height = image.height();
00583   bsta_histogram<float> image_hist(max_intensity_, intensity_hist_bins_);
00584   bsta_joint_histogram<float> joint_hist(max_intensity_, intensity_hist_bins_);
00585   unsigned int npix = intf_->Npix();
00586   if (npix == 0)
00587     return 0;
00588   unsigned int n = 0;
00589   for (intf_->reset(); intf_->next(); ++n)
00590   {
00591     int x = int(intf_->X()), y = int(intf_->Y());
00592     if (x<0||x>=width||y<0||y>=height)
00593       continue;
00594     float Ii = image(x,y);
00595     float Im = intf_->I();
00596     image_hist.upcount(Ii, 1.0f);
00597     joint_hist.upcount(Im, 1.0f, Ii, 1.0f);
00598 #ifdef DEBUG
00599     vcl_cout << '(' << x << ' ' << y << "):[" << Im << ' ' << Ii << ']' << vcl_endl;
00600 #endif
00601   }
00602   if (n<0.9*npix)
00603     return 0;
00604 #ifdef DEBUG
00605   vcl_cout << "Itensity Hist\n";
00606   image_hist.print();
00607   vcl_cout << "Joint Intensity Hist\n";
00608   joint_hist.print();
00609 #endif
00610   //apply parzen windows
00611   image_hist.parzen(parzen_sigma_);
00612   joint_hist.parzen(parzen_sigma_);
00613 
00614   //compute the mutual information
00615   intensity_entropy_= image_hist.entropy();
00616   intensity_joint_entropy_ = renyi_joint_entropy_ ? joint_hist.renyi_entropy() : joint_hist.entropy();
00617 
00618   float mi = float(model_intensity_entropy_ + intensity_entropy_ - intensity_joint_entropy_);
00619 
00620 #ifdef DEBUG
00621   vcl_cout << "Entropies:(M,I,J, MI)=(" << model_intensity_entropy_ << ' '
00622            << intensity_entropy_ << ' ' << intensity_joint_entropy_ << ' ' << mi <<")\n";
00623 #endif
00624   return mi;
00625 }
00626 
00627 float strk_tracking_face_2d::
00628 compute_intensity_mutual_information(vcl_vector <vcl_vector< vgl_point_2d<int> > > region_map,
00629                                      int base_x, int base_y,
00630                                      vil1_memory_image_of<float> const& image)
00631 {
00632   if (!intf_)
00633     return 0;
00634   int width = image.width(), height = image.height();
00635   bsta_histogram<float> image_hist(max_intensity_, intensity_hist_bins_);
00636   bsta_joint_histogram<float> joint_hist(max_intensity_, intensity_hist_bins_);
00637   unsigned int npix = intf_->Npix();
00638   if (npix == 0)
00639     return 0;
00640 #ifdef DEBUG
00641   unsigned int n = 0;
00642 #endif
00643   for (intf_->reset(); intf_->next();)
00644   {
00645     int x = int(intf_->X()), y = int(intf_->Y());
00646 
00647     //: region_map starts from (0,0)
00648     x = x - base_x; y = y - base_y;
00649     if (x < 0 || x >= static_cast<int>(region_map.size()) ||
00650         y < 0 || y >= static_cast<int>(region_map[x].size())) continue;
00651 
00652     //: read corresponding region 2 pixel from map
00653     vgl_point_2d<int> p = region_map[x][y];
00654     if (p.x() < 0 || p.y() < 0 || p.x() >= width || p.y() >= height) continue;
00655 
00656     float Ii = image(p.x(),p.y());
00657     float Im = intf_->I();
00658     image_hist.upcount(Ii, 1.0f);
00659     joint_hist.upcount(Im, 1.0f, Ii, 1.0f);
00660 #ifdef DEBUG
00661     vcl_cout << '(' << x << ' ' << y << "):[" << Im << ' ' << Ii << ']' << vcl_endl;
00662     ++n;
00663 #endif
00664   }
00665 
00666 // we don't know the relation of number of pixels in second region to
00667 // the number of pixels in the first region (maybe a constant can be put)
00668 #ifdef DEBUG
00669   vcl_cout << "n = " << n << ", 0.9*npix = " << 0.9*npix << " (n should be at least 0.9*npix)\n";
00670 #endif
00671 #if 0
00672   if (n<0.9*npix)
00673     return 0;
00674 #endif // 0
00675 
00676 #ifdef DEBUG
00677   vcl_cout << "Itensity Hist\n";
00678   image_hist.print();
00679   vcl_cout << "Joint Intensity Hist\n";
00680   joint_hist.print();
00681 #endif
00682   //apply parzen windows
00683   image_hist.parzen(parzen_sigma_);
00684   joint_hist.parzen(parzen_sigma_);
00685 
00686   //compute the mutual information
00687   intensity_entropy_= image_hist.entropy();
00688   intensity_joint_entropy_ = renyi_joint_entropy_ ? joint_hist.renyi_entropy() : joint_hist.entropy();
00689 
00690   float mi = float(model_intensity_entropy_ + intensity_entropy_ - intensity_joint_entropy_);
00691 
00692 #ifdef DEBUG
00693   vcl_cout << "Entropies:(M,I,J, MI)=(" << model_intensity_entropy_ << ' '
00694            << intensity_entropy_ << ' ' << intensity_joint_entropy_ << ' ' << mi <<")\n";
00695 #endif
00696   return mi;
00697 }
00698 
00699 float strk_tracking_face_2d::
00700 compute_gradient_mutual_information(vil1_memory_image_of<float> const& Ix,
00701                                     vil1_memory_image_of<float> const& Iy)
00702 {
00703   if (!intf_||!Ix||!Iy)
00704     return 0;
00705   int width = Ix.width(), height = Iy.height();
00706   bsta_histogram<float> image_dir_hist(360, gradient_dir_hist_bins_);
00707   bsta_joint_histogram<float> joint_dir_hist(360, gradient_dir_hist_bins_);
00708 
00709   unsigned int npix = intf_->Npix();
00710   if (npix == 0)
00711     return 0;
00712   double deg_rad = 180.0/vnl_math::pi;
00713   unsigned int n = 0;
00714   for (intf_->reset(); intf_->next(); ++n)
00715   {
00716     int x = int(intf_->X()), y = int(intf_->Y());
00717     if (x<0||x>=width||y<0||y>=height)
00718       continue;
00719     float Ix0 = this->Ix(n), Iy0 = this->Iy(n);
00720     float ang0 = float(deg_rad*vcl_atan2(Iy0, Ix0))+180.f;
00721     float mag0 = vcl_abs(Ix0)+vcl_abs(Iy0); // was: vcl_sqrt(Ix0*Ix0 + Iy0*Iy0);
00722     float Ixi = Ix(x,y), Iyi = Iy(x,y);
00723     float angi = float(deg_rad*vcl_atan2(Iyi, Ixi))+180.f;
00724     float magi = vcl_abs(Ixi)+vcl_abs(Iyi); // was: vcl_sqrt(Ixi*Ixi + Iyi*Iyi);
00725 #ifdef DEBUG
00726     vcl_cout << "ang0, mag0 " << ang0 << ' ' << mag0 << '\n'
00727              << "Ixi, Iyi " << Ixi << ' ' << Iyi << '\n'
00728              << "angi, magi " << angi << ' ' << magi << '\n';
00729 #endif
00730     if (mag0>min_gradient_&&magi>min_gradient_)
00731     {
00732       image_dir_hist.upcount(angi, magi);
00733       joint_dir_hist.upcount(ang0,mag0,angi,magi);
00734     }
00735   }
00736   if (n<0.9*npix)
00737     return 0;
00738 #ifdef DEBUG
00739   vcl_cout << "Image Dir Hist\n";
00740   image_dir_hist.print();
00741   vcl_cout << "Joint Dir Hist\n";
00742   joint_dir_hist.print();
00743 #endif
00744 
00745   //apply parzen windows
00746   image_dir_hist.parzen(parzen_sigma_);
00747   joint_dir_hist.parzen(parzen_sigma_);
00748 
00749   gradient_dir_entropy_ = image_dir_hist.entropy();
00750   gradient_joint_entropy_ = renyi_joint_entropy_ ? joint_dir_hist.renyi_entropy() : joint_dir_hist.entropy();
00751 
00752   float mi = float(model_gradient_dir_entropy_ + gradient_dir_entropy_ - gradient_joint_entropy_);
00753 #ifdef DEBUG
00754   vcl_cout << "Dir Entropies:(M,I,J, MI)=(" << model_gradient_dir_entropy_ << ' '
00755            << gradient_dir_entropy_ << ' ' << gradient_joint_entropy_ << ' ' << mi <<")\n";
00756 #endif
00757   return mi;
00758 }
00759 
00760 float strk_tracking_face_2d::
00761 compute_gradient_mutual_information(vcl_vector <vcl_vector< vgl_point_2d<int> > > region_map,
00762                                     int base_x, int base_y,
00763                                     vil1_memory_image_of<float> const& Ix,
00764                                     vil1_memory_image_of<float> const& Iy)
00765 {
00766   if (!intf_||!Ix||!Iy)
00767     return 0;
00768   int width = Ix.width(), height = Iy.height();
00769   bsta_histogram<float> image_dir_hist(360, gradient_dir_hist_bins_);
00770   bsta_joint_histogram<float> joint_dir_hist(360, gradient_dir_hist_bins_);
00771 
00772   unsigned int npix = intf_->Npix();
00773   if (npix == 0)
00774     return 0;
00775   double deg_rad = 180.0/vnl_math::pi;
00776   unsigned int n = 0;
00777   for (intf_->reset(); intf_->next(); ++n)
00778   {
00779     int x = int(intf_->X()), y = int(intf_->Y());
00780 
00781     x = x - base_x; y = y - base_y;
00782     if (x < 0 || x >= static_cast<int>(region_map.size()) ||
00783         y < 0 || y >= static_cast<int>(region_map[x].size())) continue;
00784 
00785     vgl_point_2d<int> p = region_map[x][y];
00786     if (p.x() < 0 || p.y() < 0 || p.x() >= width || p.y() >= height) continue;
00787 
00788     float Ix0 = this->Ix(n), Iy0 = this->Iy(n);
00789     float ang0 = float(deg_rad*vcl_atan2(Iy0, Ix0))+180.f;
00790     float mag0 = vcl_abs(Ix0)+vcl_abs(Iy0); // was: vcl_sqrt(Ix0*Ix0 + Iy0*Iy0);
00791 
00792     float Ixi = Ix(p.x(),p.y()), Iyi = Iy(p.x(),p.y());
00793     float angi = float(deg_rad*vcl_atan2(Iyi, Ixi))+180.f;
00794     float magi = vcl_abs(Ixi)+vcl_abs(Iyi); // was: vcl_sqrt(Ixi*Ixi + Iyi*Iyi);
00795 #ifdef DEBUG
00796     vcl_cout << "ang0, mag0 " << ang0 << ' ' << mag0 << '\n'
00797              << "Ixi, Iyi " << Ixi << ' ' << Iyi << '\n'
00798              << "angi, magi " << angi << ' ' << magi << '\n';
00799 #endif
00800     if (mag0>min_gradient_&&magi>min_gradient_)
00801     {
00802       image_dir_hist.upcount(angi, magi);
00803       joint_dir_hist.upcount(ang0,mag0,angi,magi);
00804     }
00805   }
00806 
00807 #ifdef DEBUG
00808   vcl_cout << "n = " << n << ", 0.9*npix = " << 0.9*npix << " (n should be larger than 0.9*npix)\n";
00809 #endif
00810 #if 0
00811   if (n<0.9*npix)
00812     return 0;
00813 #endif // 0
00814 
00815 #ifdef DEBUG
00816   vcl_cout << "Image Dir Hist\n";
00817   image_dir_hist.print();
00818   vcl_cout << "Joint Dir Hist\n";
00819   joint_dir_hist.print();
00820 #endif
00821 
00822   //apply parzen windows
00823   image_dir_hist.parzen(parzen_sigma_);
00824   joint_dir_hist.parzen(parzen_sigma_);
00825 
00826   gradient_dir_entropy_ = image_dir_hist.entropy();
00827   gradient_joint_entropy_ = renyi_joint_entropy_ ? joint_dir_hist.renyi_entropy() : joint_dir_hist.entropy();
00828 
00829   float mi = float(model_gradient_dir_entropy_ + gradient_dir_entropy_ - gradient_joint_entropy_);
00830 #ifdef DEBUG
00831   vcl_cout << "Dir Entropies:(M,I,J, MI)=(" << model_gradient_dir_entropy_ << ' '
00832            << gradient_dir_entropy_ << ' ' << gradient_joint_entropy_ << ' ' << mi <<")\n";
00833 #endif
00834   return mi;
00835 }
00836 
00837 float strk_tracking_face_2d::
00838 compute_color_mutual_information(vil1_memory_image_of<float> const& hue,
00839                                  vil1_memory_image_of<float> const& sat)
00840 {
00841   if (!intf_||!hue||!sat)
00842     return 0;
00843   int width = hue.width(), height = hue.height();
00844   bsta_histogram<float> color_hist(360, color_hist_bins_);
00845   bsta_joint_histogram<float> joint_color_hist(360, color_hist_bins_);
00846 
00847   unsigned int npix = intf_->Npix();
00848   if (npix == 0)
00849     return 0;
00850 
00851   unsigned int n = 0;
00852   for (intf_->reset(); intf_->next(); ++n)
00853   {
00854     int x = int(intf_->X()), y = int(intf_->Y());
00855     if (x<0||x>=width||y<0||y>=height)
00856       continue;
00857     float hue0 = this->hue(n), sat0 = this->sat(n);
00858     float hue_i = hue(x,y), sat_i = sat(x,y);
00859     if (sat_i>0)
00860       color_hist.upcount(hue_i, sat_i);
00861     if (sat0>0&&sat_i>0)
00862       joint_color_hist.upcount(hue0, sat0, hue_i, sat_i);
00863   }
00864   if (n<0.9*npix)
00865     return 0;
00866 
00867   //apply parzen windows
00868   color_hist.parzen(parzen_sigma_);
00869   joint_color_hist.parzen(parzen_sigma_);
00870 
00871   //compute entropies
00872   color_entropy_ = color_hist.entropy();
00873   color_joint_entropy_ = renyi_joint_entropy_? joint_color_hist.renyi_entropy() : joint_color_hist.entropy();
00874 
00875   float mi = float(model_color_entropy_ + color_entropy_ - color_joint_entropy_);
00876 
00877   return mi;
00878 }
00879 
00880 float strk_tracking_face_2d::
00881 compute_color_mutual_information(vcl_vector <vcl_vector< vgl_point_2d<int> > > region_map,
00882                                  int base_x, int base_y,
00883                                  vil1_memory_image_of<float> const& hue,
00884                                  vil1_memory_image_of<float> const& sat)
00885 {
00886   if (!intf_||!hue||!sat)
00887     return 0;
00888   int width = hue.width(), height = hue.height();
00889   bsta_histogram<float> color_hist(360, color_hist_bins_);
00890   bsta_joint_histogram<float> joint_color_hist(360, color_hist_bins_);
00891 
00892   unsigned int npix = intf_->Npix();
00893   if (npix == 0)
00894     return 0;
00895 
00896   unsigned int n = 0;
00897   for (intf_->reset(); intf_->next(); ++n)
00898   {
00899     int x = int(intf_->X()), y = int(intf_->Y());
00900 
00901     x = x - base_x; y = y - base_y;
00902     if (x < 0 || x >= static_cast<int>(region_map.size()) ||
00903         y < 0 || y >= static_cast<int>(region_map[x].size())) continue;
00904 
00905     vgl_point_2d<int> p = region_map[x][y];
00906     if (p.x() < 0 || p.y() < 0 || p.x() >= width || p.y() >= height) continue;
00907 
00908     float hue0 = this->hue(n), sat0 = this->sat(n);
00909     float hue_i = hue(p.x(),p.y()), sat_i = sat(p.x(),p.y());
00910 
00911     if (sat_i>0)
00912       color_hist.upcount(hue_i, sat_i);
00913     if (sat0>0&&sat_i>0)
00914       joint_color_hist.upcount(hue0, sat0, hue_i, sat_i);
00915   }
00916 
00917 #ifdef DEBUG
00918   vcl_cout << "n = " << n << ", 0.9*npix = " << 0.9*npix << " (n should be larger than 0.9*npix)\n";
00919 #endif
00920 #if 0
00921   if (n<0.9*npix)
00922     return 0;
00923 #endif
00924 
00925   //apply parzen windows
00926   color_hist.parzen(parzen_sigma_);
00927   joint_color_hist.parzen(parzen_sigma_);
00928 
00929   //compute entropies
00930   color_entropy_ = color_hist.entropy();
00931   color_joint_entropy_ = renyi_joint_entropy_? joint_color_hist.renyi_entropy() : joint_color_hist.entropy();
00932 
00933   float mi = float(model_color_entropy_ + color_entropy_ - color_joint_entropy_);
00934 
00935   return mi;
00936 }
00937 
00938 bool strk_tracking_face_2d::
00939 compute_mutual_information(vil1_memory_image_of<float> const& image,
00940                            vil1_memory_image_of<float> const& Ix,
00941                            vil1_memory_image_of<float> const& Iy,
00942                            vil1_memory_image_of<float> const& hue,
00943                            vil1_memory_image_of<float> const& sat)
00944 {
00945   if (!image)
00946     return false;
00947 
00948   if ((!Ix || !Iy) && gradient_info_)
00949     return false;
00950 
00951   if ((!hue || !sat) && color_info_)
00952     return false;
00953 
00954   this->set_int_mutual_info(this->compute_intensity_mutual_information(image));
00955 
00956   if (gradient_info_)
00957     this->set_grad_mutual_info(this->compute_gradient_mutual_information(Ix,Iy));
00958 
00959   if (color_info_)
00960     this->set_color_mutual_info(this->compute_color_mutual_information(hue, sat));
00961 
00962   return true;
00963 }
00964 
00965 //: take a map from pixels of face in image_0_ to the pixels of face in image_i_
00966 bool strk_tracking_face_2d::
00967 compute_mutual_information(vcl_vector <vcl_vector< vgl_point_2d<int> > > region_map,
00968                            int base_x, int base_y,
00969                            vil1_memory_image_of<float> const& image,
00970                            vil1_memory_image_of<float> const& Ix,
00971                            vil1_memory_image_of<float> const& Iy,
00972                            vil1_memory_image_of<float> const& hue,
00973                            vil1_memory_image_of<float> const& sat)
00974 {
00975   if (!image)
00976     return false;
00977 
00978   if ((!Ix || !Iy) && gradient_info_)
00979     return false;
00980 
00981   if ((!hue || !sat) && color_info_)
00982     return false;
00983 
00984   this->set_int_mutual_info(this->compute_intensity_mutual_information(region_map, base_x, base_y, image));
00985 
00986   if (gradient_info_)
00987     this->set_grad_mutual_info(this->compute_gradient_mutual_information(region_map, base_x, base_y, Ix, Iy));
00988 
00989   if (color_info_)
00990     this->set_color_mutual_info(this->compute_color_mutual_information(region_map, base_x, base_y, hue, sat));
00991 
00992   return true;
00993 }
00994 
00995 bool strk_tracking_face_2d::
00996 compute_only_gradient_mi(vil1_memory_image_of<float> const& Ix,
00997                          vil1_memory_image_of<float> const& Iy)
00998 {
00999   if ((!Ix || !Iy) && gradient_info_)
01000     return false;
01001 
01002   if (gradient_info_)
01003     this->set_grad_mutual_info(this->compute_gradient_mutual_information(Ix,Iy));
01004   return true;
01005 }
01006 
01007 
01008 void strk_tracking_face_2d::print_pixels(vil1_memory_image_of<float> const& image)
01009 {
01010   if (!image)
01011     return;
01012   int width = image.width(), height = image.height();
01013   for (intf_->reset(); intf_->next();)
01014   {
01015     int x = int(intf_->X()), y = int(intf_->Y());
01016     if (x<0||x>=width||y<0||y>=height)
01017       continue;
01018     float Ii = image(x,y);
01019     float Im = intf_->I();
01020     vcl_cout << '(' << x << ' ' << y << "):[" << Im << ' '
01021              << Ii << ']' << vcl_endl;
01022   }
01023 }
01024 
01025 void strk_tracking_face_2d::
01026 face_points(vcl_vector<vtol_topology_object_sptr>& points)
01027 {
01028   points.clear();
01029   for (intf_->reset(); intf_->next();)
01030   {
01031     double x = intf_->X(), y = intf_->Y();
01032     vtol_topology_object* to = new vtol_vertex_2d(x, y);
01033     points.push_back(to);
01034   }
01035 }
01036 
01037 //: randomly select a set of pixels from the interior
01038 vcl_vector<float> strk_tracking_face_2d::random_intensities(int& n_pix)
01039 {
01040   vcl_vector<float> rand_pix;
01041   if (!intf_)
01042     return rand_pix;
01043   int Np = this->Npix();
01044   if (n_pix > Np)
01045     n_pix = Np;
01046   //generate a random pixel index on [0, npix-1]
01047   unsigned short const* pix = intf_->Ij();
01048   for (int i = 0; i<n_pix; ++i)
01049   {
01050     float x = (n_pix-1)*float(vcl_rand()/(RAND_MAX+1.0));
01051     int ni = (int)x;
01052     if (ni>Np-1)
01053       ni = Np-1;
01054     float v = (float)pix[ni];
01055     rand_pix.push_back(v);
01056   }
01057   return rand_pix;
01058 }
01059 
01060 //: compute the intensity joint entropy between the pixels in the image under *this face and the "model" pixels of the other face.
01061 //
01062 float strk_tracking_face_2d::
01063 compute_intensity_joint_entropy(strk_tracking_face_2d_sptr const& other,
01064                                 vil1_memory_image_of<float> const& image)
01065 {
01066   if (!intf_||!other||!image)
01067     return 0;
01068   int width = image.width(), height = image.height();
01069   bsta_joint_histogram<float> joint_hist(max_intensity_, intensity_hist_bins_);
01070   unsigned int npix = intf_->Npix();
01071   unsigned int mpix = other->face()->Npix();
01072   if (npix == 0)
01073     return 0;
01074   unsigned int n = 0;
01075   //iterate through the pixels of the target model face
01076   for (intf_->reset(); intf_->next(); ++n)
01077   {
01078     int x = int(intf_->X()), y = int(intf_->Y());
01079     if (x<0||x>=width||y<0||y>=height)
01080       continue;
01081     float Ii = image(x,y);//the pixels under the target
01082     if (n<mpix)
01083       joint_hist.upcount((other->face()->Ij())[n], 1.0f, Ii, 1.0f);
01084   }
01085   if (n<0.9*npix)
01086     return 0;
01087 #ifdef DEBUG
01088   vcl_cout << "Joint Observation-Background  Hist\n";
01089   joint_hist.print();
01090 #endif
01091   //apply parzen windows
01092   joint_hist.parzen(parzen_sigma_);
01093 
01094   //compute the joint entropy
01095   return renyi_joint_entropy_ ? joint_hist.renyi_entropy() : joint_hist.entropy();
01096 }
01097 
01098 //: compute the intensity joint entropy between the model pixels of this face and the model pixels of the "other" face.
01099 //  The pixels from the "other" face are randomly selected and equal
01100 //  in number to the pixels inside *this face.  It is assumed that
01101 //  there is no spatial intersection of the two pixel sets.
01102 //
01103 float strk_tracking_face_2d::
01104 compute_model_intensity_joint_entropy(strk_tracking_face_2d_sptr const& other)
01105 {
01106   if (!intf_||!other)
01107     return 0;
01108 
01109   bsta_joint_histogram<float> joint_hist(max_intensity_, intensity_hist_bins_);
01110   int npix = intf_->Npix();
01111   if (npix == 0)
01112     return 0;
01113   int n = 0;
01114   vcl_vector<float> rand_int = other->random_intensities(npix);
01115   //iterate through the pixels of the target model face
01116   for (intf_->reset(); intf_->next(); ++n)
01117   {
01118     if (n<npix)
01119       joint_hist.upcount(rand_int[n], 1.0f, intf_->I(), 1.0f);
01120   }
01121   if (n<0.9*npix)
01122     return 0;
01123 #ifdef DEBUG
01124   vcl_cout << "Joint Model-Background  Hist\n";
01125   joint_hist.print();
01126 #endif
01127   //apply parzen windows
01128   joint_hist.parzen(parzen_sigma_);
01129 
01130   //compute the joint entropy
01131   return renyi_joint_entropy_ ? joint_hist.renyi_entropy() : joint_hist.entropy();
01132 }
01133 
01134 //: randomly select a set of pixels from the interior
01135 bool strk_tracking_face_2d::random_colors(int& n_pix,
01136                                           vcl_vector<float>& hue,
01137                                           vcl_vector<float>& sat)
01138 {
01139   hue.clear();
01140   sat.clear();
01141   if (!intf_||!hue_||!sat_)
01142     return false;
01143   int Np = this->Npix();
01144   if (!Np)
01145     return false;
01146   if (n_pix > Np)
01147     n_pix = Np;
01148   //generate a random pixel index on [0, npix-1]
01149   for (int i = 0; i<n_pix; ++i)
01150   {
01151     float x = (n_pix-1)*float(vcl_rand()/(RAND_MAX+1.0));
01152     int ni = (int)x;
01153     if (ni>Np-1)
01154       ni = Np-1;
01155     float hv = (float)hue_[ni];
01156     float sv = (float)sat_[ni];
01157     hue.push_back(hv);
01158     sat.push_back(sv);
01159   }
01160   return true;
01161 }
01162 
01163 float strk_tracking_face_2d::
01164 compute_color_joint_entropy(strk_tracking_face_2d_sptr const& other,
01165                             vil1_memory_image_of<float> const& hue,
01166                             vil1_memory_image_of<float> const& sat)
01167 {
01168   if (!intf_||!other||!hue||!sat||!hue_||!sat_)
01169     return 0;
01170   if (intf_->Npix() == 0)
01171     return 0;
01172   unsigned int mpix = other->face()->Npix();
01173   bsta_joint_histogram<float> joint_color_hist;
01174   int width = hue.width(), height = hue.height();
01175   unsigned int n = 0;
01176   for (intf_->reset(); intf_->next(); ++n)
01177   {
01178     int x = int(intf_->X()), y = int(intf_->Y());
01179     if (x<0||x>=width||y<0||y>=height)
01180       continue;
01181     float hue_i = hue(x,y), sat_i = sat(x,y);
01182 //  float hue_other = hvals[n], sat_other = svals[n];
01183     if (n<mpix)
01184     {
01185       float hue_other = other->hue(n), sat_other = other->sat(n);
01186       if (sat_other>0&&sat_i>0)
01187         joint_color_hist.upcount(hue_other, sat_other, hue_i, sat_i);
01188     }
01189   }
01190 #ifdef DEBUG
01191   vcl_cout << "Joint Color Background  Hist\n";
01192   joint_color_hist.print();
01193 #endif
01194   //apply parzen windows
01195   joint_color_hist.parzen(parzen_sigma_);
01196 
01197   return renyi_joint_entropy_ ? joint_color_hist.renyi_entropy() : joint_color_hist.entropy();
01198 }
01199 
01200 //: Difference in mutual information due to intensity
01201 //
01202 //     MI(this:obs, this:model)-MI(this:obs, other:model)
01203 //
01204 //  the stored model intensity information from the other face
01205 //  is compared with the observation intensites of *this face.  It is
01206 //  assumed that there is no intersection of the two pixel sets.
01207 //
01208 //  The other face has been constructed on the current image
01209 //  and so its model data reflects the current intensity statistics outside
01210 //  *this observation region
01211 //
01212 float strk_tracking_face_2d::
01213 intensity_mutual_info_diff(strk_tracking_face_2d_sptr const& other,
01214                            vil1_memory_image_of<float> const& image,
01215                            bool verbose)
01216 {
01217   if (!other||!image)
01218     return 0;
01219   //sets up the mutual information between the fa model and the current
01220   //image observation
01221   this->compute_intensity_mutual_information(image);
01222 
01223   float Hb =  other->model_intensity_entropy();
01224   float Hm =  this->model_intensity_entropy();
01225   float Ho =  this->intensity_entropy();
01226   float Hob = this->compute_intensity_joint_entropy(other, image);
01227   float Hmb = this->compute_model_intensity_joint_entropy(other);
01228   float Hom = intensity_joint_entropy_;
01229   float mi_diff = Hmb-Hom;
01230   if (verbose)
01231   {
01232     vcl_cout << "background entropy = " << Hb
01233              << "\nmodel entropy = " << Hm
01234              << "\nentropy = " << Ho
01235              << "\nobs-background joint entropy = " << Hob
01236              << "\nmodel-background joint entropy = " << Hmb
01237              << "\nobs-model joint entropy = " << Hom
01238              << "\nmutual info diff = " << mi_diff
01239              << vcl_endl << vcl_endl;
01240   }
01241   intensity_info_diff_ = mi_diff;
01242   return mi_diff;
01243 }
01244 
01245 //: Difference in mutual information due to color
01246 //
01247 //     MI(this:obs, this:model)-MI(this:obs, other:model)
01248 //
01249 //  the stored model color information from the other face
01250 //  is compared with the observation colors of *this face.  It is
01251 //  assumed that there is no intersection of the two pixel sets.
01252 //
01253 //  The other face has been constructed on the current image
01254 //  and so its model data reflects the current intensity statistics outside
01255 //  *this observation region
01256 //
01257 float strk_tracking_face_2d::
01258 color_mutual_info_diff(strk_tracking_face_2d_sptr const& other,
01259                        vil1_memory_image_of<float> const& hue,
01260                        vil1_memory_image_of<float> const& sat,
01261                        bool verbose)
01262 {
01263   if (!other||!hue||!sat)
01264     return 0;
01265   //sets up the mutual information between the fa model and the current
01266   //image observation
01267   this->compute_color_mutual_information(hue, sat);
01268 
01269   float Hb =  other->model_color_entropy();
01270   float Hm =  this->model_color_entropy();
01271   float Hob = this->compute_color_joint_entropy(other, hue, sat);
01272   float Hom = color_joint_entropy_;
01273   float mi_diff = Hm - Hb - Hom + Hob;
01274   if (verbose)
01275   {
01276     vcl_cout << "background color entropy = " << Hb
01277              << "\nmodel color entropy = " << Hm
01278              << "\nobs-background color joint entropy = " << Hob
01279              << "\nobs-model color joint entropy = " << Hom
01280              << "\ncolor mutual info diff = " << mi_diff
01281              << vcl_endl << vcl_endl;
01282   }
01283   color_info_diff_ = mi_diff;
01284   return mi_diff;
01285 }
01286 
01287 float strk_tracking_face_2d::
01288 intensity_mutual_info_diff(vcl_vector<strk_tracking_face_2d_sptr> const& others,
01289                            vil1_memory_image_of<float> const& image,
01290                            bool verbose)
01291 {
01292   if (!others.size()||!image)
01293     return 0;
01294   //sets up the mutual information between the fa model and the current
01295   //image observation
01296   this->compute_intensity_mutual_information(image);
01297   float Hm =  this->model_intensity_entropy();
01298   float Ho =  this->intensity_entropy();
01299   float Hom = intensity_joint_entropy_;
01300   int n_others = 0;
01301   float mi_diff_avg = 0, Hob_avg = 0, Hb_avg = 0;
01302   for (vcl_vector<strk_tracking_face_2d_sptr>::const_iterator fit = others.begin(); fit != others.end(); fit++, n_others++)
01303   {
01304     float Hb = (*fit)->model_intensity_entropy();
01305     float Hob = this->compute_intensity_joint_entropy(*fit, image);
01306     float mi_diff = Hm - Hb - Hom + Hob;
01307     Hb_avg += Hb;
01308     Hob_avg += Hob;
01309     mi_diff_avg += mi_diff;
01310   }
01311   if (n_others)
01312   {
01313     Hb_avg/=n_others;
01314     Hob_avg/=n_others;
01315     mi_diff_avg/=n_others;
01316   }
01317   if (verbose)
01318     {
01319     vcl_cout << "background entropy = " << Hb_avg
01320              << "\nmodel entropy = " << Hm
01321              << "\nobs entropy = " << Ho
01322              << "\nobs-background joint entropy = " << Hob_avg
01323              << "\nobs-model joint entropy = " << Hom
01324              << "\nmutual info diff = " << mi_diff_avg
01325              << vcl_endl << vcl_endl;
01326   }
01327   intensity_info_diff_ = mi_diff_avg;
01328   return mi_diff_avg;
01329 }
01330 
01331 float strk_tracking_face_2d::
01332 color_mutual_info_diff(vcl_vector<strk_tracking_face_2d_sptr> const& others,
01333                        vil1_memory_image_of<float> const& hue,
01334                        vil1_memory_image_of<float> const& sat,
01335                        bool verbose)
01336 {
01337   if (!others.size()||!hue||!sat)
01338     return 0;
01339   //sets up the mutual information between the fa model and the current
01340   //image observation
01341   this->compute_color_mutual_information(hue, sat);
01342 
01343   float Hm =  this->model_color_entropy();
01344   float Hom = color_joint_entropy_;
01345   int n_others = 0;
01346   float mi_diff_avg = 0, Hob_avg = 0, Hb_avg = 0;
01347   for (vcl_vector<strk_tracking_face_2d_sptr>::const_iterator fit = others.begin(); fit != others.end(); fit++, n_others++)
01348   {
01349     float Hb = (*fit)->model_color_entropy();
01350     float Hob = this->compute_color_joint_entropy(*fit, hue, sat);
01351     float mi_diff = Hm - Hb - Hom + Hob;
01352     Hb_avg += Hb;
01353     Hob_avg += Hob;
01354     mi_diff_avg += mi_diff;
01355   }
01356   if (n_others)
01357   {
01358     Hb_avg/=n_others;
01359     Hob_avg/=n_others;
01360     mi_diff_avg/=n_others;
01361   }
01362   if (verbose)
01363   {
01364     vcl_cout << "background color entropy = " << Hb_avg
01365              << "\nmodel color entropy = " << Hm
01366              << "\nobs-background color joint entropy = " << Hob_avg
01367              << "\nobs-model color joint entropy = " << Hom
01368              << "\ncolor mutual info diff = " << mi_diff_avg
01369              << vcl_endl << vcl_endl;
01370   }
01371   color_info_diff_ = mi_diff_avg;
01372   return mi_diff_avg;
01373 }
01374 
01375 float strk_tracking_face_2d::total_info_diff()
01376 {
01377   float temp = intensity_info_diff_+color_info_diff_;
01378   if (gradient_info_)
01379     return temp+gradient_dir_mi_;
01380   return temp;
01381 }
01382 
01383 void strk_tracking_face_2d::
01384 print_intensity_histograms(vil1_memory_image_of<float> const& image)
01385 {
01386   if (!intf_||!image)
01387     return;
01388   int width = image.width(), height = image.height();
01389   bsta_histogram<float> model_image_hist(max_intensity_, intensity_hist_bins_);
01390   bsta_histogram<float> obs_image_hist(max_intensity_, intensity_hist_bins_);
01391   if (intf_->Npix() == 0)
01392     return;
01393   for (intf_->reset(); intf_->next();)
01394   {
01395     int x = int(intf_->X()), y = int(intf_->Y());
01396     if (x<0||x>=width||y<0||y>=height)
01397       continue;
01398     float Ii = image(x,y);
01399     float Im = intf_->I();
01400     model_image_hist.upcount(Im, 1.0f);
01401     obs_image_hist.upcount(Ii, 1.0f);
01402   }
01403   vcl_cout << "model intensity histogram\n";
01404   model_image_hist.print();
01405   vcl_cout << "obs intensity histogram\n";
01406   obs_image_hist.print();
01407   vcl_cout << vcl_endl;
01408 }
01409 
01410 void strk_tracking_face_2d::
01411 print_gradient_histograms(vil1_memory_image_of<float> const& Ix,
01412                           vil1_memory_image_of<float> const& Iy)
01413 {
01414   if (!intf_||!Ix||!Iy)
01415     return;
01416   int width = Ix.width(), height = Iy.height();
01417   bsta_histogram<float> model_image_dir_hist(360, gradient_dir_hist_bins_);
01418   bsta_histogram<float> obs_image_dir_hist(360, gradient_dir_hist_bins_);
01419   if (intf_->Npix() == 0)
01420     return;
01421   double deg_rad = 180.0/vnl_math::pi;
01422   int n = 0;
01423   for (intf_->reset(); intf_->next(); ++n)
01424   {
01425     int x = int(intf_->X()), y = int(intf_->Y());
01426     if (x<0||x>=width||y<0||y>=height)
01427       continue;
01428     float Ix0 = this->Ix(n), Iy0 = this->Iy(n);
01429     float ang0 = float(deg_rad*vcl_atan2(Iy0, Ix0))+180.f;
01430     float mag0 = vcl_abs(Ix0)+vcl_abs(Iy0); // was: vcl_sqrt(Ix0*Ix0 + Iy0*Iy0);
01431     float Ixi = Ix(x,y), Iyi = Iy(x,y);
01432     float angi = float(deg_rad*vcl_atan2(Iyi, Ixi))+180.f;
01433     float magi = vcl_abs(Ixi)+vcl_abs(Iyi); // was: vcl_sqrt(Ixi*Ixi + Iyi*Iyi);
01434     if (mag0>min_gradient_&&magi>min_gradient_)
01435     {
01436       model_image_dir_hist.upcount(ang0, mag0);
01437       obs_image_dir_hist.upcount(angi, magi);
01438     }
01439   }
01440   vcl_cout << "model gradient dir histogram\n";
01441   model_image_dir_hist.print();
01442   vcl_cout << "obs gradient dir histogram\n";
01443   obs_image_dir_hist.print();
01444   vcl_cout << '\n';
01445 }
01446 
01447 void strk_tracking_face_2d::
01448 print_color_histograms(vil1_memory_image_of<float> const& hue,
01449                        vil1_memory_image_of<float> const& sat)
01450 {
01451   if (!intf_||!hue||!sat)
01452     return;
01453   int width = hue.width(), height = hue.height();
01454   bsta_histogram<float> model_color_hist(360, color_hist_bins_);
01455   bsta_histogram<float> obs_color_hist(360, color_hist_bins_);
01456 
01457   if (intf_->Npix() == 0)
01458     return;
01459   int n = 0;
01460   for (intf_->reset(); intf_->next(); ++n)
01461   {
01462     int x = int(intf_->X()), y = int(intf_->Y());
01463     if (x<0||x>=width||y<0||y>=height)
01464       continue;
01465     float hue0 = this->hue(n), sat0 = this->sat(n);
01466     float hue_i = hue(x,y), sat_i = sat(x,y);
01467     if (sat0>0)
01468       model_color_hist.upcount(hue0, sat0);
01469     if (sat_i>0)
01470       obs_color_hist.upcount(hue_i, sat_i);
01471   }
01472   vcl_cout << "model color histogram\n";
01473   model_color_hist.print();
01474   vcl_cout << "obs color histogram\n";
01475   obs_color_hist.print();
01476   vcl_cout << '\n';
01477 }
01478 
01479 bsta_histogram<float> strk_tracking_face_2d::
01480 intensity_histogram(vil1_memory_image_of<float> const& image)
01481 {
01482   bsta_histogram<float> image_hist(max_intensity_, intensity_hist_bins_);
01483   if (!intf_||!image)
01484     return image_hist;
01485   int width = image.width(), height = image.height();
01486   if (intf_->Npix() == 0)
01487     return image_hist;
01488   for (intf_->reset(); intf_->next();)
01489   {
01490     int x = int(intf_->X()), y = int(intf_->Y());
01491     if (x<0||x>=width||y<0||y>=height)
01492       continue;
01493     float Ii = image(x,y);
01494     image_hist.upcount(Ii, 1.0f);
01495   }
01496   return image_hist;
01497 }
01498 
01499 bsta_histogram<float> strk_tracking_face_2d::
01500 gradient_histogram(vil1_memory_image_of<float> const& Ix,
01501                    vil1_memory_image_of<float> const& Iy)
01502 {
01503   bsta_histogram<float> grad_dir_hist(360, gradient_dir_hist_bins_);
01504   if (!intf_||!Ix||!Iy)
01505     return grad_dir_hist;
01506   int width = Ix.width(), height = Iy.height();
01507   if (intf_->Npix() == 0)
01508     return grad_dir_hist;
01509   double deg_rad = 180.0/vnl_math::pi;
01510   for (intf_->reset(); intf_->next();)
01511   {
01512     int x = int(intf_->X()), y = int(intf_->Y());
01513     if (x<0||x>=width||y<0||y>=height)
01514       continue;
01515     float Ixi = Ix(x,y), Iyi = Iy(x,y);
01516     float angi = float(deg_rad*vcl_atan2(Iyi, Ixi))+180.f;
01517     float magi = vcl_abs(Ixi)+vcl_abs(Iyi); // was: vcl_sqrt(Ixi*Ixi + Iyi*Iyi);
01518     if (magi>min_gradient_)
01519       grad_dir_hist.upcount(angi, magi);
01520   }
01521   return grad_dir_hist;
01522 }
01523 
01524 bsta_histogram<float> strk_tracking_face_2d::
01525 color_histogram(vil1_memory_image_of<float> const& hue,
01526                 vil1_memory_image_of<float> const& sat)
01527 {
01528   bsta_histogram<float> color_hist(360, color_hist_bins_);
01529   if (!intf_||!hue||!sat)
01530     return color_hist;
01531   int width = hue.width(), height = hue.height();
01532   if (intf_->Npix() == 0)
01533     return color_hist;
01534   for (intf_->reset(); intf_->next();)
01535   {
01536     int x = int(intf_->X()), y = int(intf_->Y());
01537     if (x<0||x>=width||y<0||y>=height)
01538       continue;
01539     float hue_i = hue(x,y), sat_i = sat(x,y);
01540 #ifdef DEBUG
01541     vcl_cout << "HS(" << hue_i << ' ' << sat_i << ")\n";
01542 #endif
01543     if (sat_i>0)
01544       color_hist.upcount(hue_i, sat_i);
01545   }
01546   return color_hist;
01547 }