Removed the definition of basename, which confuses an existing system one.
[folded-ctf.git] / pose_cell_hierarchy.cc
index 0816f3a..baa6459 100644 (file)
@@ -1,33 +1,39 @@
-
-///////////////////////////////////////////////////////////////////////////
-// This program is free software: you can redistribute it and/or modify  //
-// it under the terms of the version 3 of the GNU General Public License //
-// as published by the Free Software Foundation.                         //
-//                                                                       //
-// This program is distributed in the hope that it will be useful, but   //
-// WITHOUT ANY WARRANTY; without even the implied warranty of            //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
-// General Public License for more details.                              //
-//                                                                       //
-// You should have received a copy of the GNU General Public License     //
-// along with this program. If not, see <http://www.gnu.org/licenses/>.  //
-//                                                                       //
-// Written by Francois Fleuret, (C) IDIAP                                //
-// Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
-///////////////////////////////////////////////////////////////////////////
+/*
+ *  folded-ctf is an implementation of the folded hierarchy of
+ *  classifiers for object detection, developed by Francois Fleuret
+ *  and Donald Geman.
+ *
+ *  Copyright (c) 2008 Idiap Research Institute, http://www.idiap.ch/
+ *  Written by Francois Fleuret <francois.fleuret@idiap.ch>
+ *
+ *  This file is part of folded-ctf.
+ *
+ *  folded-ctf is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 3 as
+ *  published by the Free Software Foundation.
+ *
+ *  folded-ctf is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with folded-ctf.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
 
 #include "pose_cell_hierarchy.h"
 #include "gaussian.h"
 
 PoseCellHierarchy::PoseCellHierarchy() {
-  _body_cells = 0;
+  _belly_cells = 0;
 }
 
 PoseCellHierarchy::PoseCellHierarchy(LabelledImagePool *train_pool) {
   _nb_levels = global.nb_levels;
   _min_head_radius = global.min_head_radius;
   _max_head_radius = global.max_head_radius;
-  _root_cell_nb_xy_per_scale = global.root_cell_nb_xy_per_scale;
+  _root_cell_nb_xy_per_radius = global.root_cell_nb_xy_per_radius;
 
   LabelledImage *image;
   int nb_total_targets = 0;
@@ -38,7 +44,7 @@ PoseCellHierarchy::PoseCellHierarchy(LabelledImagePool *train_pool) {
     train_pool->release_image(i);
   }
 
-  RelativeBodyPoseCell targets[nb_total_targets];
+  RelativeBellyPoseCell targets[nb_total_targets];
 
   int u = 0;
   for(int i = 0; i < train_pool->nb_images(); i++) {
@@ -53,16 +59,16 @@ PoseCellHierarchy::PoseCellHierarchy(LabelledImagePool *train_pool) {
 
       cell_set.get_containing_cell(&pose)->get_centroid(&coarse);
 
-      targets[u]._body_xc.set((pose._body_xc - coarse._head_xc) / coarse._head_radius);
-      targets[u]._body_yc.set((pose._body_yc - coarse._head_yc) / coarse._head_radius);
+      targets[u]._belly_xc.set((pose._belly_xc - coarse._head_xc) / coarse._head_radius);
+      targets[u]._belly_yc.set((pose._belly_yc - coarse._head_yc) / coarse._head_radius);
       u++;
 
       pose.horizontal_flip(image->width());
 
       cell_set.get_containing_cell(&pose)->get_centroid(&coarse);
 
-      targets[u]._body_xc.set((pose._body_xc - coarse._head_xc) / coarse._head_radius);
-      targets[u]._body_yc.set((pose._body_yc - coarse._head_yc) / coarse._head_radius);
+      targets[u]._belly_xc.set((pose._belly_xc - coarse._head_xc) / coarse._head_radius);
+      targets[u]._belly_yc.set((pose._belly_yc - coarse._head_yc) / coarse._head_radius);
       u++;
     }
 
@@ -71,38 +77,30 @@ PoseCellHierarchy::PoseCellHierarchy(LabelledImagePool *train_pool) {
 
   scalar_t fattening = 1.1;
 
-  Interval body_rxc, body_ryc;
+  Interval belly_rxc, belly_ryc;
 
-  body_rxc.set(&targets[0]._body_xc);
-  body_ryc.set(&targets[0]._body_yc);
+  belly_rxc.set(&targets[0]._belly_xc);
+  belly_ryc.set(&targets[0]._belly_yc);
 
   for(int t = 0; t < nb_total_targets; t++) {
-    body_rxc.swallow(&targets[t]._body_xc);
-    body_ryc.swallow(&targets[t]._body_yc);
+    belly_rxc.swallow(&targets[t]._belly_xc);
+    belly_ryc.swallow(&targets[t]._belly_yc);
   }
 
-  body_rxc.min *= fattening;
-  body_rxc.max *= fattening;
-  body_ryc.min *= fattening;
-  body_ryc.max *= fattening;
-
-  scalar_t body_rxc_min = body_resolution * floor(body_rxc.min / body_resolution);
-  int nb_body_rxc = int(ceil((body_rxc.max - body_rxc_min) / body_resolution));
+  belly_rxc.min *= fattening;
+  belly_rxc.max *= fattening;
+  belly_ryc.min *= fattening;
+  belly_ryc.max *= fattening;
 
-  scalar_t body_ryc_min = body_resolution * floor(body_ryc.min / body_resolution);
-  int nb_body_ryc = int(ceil((body_ryc.max - body_ryc_min) / body_resolution));
+  scalar_t belly_rxc_min = belly_resolution * floor(belly_rxc.min / belly_resolution);
+  int nb_belly_rxc = int(ceil((belly_rxc.max - belly_rxc_min) / belly_resolution));
 
-  (*global.log_stream) << "body_rxc = " << body_rxc << endl
-                       << "body_rxc_min = " << body_rxc_min << endl
-                       << "body_rxc_min + nb_body_rxc * body_resolution = " << body_rxc_min + nb_body_rxc * body_resolution << endl
-                       << endl
-                       << "body_ryc = " << body_ryc << endl
-                       << "body_ryc_min = " << body_ryc_min << endl
-                       << "body_ryc_min + nb_body_ryc * body_resolution = " << body_ryc_min + nb_body_ryc * body_resolution << endl;
+  scalar_t belly_ryc_min = belly_resolution * floor(belly_ryc.min / belly_resolution);
+  int nb_belly_ryc = int(ceil((belly_ryc.max - belly_ryc_min) / belly_resolution));
 
-  int used[nb_body_rxc * nb_body_rxc];
+  int used[nb_belly_rxc * nb_belly_rxc];
 
-  for(int k = 0; k < nb_body_rxc * nb_body_ryc; k++) {
+  for(int k = 0; k < nb_belly_rxc * nb_belly_ryc; k++) {
     used[k] = 1;
   }
 
@@ -113,129 +111,65 @@ PoseCellHierarchy::PoseCellHierarchy(LabelledImagePool *train_pool) {
     scalar_t rho = 0;
 
     for(int t = 0; t < nb_total_targets; t++) {
-      rho = min(rho, vx * targets[t]._body_xc.middle() + vy * targets[t]._body_yc.middle());
+      rho = min(rho, vx * targets[t]._belly_xc.middle() + vy * targets[t]._belly_yc.middle());
     }
 
     rho *= fattening;
 
-    for(int j = 0; j < nb_body_ryc; j++) {
-      for(int i = 0; i < nb_body_rxc; i++) {
+    for(int j = 0; j < nb_belly_ryc; j++) {
+      for(int i = 0; i < nb_belly_rxc; i++) {
         if(
-           vx * (scalar_t(i + 0) * body_resolution + body_rxc_min) +
-           vy * (scalar_t(j + 0) * body_resolution + body_ryc_min) < rho
+           vx * (scalar_t(i + 0) * belly_resolution + belly_rxc_min) +
+           vy * (scalar_t(j + 0) * belly_resolution + belly_ryc_min) < rho
            &&
-           vx * (scalar_t(i + 1) * body_resolution + body_rxc_min) +
-           vy * (scalar_t(j + 0) * body_resolution + body_ryc_min) < rho
+           vx * (scalar_t(i + 1) * belly_resolution + belly_rxc_min) +
+           vy * (scalar_t(j + 0) * belly_resolution + belly_ryc_min) < rho
            &&
-           vx * (scalar_t(i + 0) * body_resolution + body_rxc_min) +
-           vy * (scalar_t(j + 1) * body_resolution + body_ryc_min) < rho
+           vx * (scalar_t(i + 0) * belly_resolution + belly_rxc_min) +
+           vy * (scalar_t(j + 1) * belly_resolution + belly_ryc_min) < rho
            &&
-           vx * (scalar_t(i + 1) * body_resolution + body_rxc_min) +
-           vy * (scalar_t(j + 1) * body_resolution + body_ryc_min) < rho
+           vx * (scalar_t(i + 1) * belly_resolution + belly_rxc_min) +
+           vy * (scalar_t(j + 1) * belly_resolution + belly_ryc_min) < rho
            ) {
-          used[i + j * nb_body_rxc] = 0;
+          used[i + j * nb_belly_rxc] = 0;
         }
       }
     }
   }
 
-  _nb_body_cells = 0;
-  for(int j = 0; j < nb_body_ryc; j++) {
-    for(int i = 0; i < nb_body_rxc; i++) {
-      if(used[i + nb_body_rxc * j]) {
-        _nb_body_cells++;
+  _nb_belly_cells = 0;
+  for(int j = 0; j < nb_belly_ryc; j++) {
+    for(int i = 0; i < nb_belly_rxc; i++) {
+      if(used[i + nb_belly_rxc * j]) {
+        _nb_belly_cells++;
       }
     }
   }
 
-  _body_cells = new RelativeBodyPoseCell[_nb_body_cells];
-
-  for(int j = 0; j < nb_body_ryc; j++) {
-    for(int i = 0; i < nb_body_rxc; i++) {
-      if(used[i + nb_body_rxc * j]) {
-        if(sq(scalar_t(i) * body_resolution + body_resolution/2 + body_rxc_min) +
-           sq(scalar_t(j) * body_resolution + body_resolution/2 + body_ryc_min) <= 1) {
-          (*global.log_stream) << "*";
-        } else {
-          (*global.log_stream) << "X";
-        }
-      } else {
-        (*global.log_stream) << ".";
-      }
-    }
-    (*global.log_stream) << endl;
-  }
+  _belly_cells = new RelativeBellyPoseCell[_nb_belly_cells];
 
   int k = 0;
-  for(int j = 0; j < nb_body_ryc; j++) {
-    for(int i = 0; i < nb_body_rxc; i++) {
-
-      if(used[i + nb_body_rxc * j]) {
-
-        RelativeBodyPoseCell mother;
-
-        scalar_t x = scalar_t(i) * body_resolution + body_rxc_min;
-        scalar_t y = scalar_t(j) * body_resolution + body_ryc_min;
-
-        mother._body_xc.set(x, x + body_resolution);
-        mother._body_yc.set(y, y + body_resolution);
+  for(int j = 0; j < nb_belly_ryc; j++) {
+    for(int i = 0; i < nb_belly_rxc; i++) {
 
-        //         scalar_t dist_min = body_resolution;
-        scalar_t dist_min = 1e6;
+      if(used[i + nb_belly_rxc * j]) {
 
-        int nb_got;
+        RelativeBellyPoseCell mother;
 
-        Gaussian dist_body_radius_1, dist_body_radius_2, dist_body_tilt;
+        scalar_t x = scalar_t(i) * belly_resolution + belly_rxc_min;
+        scalar_t y = scalar_t(j) * belly_resolution + belly_ryc_min;
 
-        do {
+        mother._belly_xc.set(x, x + belly_resolution);
+        mother._belly_yc.set(y, y + belly_resolution);
 
-          nb_got = 0;
-
-          for(int t = 0; t < nb_total_targets; t++) {
-
-            scalar_t dist =
-              sqrt(sq(targets[t]._body_xc.middle() - x - body_resolution / 2) +
-                   sq(targets[t]._body_yc.middle() - y - body_resolution / 2));
-
-            if(dist <= dist_min) {
-              dist_body_radius_1.add_sample(targets[t]._body_radius_1.middle());
-              dist_body_radius_2.add_sample(targets[t]._body_radius_2.middle());
-              dist_body_tilt.add_sample(targets[t]._body_tilt.middle());
-              nb_got++;
-            }
-
-          }
-
-          dist_min *= 2.0;
-        } while(nb_got < min(100, nb_total_targets));
-
-        scalar_t zeta = 4;
-
-        mother._body_radius_1.set(dist_body_radius_1.expectation() -
-                                  zeta * dist_body_radius_1.standard_deviation(),
-                                  dist_body_radius_1.expectation() +
-                                  zeta * dist_body_radius_1.standard_deviation());
-
-        mother._body_radius_2.set(dist_body_radius_2.expectation() -
-                                  zeta * dist_body_radius_2.standard_deviation(),
-                                  dist_body_radius_2.expectation() +
-                                  zeta * dist_body_radius_2.standard_deviation());
-
-        mother._body_tilt.set(dist_body_tilt.expectation() -
-                              zeta * dist_body_tilt.standard_deviation(),
-                              dist_body_tilt.expectation() +
-                              zeta * dist_body_tilt.standard_deviation());
-
-        _body_cells[k++] = mother;
+        _belly_cells[k++] = mother;
       }
     }
   }
-
-  (*global.log_stream) << _nb_body_cells << " body cells." << endl;
 }
 
 PoseCellHierarchy::~PoseCellHierarchy() {
-  delete[] _body_cells;
+  delete[] _belly_cells;
 }
 
 int PoseCellHierarchy::nb_levels() {
@@ -267,7 +201,7 @@ void PoseCellHierarchy::add_root_cells(Image *image, PoseCellSet *cell_set) {
   scalar_t beta = log(2) / scalar_t(global.nb_scales_per_power_of_two);
 
   for(int s = 0; s < nb_scales; s++) {
-    scalar_t cell_xy_size = exp(alpha + scalar_t(s) * beta) / global.root_cell_nb_xy_per_scale;
+    scalar_t cell_xy_size = exp(alpha + scalar_t(s) * beta) / global.root_cell_nb_xy_per_radius;
     PoseCell cell;
     cell._head_radius.min = exp(alpha + scalar_t(s) * beta);
     cell._head_radius.max = exp(alpha + scalar_t(s+1) * beta);
@@ -279,10 +213,10 @@ void PoseCellHierarchy::add_root_cells(Image *image, PoseCellSet *cell_set) {
         cell._head_xc.max = x + cell_xy_size;
         cell._head_yc.min = y;
         cell._head_yc.max = y + cell_xy_size;
-        cell._body_xc.min = cell._head_xc.min - pseudo_infty;
-        cell._body_xc.max = cell._head_xc.max + pseudo_infty;
-        cell._body_yc.min = cell._head_yc.min - pseudo_infty;
-        cell._body_yc.max = cell._head_yc.max + pseudo_infty;
+        cell._belly_xc.min = cell._head_xc.min - pseudo_infty;
+        cell._belly_xc.max = cell._head_xc.max + pseudo_infty;
+        cell._belly_yc.min = cell._head_yc.min - pseudo_infty;
+        cell._belly_yc.max = cell._head_yc.max + pseudo_infty;
         cell_set->add_cell(&cell);
       }
   }
@@ -295,16 +229,16 @@ void PoseCellHierarchy::add_subcells(int level, PoseCell *root,
 
   case 1:
     {
-      // Here we split the body-center coordinate cell part
+      // Here we split the belly-center coordinate cell part
       PoseCell cell = *root;
       scalar_t r = sqrt(cell._head_radius.min * cell._head_radius.max);
       scalar_t x = (cell._head_xc.min + cell._head_xc.max) / 2.0;
       scalar_t y = (cell._head_yc.min + cell._head_yc.max) / 2.0;
-      for(int k = 0; k < _nb_body_cells; k++) {
-        cell._body_xc.min = (_body_cells[k]._body_xc.min * r) + x;
-        cell._body_xc.max = (_body_cells[k]._body_xc.max * r) + x;
-        cell._body_yc.min = (_body_cells[k]._body_yc.min * r) + y;
-        cell._body_yc.max = (_body_cells[k]._body_yc.max * r) + y;
+      for(int k = 0; k < _nb_belly_cells; k++) {
+        cell._belly_xc.min = (_belly_cells[k]._belly_xc.min * r) + x;
+        cell._belly_xc.max = (_belly_cells[k]._belly_xc.max * r) + x;
+        cell._belly_yc.min = (_belly_cells[k]._belly_yc.min * r) + y;
+        cell._belly_yc.max = (_belly_cells[k]._belly_yc.max * r) + y;
         cell_set->add_cell(&cell);
       }
     }
@@ -372,21 +306,21 @@ int PoseCellHierarchy::nb_incompatible_poses(LabelledImagePool *pool) {
 void PoseCellHierarchy::write(ostream *os) {
   write_var(os, &_min_head_radius);
   write_var(os, &_max_head_radius);
-  write_var(os, &_root_cell_nb_xy_per_scale);
-  write_var(os, &_nb_body_cells);
-  for(int k = 0; k < _nb_body_cells; k++)
-    write_var(os, &_body_cells[k]);
+  write_var(os, &_root_cell_nb_xy_per_radius);
+  write_var(os, &_nb_belly_cells);
+  for(int k = 0; k < _nb_belly_cells; k++)
+    write_var(os, &_belly_cells[k]);
 }
 
 void PoseCellHierarchy::read(istream *is) {
-  delete[] _body_cells;
+  delete[] _belly_cells;
   read_var(is, &_min_head_radius);
   read_var(is, &_max_head_radius);
-  read_var(is, &_root_cell_nb_xy_per_scale);
-  read_var(is, &_nb_body_cells);
-  delete[] _body_cells;
-  _body_cells = new RelativeBodyPoseCell[_nb_body_cells];
-  for(int k = 0; k < _nb_body_cells; k++) {
-    read_var(is, &_body_cells[k]);
+  read_var(is, &_root_cell_nb_xy_per_radius);
+  read_var(is, &_nb_belly_cells);
+  delete[] _belly_cells;
+  _belly_cells = new RelativeBellyPoseCell[_nb_belly_cells];
+  for(int k = 0; k < _nb_belly_cells; k++) {
+    read_var(is, &_belly_cells[k]);
   }
 }