Removed the definition of basename, which confuses an existing system one.
[folded-ctf.git] / list_to_pool.cc
1 /*
2  *  folded-ctf is an implementation of the folded hierarchy of
3  *  classifiers for object detection, developed by Francois Fleuret
4  *  and Donald Geman.
5  *
6  *  Copyright (c) 2008 Idiap Research Institute, http://www.idiap.ch/
7  *  Written by Francois Fleuret <francois.fleuret@idiap.ch>
8  *
9  *  This file is part of folded-ctf.
10  *
11  *  folded-ctf is free software: you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License version 3 as
13  *  published by the Free Software Foundation.
14  *
15  *  folded-ctf is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with folded-ctf.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include <fstream>
26
27 using namespace std;
28
29 #include "misc.h"
30 #include "global.h"
31 #include "param_parser.h"
32 #include "labelled_image.h"
33
34 void parse_warning(const char *message, char *file, int line) {
35   cerr << message << " " << file << ":" << line << "." << endl;
36   cerr.flush();
37 }
38
39 void parse_error(const char *message, char *file, int line) {
40   cerr << message << " " << file << ":" << line << "." << endl;
41   cerr.flush();
42   exit(1);
43 }
44
45 //////////////////////////////////////////////////////////////////////
46
47 void list_to_pool(char *main_path, char *list_name, char *pool_name) {
48   ifstream list_stream(list_name);
49
50   if(list_stream.fail()) {
51     cerr << "Can not open " << list_name << " for reading." << endl;
52     exit(1);
53   }
54
55   ofstream pool_stream(pool_name);
56
57   if(pool_stream.fail()) {
58     cerr << "Can not open " << pool_name << " for writing." << endl;
59     exit(1);
60   }
61
62   int line_number = 0;
63   int nb_scenes = 0;
64
65   int nb_cats = -1;
66   LabelledImage *current_image = 0;
67   bool open_current_cat = false;
68   bool head_defined =  false;
69   bool bounding_box_defined =  false;
70   bool belly_defined = false;
71   int nb_ears = 0;
72
73   while(!list_stream.eof() && (global.nb_images < 0 || nb_scenes < global.nb_images)) {
74     char line[large_buffer_size], token[buffer_size], full_image_name[buffer_size];
75     list_stream.getline(line, large_buffer_size);
76     line_number++;
77     char *s = line;
78     s = next_word(token, s, buffer_size);
79
80     //////////////////////////////////////////////////////////////////////
81
82     if(strcmp(token, "SCENE") == 0) {
83
84       if(current_image) {
85         parse_error("Non-closed scene ", list_name, line_number);
86       }
87
88       if(s) {
89         s = next_word(token, s, buffer_size);
90         sprintf(full_image_name, "%s/%s", main_path, token);
91       } else {
92         parse_error("Image name is missing ", list_name, line_number);
93       }
94
95       cout << "Processing scene " << full_image_name << "." << endl;
96
97       int nb_cats_in_current_image = -1;
98
99       if(s) {
100         s = next_word(token, s, buffer_size);
101         nb_cats_in_current_image = atoi(token);
102       } else {
103         parse_error("Number of cats is missing ", list_name, line_number);
104       }
105
106       if(nb_cats_in_current_image < 0 || nb_cats_in_current_image > 100) {
107         parse_error("Weird number of cats ", list_name, line_number);
108       }
109
110       RGBImage tmp;
111       tmp.read_jpg(full_image_name);
112
113       current_image = new LabelledImage(tmp.width(),
114                                         tmp.height(),
115                                         nb_cats_in_current_image);
116
117       for(int y = 0; y < tmp.height(); y++) {
118         for(int x = 0; x < tmp.width(); x++) {
119           current_image->set_value(x, y,
120                                    int(scalar_t(tmp.pixel(x, y, 0)) * 0.2989 +
121                                        scalar_t(tmp.pixel(x, y, 1)) * 0.5870 +
122                                        scalar_t(tmp.pixel(x, y, 2)) * 0.1140));
123         }
124       }
125
126       nb_cats = 0;
127     }
128
129     else if(strcmp(token, "END_SCENE") == 0) {
130       if(current_image == 0)
131         parse_error("Non-open scene ", list_name, line_number);
132
133       if(nb_cats < current_image->nb_targets()) {
134         parse_warning("Less cats than advertised (some were ignored?), scene ignored",
135                       list_name, line_number);
136       } else {
137         current_image->write(&pool_stream);
138         nb_scenes++;
139       }
140
141       delete current_image;
142       current_image = 0;
143     }
144
145     //////////////////////////////////////////////////////////////////////
146
147     else if(strcmp(token, "CAT") == 0) {
148       if(open_current_cat)
149         parse_error("Non-closed cat ", list_name, line_number);
150       if(current_image == 0)
151         parse_error("Cat without scene ", list_name, line_number);
152       if(nb_cats >= current_image->nb_targets())
153         parse_error("More cats than advertised", list_name, line_number);
154       open_current_cat = true;
155       head_defined = false;
156       bounding_box_defined = false;
157       belly_defined = false;
158       nb_ears = 0;
159     }
160
161     else if(strcmp(token, "END_CAT") == 0) {
162       if(!open_current_cat)
163         parse_error("Undefined cat ", list_name, line_number);
164
165       if(!bounding_box_defined) {
166         parse_error("Undefined bounding box ", list_name, line_number);
167       }
168
169       if(head_defined && belly_defined) {
170         if(current_image->get_target_pose(nb_cats)->_head_radius > global.min_head_radius &&
171            current_image->get_target_pose(nb_cats)->_head_radius < global.max_head_radius) {
172           nb_cats++;
173         } else {
174           cerr << "Cat ignored since the head radius ("
175                <<  current_image->get_target_pose(nb_cats)->_head_radius << ") is not in the tolerance ("
176                << global.min_head_radius << ", " << global.max_head_radius
177                << ") "
178                << list_name << ":" << line_number
179                << endl;
180           cerr.flush();
181         }
182       } else {
183         parse_warning("Cat ignored since either the head and/or the belly are undefined",
184                       list_name, line_number);
185       }
186
187       open_current_cat = false;
188     }
189
190     //////////////////////////////////////////////////////////////////////
191
192     else if(strcmp(token, "BOUNDINGBOX") == 0) {
193       if(!open_current_cat) parse_error("Undefined cat ", list_name, line_number);
194       if(bounding_box_defined) parse_error("Two bounding box", list_name, line_number);
195       int xmin = -1, ymin = -1, xmax = -1, ymax = -1;
196       if(s) { s = next_word(token, s, buffer_size); xmin = atoi(token); }
197       else parse_error("BOUNDINGBOX parameter xmin missing ", list_name, line_number);
198       if(s) { s = next_word(token, s, buffer_size); ymin = atoi(token); }
199       else parse_error("BOUNDINGBOX parameter ymin missing ", list_name, line_number);
200       if(s) { s = next_word(token, s, buffer_size); xmax = atoi(token); }
201       else parse_error("BOUNDINGBOX parameter xmax missing ", list_name, line_number);
202       if(s) { s = next_word(token, s, buffer_size); ymax = atoi(token); }
203       else parse_error("BOUNDINGBOX parameter ymax missing ", list_name, line_number);
204       current_image->get_target_pose(nb_cats)->_bounding_box_xmin = xmin;
205       current_image->get_target_pose(nb_cats)->_bounding_box_ymin = ymin;
206       current_image->get_target_pose(nb_cats)->_bounding_box_xmax = xmax;
207       current_image->get_target_pose(nb_cats)->_bounding_box_ymax = ymax;
208       bounding_box_defined = true;
209     }
210
211     //////////////////////////////////////////////////////////////////////
212
213     else if(strcmp(token, "HEADELLIPSE") == 0) {
214       if(!open_current_cat) parse_error("Undefined cat ", list_name, line_number);
215       if(head_defined) parse_error("Two head definitions", list_name, line_number);
216       int xmin = -1, ymin = -1, xmax = -1, ymax = -1;
217       if(s) { s = next_word(token, s, buffer_size); xmin = atoi(token); }
218       else parse_error("HEADELLIPSE parameter xmin missing ", list_name, line_number);
219       if(s) { s = next_word(token, s, buffer_size); ymin = atoi(token); }
220       else parse_error("HEADELLIPSE parameter ymin missing ", list_name, line_number);
221       if(s) { s = next_word(token, s, buffer_size); xmax = atoi(token); }
222       else parse_error("HEADELLIPSE parameter xmax missing ", list_name, line_number);
223       if(s) { s = next_word(token, s, buffer_size); ymax = atoi(token); }
224       else parse_error("HEADELLIPSE parameter ymax missing ", list_name, line_number);
225       current_image->get_target_pose(nb_cats)->_head_xc = (xmin + xmax)/2;
226       current_image->get_target_pose(nb_cats)->_head_yc = (ymin + ymax)/2;
227       current_image->get_target_pose(nb_cats)->_head_radius = int(sqrt(scalar_t(xmax - xmin) * scalar_t(ymax - ymin))/2);
228       head_defined = true;
229     }
230
231     else if(strcmp(token, "BELLYLOCATION") == 0) {
232       if(!open_current_cat) parse_error("Undefined cat ", list_name, line_number);
233       int x1 = -1, y1 = -1;
234
235       if(s) { s = next_word(token, s, buffer_size); x1 = atoi(token); }
236       else parse_error("BELLYLOCATION parameter x1 missing ", list_name, line_number);
237       if(s) { s = next_word(token, s, buffer_size); y1 = atoi(token); }
238       else parse_error("BELLYLOCATION parameter y1 missing ", list_name, line_number);
239
240       if(belly_defined) {
241         parse_error("More than one belly location. ", list_name, line_number);
242       } else {
243
244         Pose *pose = current_image->get_target_pose(nb_cats);
245
246         pose->_belly_xc = x1;
247         pose->_belly_yc = y1;
248
249         belly_defined = true;
250       }
251     }
252   }
253 }
254
255 //////////////////////////////////////////////////////////////////////
256
257 int main(int argc, char **argv) {
258   char *new_argv[argc];
259   int new_argc = 0;
260
261   {
262     ParamParser parser;
263     global.init_parser(&parser);
264     parser.parse_options(argc, argv, false, &new_argc, new_argv);
265     global.read_parser(&parser);
266     cout << "-- PARAMETERS --------------------------------------------------------" << endl;
267     parser.print_all(&cout);
268   }
269
270   if(new_argc != 4) {
271     cerr << new_argv[0] << " <list file> <image path> <pool name>" << endl;
272     exit(1);
273   }
274
275   cout << "From list " << new_argv[1]
276        << " and image dir " << new_argv[2]
277        << ", generating pool " << new_argv[3]
278        << "." << endl;
279
280   cout << "-- GENERATING IMAGES -------------------------------------------------" << endl;
281
282   list_to_pool(new_argv[2], new_argv[1], new_argv[3]);
283
284   cout << "-- FINISHED ----------------------------------------------------------" << endl;
285
286 }