automatic commit
[folded-ctf.git] / list_to_pool.cc
diff --git a/list_to_pool.cc b/list_to_pool.cc
new file mode 100644 (file)
index 0000000..c142534
--- /dev/null
@@ -0,0 +1,280 @@
+
+///////////////////////////////////////////////////////////////////////////
+// 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        //
+///////////////////////////////////////////////////////////////////////////
+
+#include <fstream>
+
+using namespace std;
+
+#include "misc.h"
+#include "global.h"
+#include "param_parser.h"
+#include "labelled_image.h"
+
+void parse_warning(const char *message, char *file, int line) {
+  cerr << message << " " << file << ":" << line << "." << endl;
+  cerr.flush();
+}
+
+void parse_error(const char *message, char *file, int line) {
+  cerr << message << " " << file << ":" << line << "." << endl;
+  cerr.flush();
+  exit(1);
+}
+
+//////////////////////////////////////////////////////////////////////
+
+void list_to_pool(char *main_path, char *list_name, char *pool_name) {
+  ifstream list_stream(list_name);
+
+  if(list_stream.fail()) {
+    cerr << "Can not open " << list_name << " for reading." << endl;
+    exit(1);
+  }
+
+  ofstream pool_stream(pool_name);
+
+  if(pool_stream.fail()) {
+    cerr << "Can not open " << pool_name << " for writing." << endl;
+    exit(1);
+  }
+
+  int line_number = 0;
+  int nb_scenes = 0;
+
+  int nb_cats = -1;
+  LabelledImage *current_image = 0;
+  bool open_current_cat = false;
+  bool head_defined =  false;
+  bool bounding_box_defined =  false;
+  bool body_defined = false;
+  int nb_ears = 0;
+
+  while(!list_stream.eof() && (global.nb_images < 0 || nb_scenes < global.nb_images)) {
+    char line[large_buffer_size], token[buffer_size], full_image_name[buffer_size];
+    list_stream.getline(line, large_buffer_size);
+    line_number++;
+    char *s = line;
+    s = next_word(token, s, buffer_size);
+
+    //////////////////////////////////////////////////////////////////////
+
+    if(strcmp(token, "SCENE") == 0) {
+
+      if(current_image) {
+        parse_error("Non-closed scene ", list_name, line_number);
+      }
+
+      if(s) {
+        s = next_word(token, s, buffer_size);
+        sprintf(full_image_name, "%s/%s", main_path, token);
+      } else {
+        parse_error("Image name is missing ", list_name, line_number);
+      }
+
+      cout << "Processing scene " << full_image_name << "." << endl;
+
+      int nb_cats_in_current_image = -1;
+
+      if(s) {
+        s = next_word(token, s, buffer_size);
+        nb_cats_in_current_image = atoi(token);
+      } else {
+        parse_error("Number of cats is missing ", list_name, line_number);
+      }
+
+      if(nb_cats_in_current_image < 0 || nb_cats_in_current_image > 100) {
+        parse_error("Weird number of cats ", list_name, line_number);
+      }
+
+      RGBImage tmp;
+      tmp.read_jpg(full_image_name);
+
+      current_image = new LabelledImage(tmp.width(),
+                                        tmp.height(),
+                                        nb_cats_in_current_image);
+
+      for(int y = 0; y < tmp.height(); y++) {
+        for(int x = 0; x < tmp.width(); x++) {
+          current_image->set_value(x, y,
+                                   int(scalar_t(tmp.pixel(x, y, 0)) * 0.2989 +
+                                       scalar_t(tmp.pixel(x, y, 1)) * 0.5870 +
+                                       scalar_t(tmp.pixel(x, y, 2)) * 0.1140));
+        }
+      }
+
+      nb_cats = 0;
+    }
+
+    else if(strcmp(token, "END_SCENE") == 0) {
+      if(current_image == 0)
+        parse_error("Non-open scene ", list_name, line_number);
+
+      if(nb_cats < current_image->nb_targets()) {
+        parse_warning("Less cats than advertised (some were ignored?), scene ignored",
+                      list_name, line_number);
+      } else {
+        current_image->write(&pool_stream);
+        nb_scenes++;
+      }
+
+      delete current_image;
+      current_image = 0;
+    }
+
+    //////////////////////////////////////////////////////////////////////
+
+    else if(strcmp(token, "CAT") == 0) {
+      if(open_current_cat)
+        parse_error("Non-closed cat ", list_name, line_number);
+      if(current_image == 0)
+        parse_error("Cat without scene ", list_name, line_number);
+      if(nb_cats >= current_image->nb_targets())
+        parse_error("More cats than advertised", list_name, line_number);
+      open_current_cat = true;
+      head_defined = false;
+      bounding_box_defined = false;
+      body_defined = false;
+      nb_ears = 0;
+    }
+
+    else if(strcmp(token, "END_CAT") == 0) {
+      if(!open_current_cat)
+        parse_error("Undefined cat ", list_name, line_number);
+
+      if(!bounding_box_defined) {
+        parse_error("Undefined bounding box ", list_name, line_number);
+      }
+
+      if(head_defined && body_defined) {
+        if(current_image->get_target_pose(nb_cats)->_head_radius > global.min_head_radius &&
+           current_image->get_target_pose(nb_cats)->_head_radius < global.max_head_radius) {
+          nb_cats++;
+        } else {
+          cerr << "Cat ignored since the head radius ("
+               <<  current_image->get_target_pose(nb_cats)->_head_radius << ") is not in the tolerance ("
+               << global.min_head_radius << ", " << global.max_head_radius
+               << ") "
+               << list_name << ":" << line_number
+               << endl;
+          cerr.flush();
+        }
+      } else {
+        parse_warning("Cat ignored since either the body, head or belly are undefined",
+                      list_name, line_number);
+      }
+
+      open_current_cat = false;
+    }
+
+    //////////////////////////////////////////////////////////////////////
+
+    else if(strcmp(token, "BODYBOX") == 0) {
+      if(!open_current_cat) parse_error("Undefined cat ", list_name, line_number);
+      if(bounding_box_defined) parse_error("Two bounding box", list_name, line_number);
+      int xmin = -1, ymin = -1, xmax = -1, ymax = -1;
+      if(s) { s = next_word(token, s, buffer_size); xmin = atoi(token); }
+      else parse_error("BODYBOX parameter xmin missing ", list_name, line_number);
+      if(s) { s = next_word(token, s, buffer_size); ymin = atoi(token); }
+      else parse_error("BODYBOX parameter ymin missing ", list_name, line_number);
+      if(s) { s = next_word(token, s, buffer_size); xmax = atoi(token); }
+      else parse_error("BODYBOX parameter xmax missing ", list_name, line_number);
+      if(s) { s = next_word(token, s, buffer_size); ymax = atoi(token); }
+      else parse_error("BODYBOX parameter ymax missing ", list_name, line_number);
+      current_image->get_target_pose(nb_cats)->_bounding_box_xmin = xmin;
+      current_image->get_target_pose(nb_cats)->_bounding_box_ymin = ymin;
+      current_image->get_target_pose(nb_cats)->_bounding_box_xmax = xmax;
+      current_image->get_target_pose(nb_cats)->_bounding_box_ymax = ymax;
+      bounding_box_defined = true;
+    }
+
+    //////////////////////////////////////////////////////////////////////
+
+    else if(strcmp(token, "HEADELLIPSE") == 0) {
+      if(!open_current_cat) parse_error("Undefined cat ", list_name, line_number);
+      if(head_defined) parse_error("Two head definitions", list_name, line_number);
+      int xmin = -1, ymin = -1, xmax = -1, ymax = -1;
+      if(s) { s = next_word(token, s, buffer_size); xmin = atoi(token); }
+      else parse_error("HEADELLIPSE parameter xmin missing ", list_name, line_number);
+      if(s) { s = next_word(token, s, buffer_size); ymin = atoi(token); }
+      else parse_error("HEADELLIPSE parameter ymin missing ", list_name, line_number);
+      if(s) { s = next_word(token, s, buffer_size); xmax = atoi(token); }
+      else parse_error("HEADELLIPSE parameter xmax missing ", list_name, line_number);
+      if(s) { s = next_word(token, s, buffer_size); ymax = atoi(token); }
+      else parse_error("HEADELLIPSE parameter ymax missing ", list_name, line_number);
+      current_image->get_target_pose(nb_cats)->_head_xc = (xmin + xmax)/2;
+      current_image->get_target_pose(nb_cats)->_head_yc = (ymin + ymax)/2;
+      current_image->get_target_pose(nb_cats)->_head_radius = int(sqrt(scalar_t(xmax - xmin) * scalar_t(ymax - ymin))/2);
+      head_defined = true;
+    }
+
+    else if(strcmp(token, "BELLYLOCATION") == 0) {
+      if(!open_current_cat) parse_error("Undefined cat ", list_name, line_number);
+      int x1 = -1, y1 = -1;
+
+      if(s) { s = next_word(token, s, buffer_size); x1 = atoi(token); }
+      else parse_error("BELLYLOCATION parameter x1 missing ", list_name, line_number);
+      if(s) { s = next_word(token, s, buffer_size); y1 = atoi(token); }
+      else parse_error("BELLYLOCATION parameter y1 missing ", list_name, line_number);
+
+      if(body_defined) {
+        parse_error("More than one body location. ", list_name, line_number);
+      } else {
+
+        Pose *pose = current_image->get_target_pose(nb_cats);
+
+        pose->_body_xc = x1;
+        pose->_body_yc = y1;
+
+        body_defined = true;
+      }
+    }
+  }
+}
+
+//////////////////////////////////////////////////////////////////////
+
+int main(int argc, char **argv) {
+  char *new_argv[argc];
+  int new_argc = 0;
+
+  {
+    ParamParser parser;
+    global.init_parser(&parser);
+    parser.parse_options(argc, argv, false, &new_argc, new_argv);
+    global.read_parser(&parser);
+    cout << "-- PARAMETERS --------------------------------------------------------" << endl;
+    parser.print_all(&cout);
+  }
+
+  if(new_argc != 4) {
+    cerr << new_argv[0] << " <list file> <image path> <pool name>" << endl;
+    exit(1);
+  }
+
+  cout << "From list " << new_argv[1]
+       << " and image dir " << new_argv[2]
+       << ", generating pool " << new_argv[3]
+       << "." << endl;
+
+  cout << "-- GENERATING IMAGES -------------------------------------------------" << endl;
+
+  list_to_pool(new_argv[2], new_argv[1], new_argv[3]);
+
+  cout << "-- FINISHED ----------------------------------------------------------" << endl;
+
+}