00001
00002 #include "strk_info_tracker.h"
00003
00004
00005 #include <vcl_algorithm.h>
00006 #include <vcl_cstdlib.h>
00007 #include <vul/vul_timer.h>
00008 #include <vil1/vil1_memory_image_of.h>
00009 #include <vsol/vsol_box_2d.h>
00010 #include <vtol/vtol_vertex_2d.h>
00011 #include <brip/brip_vil1_float_ops.h>
00012 #include <bsta/bsta_histogram.h>
00013 #include <strk/strk_tracking_face_2d.h>
00014
00015
00016 static bool info_compare(strk_tracking_face_2d_sptr const f1,
00017 strk_tracking_face_2d_sptr const f2)
00018 {
00019 return f1->total_info() > f2->total_info();
00020 }
00021
00022
00023 static bool info_diff_compare(strk_tracking_face_2d_sptr const f1,
00024 strk_tracking_face_2d_sptr const f2)
00025 {
00026 double d1 = f1->total_info_diff(), d2 = f2->total_info_diff();
00027 return d1 > d2;
00028 }
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 strk_info_tracker::strk_info_tracker(strk_info_tracker_params& tp)
00039 : strk_info_tracker_params(tp)
00040 {
00041
00042 }
00043
00044
00045 strk_info_tracker::~strk_info_tracker()
00046 {
00047 }
00048
00049
00050
00051
00052 void strk_info_tracker::set_image_0(vil1_image& image)
00053 {
00054 if (!image)
00055 {
00056 vcl_cout <<"In strk_info_tracker::set_image_i(.) - null input\n";
00057 return;
00058 }
00059
00060 vil1_memory_image_of<float> in, hue, sat;
00061 int w = image.width(), h = image.height();
00062
00063 if (!color_info_||image.components()==1)
00064 {
00065 vil1_memory_image_of<float> in=brip_vil1_float_ops::convert_to_float(image);
00066 image_0_= brip_vil1_float_ops::gaussian(in, sigma_);
00067 }
00068
00069 if (color_info_&&image.components()==3)
00070 {
00071 vil1_memory_image_of<vil1_rgb<unsigned char> > temp(image);
00072 brip_vil1_float_ops::convert_to_IHS(temp, in, hue, sat);
00073 image_0_= brip_vil1_float_ops::gaussian(in, sigma_);
00074 hue_0_ = brip_vil1_float_ops::gaussian(hue, sigma_);
00075 sat_0_ = brip_vil1_float_ops::gaussian(sat, sigma_);
00076 }
00077
00078 if (gradient_info_)
00079 {
00080 Ix_0_.resize(w,h);
00081 Iy_0_.resize(w,h);
00082 brip_vil1_float_ops::gradient_3x3(image_0_, Ix_0_, Iy_0_);
00083 }
00084 }
00085
00086
00087
00088
00089 void strk_info_tracker::set_image_i(vil1_image& image)
00090 {
00091 if (!image)
00092 {
00093 vcl_cout <<"In strk_info_tracker::set_image_i(.) - null input\n";
00094 return;
00095 }
00096
00097 vil1_memory_image_of<float> in, hue, sat;
00098 int w = image.width(), h = image.height();
00099
00100 if (!color_info_||image.components()==1)
00101 {
00102 vil1_memory_image_of<float> in=brip_vil1_float_ops::convert_to_float(image);
00103 image_i_= brip_vil1_float_ops::gaussian(in, sigma_);
00104 }
00105
00106 if (color_info_&&image.components()==3)
00107 {
00108 vil1_memory_image_of<vil1_rgb<unsigned char> > temp(image);
00109 brip_vil1_float_ops::convert_to_IHS(temp, in, hue, sat);
00110 image_i_= brip_vil1_float_ops::gaussian(in, sigma_);
00111 hue_i_ = brip_vil1_float_ops::gaussian(hue, sigma_);
00112 sat_i_ = brip_vil1_float_ops::gaussian(sat, sigma_);
00113 }
00114
00115 if (gradient_info_)
00116 {
00117 Ix_i_.resize(w,h);
00118 Iy_i_.resize(w,h);
00119 brip_vil1_float_ops::gradient_3x3(image_i_, Ix_i_, Iy_i_);
00120 }
00121 }
00122
00123
00124
00125 void strk_info_tracker::set_initial_model(vtol_face_2d_sptr const& face)
00126 {
00127 initial_model_ = face;
00128 }
00129
00130
00131
00132
00133 bool strk_info_tracker::init()
00134 {
00135 if (!image_0_)
00136 {
00137 vcl_cout << "In strk_info_tracker::init() - no initial video frame\n";
00138 return false;
00139 }
00140
00141 if (!initial_model_)
00142 {
00143 vcl_cout << "In strk_info_tracker::init() - not all faces set\n";
00144 return false;
00145 }
00146
00147 strk_tracking_face_2d_sptr tf;
00148 tf = new strk_tracking_face_2d(initial_model_, image_0_,
00149 Ix_0_, Iy_0_, hue_0_, sat_0_,
00150 min_gradient_,
00151 parzen_sigma_,
00152 intensity_hist_bins_,
00153 gradient_dir_hist_bins_,
00154 color_hist_bins_
00155 );
00156
00157 initial_tf_ = tf;
00158 if (renyi_joint_entropy_)
00159 tf->set_renyi_joint_entropy();
00160
00161 current_samples_.push_back(tf);
00162 return true;
00163 }
00164
00165
00166
00167 strk_tracking_face_2d_sptr strk_info_tracker::
00168 generate_randomly_positioned_sample(strk_tracking_face_2d_sptr const& seed)
00169 {
00170 if (!seed)
00171 return 0;
00172
00173 float tx = (2.f*search_radius_)*float(vcl_rand()/(RAND_MAX+1.0)) - search_radius_;
00174 float ty = (2.f*search_radius_)*float(vcl_rand()/(RAND_MAX+1.0)) - search_radius_;
00175 float theta = (2.f*angle_range_)*float(vcl_rand()/(RAND_MAX+1.0)) - angle_range_;
00176 float s = (2.f*scale_range_)*float(vcl_rand()/(RAND_MAX+1.0)) - scale_range_;
00177 float scale = 1+s;
00178 strk_tracking_face_2d* tf = new strk_tracking_face_2d(seed);
00179
00180 tf->transform(tx, ty, theta, scale);
00181 return tf;
00182 }
00183
00184 static void
00185 print_tracking_bounds(vcl_vector<strk_tracking_face_2d_sptr> const& faces)
00186 {
00187 if (faces.size() == 0)
00188 return;
00189 #ifdef DEBUG
00190 float xmin = faces.front()->face()->Xo(), xmax = xmin;
00191 float ymin = faces.front()->face()->Yo(), ymax = ymin;
00192 for (vcl_vector<strk_tracking_face_2d_sptr>::const_iterator fit =
00193 faces.begin(); fit != faces.end(); fit++)
00194 {
00195 float x = (*fit)->face()->Xo(), y = (*fit)->face()->Yo();
00196 if (x < xmin) xmin = x;
00197 if (x > xmax) xmax = x;
00198 if (y < ymin) ymin = y;
00199 if (y > ymax) ymax = y;
00200 }
00201 strk_tracking_face_2d_sptr f = faces[0];
00202 float search_area = (xmax-xmin)*(ymax-ymin);
00203 float R = f->Npix()/search_area;
00204 vcl_cout << "S[(" << xmin << ' ' << xmax << ")(" << ymin << ' ' << ymax
00205 << ")]= " << search_area << ", area ratio = " << R << '\n';
00206 #endif
00207 }
00208
00209
00210
00211 void strk_info_tracker::generate_samples()
00212 {
00213 vul_timer t;
00214 for (vcl_vector<strk_tracking_face_2d_sptr>::iterator fit =
00215 current_samples_.begin(); fit != current_samples_.end(); fit++)
00216 for (int i = 0; i<n_samples_; i++)
00217 {
00218 strk_tracking_face_2d_sptr tf, back;
00219 tf = this->generate_randomly_positioned_sample(*fit);
00220 if (!tf)
00221 continue;
00222 if (use_background_)
00223 {
00224 tf->intensity_mutual_info_diff(background_faces_, image_i_);
00225 if (color_info_)
00226 tf->color_mutual_info_diff(background_faces_, hue_i_, sat_i_);
00227 if (gradient_info_)
00228 tf->compute_only_gradient_mi(Ix_i_, Iy_i_);
00229 }
00230 else
00231 tf->compute_mutual_information(image_i_, Ix_i_, Iy_i_, hue_i_, sat_i_);
00232
00233 hypothesized_samples_.push_back(tf);
00234 }
00235
00236 if (use_background_)
00237 vcl_sort(hypothesized_samples_.begin(),
00238 hypothesized_samples_.end(), info_diff_compare);
00239 else
00240 vcl_sort(hypothesized_samples_.begin(),
00241 hypothesized_samples_.end(), info_compare);
00242 print_tracking_bounds(hypothesized_samples_);
00243 }
00244
00245 bool strk_info_tracker::refresh_sample()
00246 {
00247 #if 0
00248 double t = vcl_rand()/(RAND_MAX+1.0);
00249 return t<=frac_time_samples_;
00250 #else
00251 vcl_rand();
00252 return false;
00253 #endif // 0
00254 }
00255
00256 strk_tracking_face_2d_sptr strk_info_tracker::
00257 clone_and_refresh_data(strk_tracking_face_2d_sptr const& sample)
00258 {
00259 if (!sample)
00260 return (strk_tracking_face_2d*)0;
00261 vtol_face_2d_sptr f =
00262 sample->face()->cast_to_face_2d();
00263 strk_tracking_face_2d_sptr tf;
00264 tf = new strk_tracking_face_2d(f, image_i_, Ix_i_, Iy_i_, hue_i_, sat_i_,
00265 min_gradient_, parzen_sigma_,
00266 intensity_hist_bins_,
00267 gradient_dir_hist_bins_,
00268 color_hist_bins_
00269 );
00270 if (renyi_joint_entropy_)
00271 tf->set_renyi_joint_entropy();
00272 return tf;
00273 }
00274
00275
00276
00277 void strk_info_tracker::cull_samples()
00278 {
00279 current_samples_.clear();
00280 for (int i=0; i<n_samples_; i++)
00281 {
00282 current_samples_.push_back(hypothesized_samples_[i]);
00283 if (debug_)
00284 vcl_cout << "I[" << i << "]= " << hypothesized_samples_[i]->total_info() << vcl_endl;
00285 }
00286
00287 strk_tracking_face_2d_sptr tf = hypothesized_samples_[0];
00288 if (verbose_&&!use_background_)
00289 vcl_cout << "Total Inf = " << tf->total_info()
00290 << " = IntInfo(" << tf->int_mutual_info()
00291 << ") + GradInfo(" << tf->grad_mutual_info()
00292 << ") + ColorInfo(" << tf->color_mutual_info()
00293 << ')' << vcl_endl;
00294 bool hist_print = false;
00295 if (verbose_&&hist_print)
00296 {
00297 tf->print_intensity_histograms(image_i_);
00298 if (gradient_info_)
00299 tf->print_gradient_histograms(Ix_i_, Iy_i_);
00300 if (color_info_)
00301 tf->print_color_histograms(hue_i_, sat_i_);
00302 }
00303
00304 if (debug_)
00305 vcl_cout << "model_intensity_entropy = " << tf->model_intensity_entropy()
00306 << "\nintensity_entropy = " << tf->intensity_entropy()
00307 << "\nintensity_joint_entropy = " <<tf->intensity_joint_entropy()
00308 << "\n\nmodel_gradient_entropy = " << tf->model_gradient_entropy()
00309 << "\ngradient_entropy = " << tf->gradient_entropy()
00310 << "\ngradient_joint_entropy = " << tf->gradient_joint_entropy()
00311 << "\n\nmodel_color_entropy = " << tf->model_color_entropy()
00312 << "\ncolor_entropy = " << tf->color_entropy()
00313 << "\ncolor_joint_entropy = " << tf->color_joint_entropy()
00314 << vcl_endl << vcl_endl;
00315 #ifdef DEBUG
00316 tf->print_pixels(image_i_);
00317 #endif
00318
00319 hypothesized_samples_.clear();
00320
00321 strk_tracking_face_2d_sptr refreshed_best =
00322 clone_and_refresh_data(current_samples_[0]);
00323 track_history_.push_back(refreshed_best);
00324
00325
00326
00327 if (use_background_)
00328 {
00329 vcl_cout << "\n====Background Information Diffs====\n";
00330 float MIdiff =
00331 tf->intensity_info_diff();
00332 vcl_cout << "Intensity Inf Diff = " << MIdiff << vcl_endl;
00333 if (color_info_)
00334 {
00335 float color_MIdiff = tf->color_info_diff();
00336 vcl_cout << "Color Inf Diff = " << color_MIdiff << vcl_endl;
00337 }
00338 if (gradient_info_)
00339 {
00340 float grad_MI = tf->grad_mutual_info();
00341 vcl_cout << "Grad Mutual Info = " << grad_MI << vcl_endl;
00342 }
00343 vcl_cout << "Total Inf Diff = " << tf->total_info_diff() << vcl_endl;
00344
00345 this->construct_background_faces(tf->face()->cast_to_face_2d());
00346 }
00347 }
00348
00349
00350
00351 vtol_face_2d_sptr strk_info_tracker::get_best_sample()
00352 {
00353 if (!current_samples_.size())
00354 return 0;
00355
00356 return current_samples_[0]->face()->cast_to_face_2d();
00357 }
00358
00359
00360
00361 void strk_info_tracker::get_samples(vcl_vector<vtol_face_2d_sptr>& samples)
00362 {
00363 samples.clear();
00364 for (vcl_vector<strk_tracking_face_2d_sptr>::iterator
00365 fit = current_samples_.begin(); fit != current_samples_.end(); fit++)
00366 samples.push_back((*fit)->face()->cast_to_face_2d());
00367 }
00368
00369
00370
00371 void strk_info_tracker::track()
00372 {
00373 vul_timer t;
00374 this->generate_samples();
00375 if (verbose_)
00376 vcl_cout << "Samples generated in " << t.real() << " msecs.\n";
00377 this->cull_samples();
00378 }
00379
00380 void strk_info_tracker::clear()
00381 {
00382 current_samples_.clear();
00383 hypothesized_samples_.clear();
00384 }
00385
00386
00387
00388
00389 void strk_info_tracker::evaluate_info()
00390 {
00391 if (!initial_model_)
00392 return;
00393 strk_tracking_face_2d_sptr tf =
00394 new strk_tracking_face_2d(initial_model_, image_0_,
00395 Ix_0_, Iy_0_, hue_0_, sat_0_,
00396 min_gradient_,
00397 parzen_sigma_,
00398 intensity_hist_bins_,
00399 gradient_dir_hist_bins_,
00400 color_hist_bins_
00401 );
00402
00403 if (renyi_joint_entropy_)
00404 tf->set_renyi_joint_entropy();
00405
00406 if (!tf->compute_mutual_information(image_i_, Ix_i_, Iy_i_, hue_i_, sat_i_))
00407 return;
00408
00409 if (verbose_)
00410 vcl_cout << "Total Inf = " << tf->total_info()
00411 << " = IntInfo(" << tf->int_mutual_info()
00412 << ") + GradInfo(" << tf->grad_mutual_info()
00413 << ") + ColorInfo(" << tf->color_mutual_info()
00414 << ')' << vcl_endl;
00415
00416 if (debug_)
00417 vcl_cout << "model_intensity_entropy = " << tf->model_intensity_entropy()
00418 << "\nintensity_entropy = " << tf->intensity_entropy()
00419 << "\nintensity_joint_entropy = " <<tf->intensity_joint_entropy()
00420 << "\n\nmodel_gradient_entropy = " << tf->model_gradient_entropy()
00421 << "\ngradient_entropy = " << tf->gradient_entropy()
00422 << "\ngradient_joint_entropy = " << tf->gradient_joint_entropy()
00423 << "\n\nmodel_color_entropy = " << tf->model_color_entropy()
00424 << "\ncolor_entropy = " << tf->color_entropy()
00425 << "\ncolor_joint_entropy = " << tf->color_joint_entropy()
00426 << vcl_endl << vcl_endl;
00427 }
00428
00429 void strk_info_tracker::
00430 get_best_face_points(vcl_vector<vtol_topology_object_sptr>& points)
00431 {
00432 points.clear();
00433 if (!current_samples_.size())
00434 return;
00435 if (!use_background_)
00436 current_samples_[0]->face_points(points);
00437 }
00438
00439
00440
00441
00442 bool strk_info_tracker::
00443 construct_background_faces(vtol_face_2d_sptr const& current_model,
00444 bool first_frame)
00445 {
00446 if (!current_model)
00447 return false;
00448 background_faces_.clear();
00449 vsol_box_2d_sptr bb = current_model->get_bounding_box();
00450 if (!bb)
00451 return false;
00452 double min_x = bb->get_min_x();
00453 double max_x = bb->get_max_x();
00454 double min_y = bb->get_min_y();
00455 double max_y = bb->get_max_y();
00456 double width = max_x-min_x;
00457 double height = max_y-min_y;
00458 vcl_vector<vtol_vertex_sptr> verts;
00459 vcl_vector<vtol_vertex_2d_sptr> model_verts_2d;
00460 current_model->vertices(verts);
00461 for (vcl_vector<vtol_vertex_sptr>::iterator vit = verts.begin();
00462 vit != verts.end();vit++)
00463 model_verts_2d.push_back((*vit)->cast_to_vertex_2d());
00464 double tx[4], ty[4];
00465 tx[0]=width; ty[0]=0;
00466 tx[1]=-width; ty[1]=0;
00467 tx[2]=0; ty[2]=height;
00468 tx[3]=0; ty[3]=-height;
00469 for (int i = 0; i<4; i++)
00470 {
00471 vcl_vector<vtol_vertex_sptr> face_verts;
00472 for (vcl_vector<vtol_vertex_2d_sptr>::iterator vit =model_verts_2d.begin();
00473 vit != model_verts_2d.end(); vit++)
00474 {
00475 vtol_vertex_2d_sptr mv = (*vit);
00476 double x = mv->x()+tx[i], y = mv->y()+ty[i];
00477 vtol_vertex_2d_sptr tmv = new vtol_vertex_2d(x, y);
00478 face_verts.push_back(tmv->cast_to_vertex());
00479 }
00480 vtol_face_2d_sptr f = new vtol_face_2d(face_verts);
00481 strk_tracking_face_2d_sptr tf;
00482 if (first_frame)
00483 tf = new strk_tracking_face_2d(f, image_0_,
00484 Ix_0_, Iy_0_,
00485 hue_0_, sat_0_,
00486 min_gradient_,
00487 parzen_sigma_,
00488 intensity_hist_bins_,
00489 gradient_dir_hist_bins_,
00490 color_hist_bins_
00491 );
00492 else
00493 tf = new strk_tracking_face_2d(f, image_i_,
00494 Ix_i_, Iy_i_,
00495 hue_i_, sat_i_,
00496 min_gradient_,
00497 parzen_sigma_,
00498 intensity_hist_bins_,
00499 gradient_dir_hist_bins_,
00500 color_hist_bins_
00501 );
00502 if (!tf->Npix())
00503 continue;
00504
00505 if (renyi_joint_entropy_)
00506 tf->set_renyi_joint_entropy();
00507 tf->compute_mutual_information(image_i_,
00508 Ix_i_, Iy_i_,
00509 hue_i_, sat_i_);
00510 background_faces_.push_back(tf);
00511 }
00512 return true;
00513 }
00514
00515 bool
00516 strk_info_tracker::get_background_faces(vcl_vector<vtol_face_2d_sptr>& faces)
00517 {
00518 if (!background_faces_.size())
00519 return false;
00520 faces.clear();
00521 for (vcl_vector<strk_tracking_face_2d_sptr>::iterator fit = background_faces_.begin(); fit != background_faces_.end(); fit++)
00522 faces.push_back((*fit)->face()->cast_to_face_2d());
00523 return true;
00524 }
00525
00526
00527
00528 vcl_vector<float>
00529 strk_info_tracker::extract_histograms(strk_tracking_face_2d_sptr const& tf,
00530 bool first_frame)
00531 {
00532
00533 unsigned int ibins = intensity_hist_bins_;
00534 unsigned int gbins = gradient_dir_hist_bins_;
00535 unsigned int cbins = color_hist_bins_;
00536 unsigned int nbins = ibins + gbins + cbins;
00537 vcl_vector<float> out(nbins, 0.0);
00538 bsta_histogram<float> int_hist(0, 0);
00539 if (first_frame)
00540 int_hist= tf->intensity_histogram(image_0_);
00541 else
00542 int_hist= tf->intensity_histogram(image_i_);
00543 for (unsigned int i = 0; i<ibins; ++i)
00544 out[i]=int_hist.p(i);
00545
00546 if (gradient_info_)
00547 {
00548 bsta_histogram<float> grad_hist(0, 0);
00549 if (first_frame)
00550 grad_hist = tf->gradient_histogram(Ix_0_, Iy_0_);
00551 else
00552 grad_hist = tf->gradient_histogram(Ix_i_, Iy_i_);
00553 for (unsigned int i = 0; i<gbins; ++i)
00554 out[i+ibins]=grad_hist.p(i);
00555 }
00556 if (color_info_)
00557 {
00558 bsta_histogram<float> color_hist(0,0);
00559 if (first_frame)
00560 color_hist = tf->color_histogram(hue_0_, sat_0_);
00561 else
00562 color_hist = tf->color_histogram(hue_i_, sat_i_);
00563 for (unsigned int i = 0; i<cbins; ++i)
00564 out[i+ibins+gbins]=color_hist.p(i);
00565 }
00566 return out;
00567 }
00568
00569
00570 vcl_vector<float>
00571 strk_info_tracker::histograms()
00572 {
00573 strk_tracking_face_2d_sptr tf = current_samples_[0];
00574 return this->extract_histograms(tf);
00575 }
00576
00577
00578 vcl_vector<float>
00579 strk_info_tracker::capture_histograms(bool first_frame)
00580 {
00581 if (first_frame)
00582 return this->extract_histograms(initial_tf_, first_frame);
00583 return this->extract_histograms(capture_tf_, first_frame);
00584 }
00585
00586 void strk_info_tracker::set_capture_face(vtol_face_2d_sptr const& face,
00587 bool first_frame)
00588 {
00589 capture_face_ = face;
00590 if (first_frame)
00591 capture_tf_ = new strk_tracking_face_2d(face, image_0_,
00592 Ix_0_, Iy_0_,
00593 hue_0_, sat_0_,
00594 min_gradient_,
00595 parzen_sigma_,
00596 intensity_hist_bins_,
00597 gradient_dir_hist_bins_,
00598 color_hist_bins_
00599 );
00600 else
00601 capture_tf_ = new strk_tracking_face_2d(face, image_i_,
00602 Ix_i_, Iy_i_,
00603 hue_i_, sat_i_,
00604 min_gradient_,
00605 parzen_sigma_,
00606 intensity_hist_bins_,
00607 gradient_dir_hist_bins_,
00608 color_hist_bins_
00609 );
00610 }