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