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