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