Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CelesteTrain.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2008 by Tim Nugent *
3  * timnugent@gmail.com *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17  ***************************************************************************/
18 
19 #include <iostream>
20 #include "vigra/stdimage.hxx"
21 #include "vigra/resizeimage.hxx"
22 #include "vigra/impex.hxx"
23 #include "vigra/colorconversions.hxx"
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <stdlib.h>
27 #include "Gabor.h"
28 #include "Utilities.h"
29 #include "CelesteGlobals.h"
30 
31 using namespace vigra;
32 using namespace std;
33 
34 void usage (char* filename){
35 
36  cout << "Usage: " << filename << " <image file> <mask file>" << endl;
37  cout << "or for a positive example: " << filename << " -p <image file>" << endl;
38  cout << "or for a negative example: " << filename << " -n <image file>" << endl;
39  cout << "(supported formats: " << vigra::impexListFormats() << ")" << endl;
40 }
41 
42 int main(int argc, char ** argv){
43 
44  unsigned int a = 1;
45  unsigned int pos = 0;
46  unsigned int neg = 0;
47  string image_file,mask_file;
48  vigra::FRGBImage mask_in;
49  vigra::FRGBImage::iterator mask_iter;
50 
51  // Deal with arguments
52  if(argc < 3 || argc >= 4){
53 
54  usage(argv[0]); exit(1);
55  }
56 
57  while( a < argc ){
58 
59  if( argv[a][0] == '-'){
60 
61  a++;
62  switch(argv[a-1][1]){
63 
64  // Put some more argument options in here later
65  case 'h' : {usage(argv[0]); exit(1);}
66  case 'p' : {pos = 1;
67  cerr << "Ignoring mask. Image is a positive example." << endl;
68  image_file = argv[argc-1];
69  break;
70  }
71  case 'n' : {neg = 1;
72  cerr << "Ignoring mask. Image is a negative example." << endl;
73  image_file = argv[argc-1];
74  break;
75  }
76  default : {usage(argv[0]); exit(1);}
77  }
78 
79  }
80 
81  a++;
82  }
83 
84  if (pos == 0 && neg == 0){
85 
86  image_file = argv[argc-2];
87  mask_file = argv[argc-1];
88 
89  //cout << "Image is " << argv[argc-2] << endl;
90  //cout << "Mask is " << argv[argc-1] << endl;
91 
92  }
93 
94  try{
95 
96  cerr << "Opening image file: " << image_file << endl;
97 
98  // Read image given as first argument
99  // File type is determined automatically
100  vigra::ImageImportInfo info(image_file.c_str());
101 
102  // Create RGB images of appropriate size
103  vigra::FRGBImage in(info.width(), info.height());
104 
105  // Import the image
106  importImage(info, destImage(in));
107 
108  // Deal with mask unless -p || -n flags are on
109  if (pos == 0 && neg == 0){
110 
111  cerr << "Opening mask file: " << mask_file << endl;
112 
113  // Read mask given as second argument
114  vigra::ImageImportInfo mask_info(mask_file.c_str());
115 
116  // Check dimensions are the same
117  if (info.width() != mask_info.width() || info.height() != mask_info.height()){
118 
119  cerr << "Error - image and mask files are different dimension:" << endl;
120  cerr << "Image:\t" << info.width() << " x " << info.height() << endl;
121  cerr << "Mask:\t" << mask_info.width() << " x " << mask_info.height() << endl << endl;
122  return 1;
123 
124  }
125 
126  // Create RGB images of appropriate size
127  vigra::FRGBImage tmp_mask_in(info.width(), info.height());
128  // Import the mask
129  importImage(mask_info, destImage(tmp_mask_in));
130  mask_in = tmp_mask_in;
131 
132  }
133 
134 
135  // Max dimension
136  const int resize_dimension = 800;
137 
138  // Re-size to 800 max dimension
139  if (info.width() >= resize_dimension || info.height() >= resize_dimension){
140 
141  // Method (0 - pixel repetition, 1 - linear, 2 - spline
142  // Pixel repetition seems to be the fastest
143  int method = 0;
144  double sizefactor;
145 
146  if (info.width() >= info.height()){
147  sizefactor = (double)resize_dimension/info.width();
148  }else{
149  sizefactor = (double)resize_dimension/info.height();
150  }
151 
152  // calculate new image size
153  int nw = (int)(sizefactor*info.width());
154  int nh = (int)(sizefactor*info.height());
155 
156  cerr << "Image dimensions:\t" << info.width() << " x " << info.height() << endl;
157  cerr << "Scaling by:\t\t" << sizefactor << endl;
158  cerr << "New dimensions:\t\t" << nw << " x " << nh << endl;
159 
160  // create a RGB image of appropriate size
161  vigra::FRGBImage out(nw, nh);
162 
163  switch(method){
164 
165  case 0:
166  // resize the image, using a bi-cubic spline algorithms
167  resizeImageNoInterpolation(srcImageRange(in),destImageRange(out));
168  break;
169 
170  case 1:
171  // resize the image, using a bi-cubic spline algorithms
172  resizeImageLinearInterpolation(srcImageRange(in),destImageRange(out));
173  break;
174 
175  default:
176  // resize the image, using a bi-cubic spline algorithms
177  resizeImageSplineInterpolation(srcImageRange(in),destImageRange(out));
178  }
179 
180  in = out;
181 
182  // Deal with mask unless -p || -n flags are on
183  if (pos == 0 && neg == 0){
184 
185  vigra::FRGBImage mask_out(nw, nh);
186 
187  switch(method){
188 
189  case 0:
190  // resize the image, using a bi-cubic spline algorithms
191  resizeImageNoInterpolation(srcImageRange(mask_in),destImageRange(mask_out));
192  break;
193 
194  case 1:
195  // resize the image, using a bi-cubic spline algorithms
196  resizeImageLinearInterpolation(srcImageRange(mask_in),destImageRange(mask_out));
197  break;
198 
199  default:
200  // resize the image, using a bi-cubic spline algorithms
201  resizeImageSplineInterpolation(srcImageRange(mask_in),destImageRange(mask_out));
202 
203  }
204 
205  mask_in = mask_out;
206  }
207 
208  }else{
209  cerr << "Image dimensions:\t" << info.width() << " x " << info.height() << endl;
210  }
211 
212  cerr << "Total pixels:\t\t" << in.width()*in.height() << endl;
213 
214  // Convert to LUV colour space
215  cerr << "Converting to LUV colourspace..." << endl;
216 
217  FRGBImage luv(in.width(),in.height());
218  transformImage(srcImageRange(in), destImage(luv), RGBPrime2LuvFunctor<double>() );
219 
220  // Create grid of fiducial points
221  cerr << "Generating fiducial points..." << endl;
222 
223  for (int i = gRadius; i < in.height() - gRadius; i += spacing ){
224  for (int j = gRadius; j < in.width() - gRadius; j += spacing ){
225  gNumLocs++;
226  }
227  }
228 
229  // Create the storage matrix
230  gLocations = CreateMatrix( (int)0, gNumLocs, 2);
231  gNumLocs = 0;
232  for (int i = gRadius; i < in.height() - gRadius; i += spacing ){
233  for (int j = gRadius; j < in.width() - gRadius; j += spacing ){
234 
235  gLocations[gNumLocs][0] = j;
236  gLocations[gNumLocs][1] = i;
237 
238  //cerr << "fPoint " << gNumLocs << ":\t" << i << " " << j << endl;
239 
240  gNumLocs++;
241  }
242  }
243  cerr << "Total fiducial points: " << gNumLocs << endl;
244 
245  // Prepare Gabor API array
246  float *frameBuf = new float[in.width()*in.height()];
247  float *u_values = new float[in.width()*in.height()];
248  float *v_values = new float[in.width()*in.height()];
249 
250 
251  float** pixels = CreateMatrix( (float)0, in.height(), in.width() );
252 
253  // Do something with each pixel...
254  int counter = 0;
255  vigra::FRGBImage::iterator img_iter(luv.begin()),end(luv.end());
256  for(; img_iter != end; ++img_iter) {
257 
258  // [0] is L, [1] is U, [2] is V
259  // We only want L for Gabor filtering
260  frameBuf[counter] = (*img_iter)[0];
261 
262  u_values[counter] = (*img_iter)[1];
263  v_values[counter] = (*img_iter)[2];
264 
265  //cout << "Pixel " << counter << " - L: " << (*img_iter)[0] << endl;
266  //cout << "Pixel " << counter << " - U: " << (*img_iter)[1] << endl;
267  //cout << "Pixel " << counter << " - V: " << (*img_iter)[2] << endl;
268  counter++;
269  }
270 
271 
272  int k = 0;
273  for (int i = 0; i < in.height(); i++ ){
274  for (int j = 0; j < in.width(); j++ ){
275  pixels[i][j] = frameBuf[k];
276  //cout << i << " " << j << " = " << k << " - " << frameBuf[k] << endl;
277  k++;
278  }
279  }
280 
281  char basename[] = "gabor_filters/celeste";
282 
283  float *response = NULL;
284  int len = 0;
285 
286  response = ProcessChannel( pixels, in.height(), in.width(), response, &len, basename );
287 
288  // Deal with mask unless -p || -n flags are on
289  if (pos == 0 && neg == 0){
290 
291  // Iterator for mask
292  vigra::FRGBImage::iterator tmp_mask_iter(mask_in.begin()),mask_end(mask_in.end());
293  mask_iter = tmp_mask_iter;
294  mask_end = NULL;
295  }
296 
297  cerr << "Generating feature vector by Gabor filtering..." << endl;
298 
299  // Do something nice with response
300  int vector_length = (int)len/gNumLocs;
301  for ( int j = 0; j < gNumLocs; j++ ){
302 
303  //cerr << gLocations[j][0] << "," << gLocations[j][1] << endl;
304 
305  int pixel_number = gLocations[j][0] + (in.width() * (gLocations[j][1] - 1)) - 1;
306 
307  // Apply label
308  if (pos){
309  cout << "+1 ";
310  }else if (neg){
311  cout << "-1 ";
312  }else{
313  // In the mask, clouds are black, non-clouds are white
314  if (mask_iter[pixel_number][0] != 0 || mask_iter[pixel_number][1] != 0 || mask_iter[pixel_number][2] != 0){
315  // So this must be non-cloud = -ve example
316  cout << "-1 ";
317  }else{
318  // So this must be cloud = +ve example
319  cout << "+1 ";
320  }
321  }
322 
323  int feature = 1;
324  for ( int v = (j * vector_length); v < ((j + 1) * vector_length); v++){
325  cout << feature << ":" << response[v] << " ";
326  feature++;
327  }
328 
329  // Work out average colour - U + V channels
330 
331  float u_sum = 0, v_sum = 0;
332  int pixels_in_region = (gRadius * 2)*(gRadius * 2);
333 
334  // height
335  //cout << endl << "Pixel " << pixel_number << " x:" << gLocations[j][0] << " y:" <<
336  //gLocations[j][1] << " width: " << in.width() << endl;
337 
338  for (int t = 1 - gRadius; t <= gRadius; t++){
339 
340  int this_y_pixel = pixel_number + (t * in.width());
341  //cout << "t = " << t << " pixel= " << pixel_number << " + " << (t * in.width()) << endl;
342  // width
343  for (int r = 1 - gRadius; r <= gRadius; r++){
344 
345  int this_x_pixel = this_y_pixel + r;
346 
347  //if (this_x_pixel == pixel_number){
348  // cout << "*" << this_x_pixel << "* ";
349  //}else{
350  // cout << this_x_pixel << " ";
351  //}
352 
353  u_sum += u_values[this_x_pixel];
354  v_sum += v_values[this_x_pixel];
355 
356  //cout << "u = " << u_values[this_x_pixel] << "(" << u_sum << ")" << endl;
357  //cout << "v = " << v_values[this_x_pixel] << "(" << v_sum << ")" << endl;
358 
359  }
360  //cout << endl;
361  }
362  //cout << endl;
363 
364  float u_ave = (float)u_sum/pixels_in_region;
365  float v_ave = (float)v_sum/pixels_in_region;
366 
367  // Now work out standard deviation for U and V channels
368  u_sum = 0, v_sum = 0;
369 
370  for (int t = 1 - gRadius; t <= gRadius; t++){
371  int this_y_pixel = pixel_number + (t * in.width());
372 
373  for (int r = 1 - gRadius; r <= gRadius; r++){
374 
375  int this_x_pixel = this_y_pixel + r;
376 
377  u_sum += pow(u_values[this_x_pixel]-u_ave,2);
378  v_sum += pow(v_values[this_x_pixel]-v_ave,2);
379 
380  }
381  }
382 
383 
384  float std_u = sqrt(u_sum/(pixels_in_region-1));
385  float std_v = sqrt(v_sum/(pixels_in_region-1));
386 
387  //cerr << "U sum = " << u_sum << " U ave = " << u_ave << " U std = " << std_u << endl;
388  //cerr << "V sum = " << v_sum << " V ave = " << v_ave << " V std = " << std_v << endl << endl;
389 
390  cout << feature << ":" << u_ave << " ";
391  feature++;
392  cout << feature << ":" << std_u << " ";
393  feature++;
394  cout << feature << ":" << v_ave << " ";
395  feature++;
396  cout << feature << ":" << std_v << " ";
397  feature++;
398 
399  // Add the U/V values for this actual pixel
400 
401  cout << feature << ":" << u_values[pixel_number] << " ";
402  feature++;
403  cout << feature << ":" << v_values[pixel_number] << " ";
404  feature++;
405 
406 
407  //cout << "# FP_" << j << "_Pixel_" << pixel_number << "_Pos_" << gLocations[j][0] << "-" << gLocations[j][1] <<
408  //"_Mask_RGB_" << mask_iter[pixel_number][0] << "," << mask_iter[pixel_number][1] << "," <<
409  //mask_iter[pixel_number][2] << endl;
410  cout << endl;
411  }
412 
413  delete[] response;
414  delete[] frameBuf;
415  delete[] u_values;
416  delete[] v_values;
417 
418  // Export images
419  //exportImage(srcImageRange(in), ImageExportInfo("output_images/image_reduced.jpg"));
420  //exportImage(srcImageRange(luv), ImageExportInfo("output_images/luv_reduced.jpg"));
421  //
422  //if (pos == 0 && neg == 0){
423  // exportImage(srcImageRange(mask_in), ImageExportInfo("output_images/mask_reduced.jpg"));
424  //}
425 
426  //cout << "Done." << endl;
427 
428  }catch (vigra::StdException & e){
429 
430  // catch any errors that might have occurred and print their reason
431  std::cout << e.what() << std::endl;
432  return 1;
433 
434  }
435 
436  return 0;
437 
438 }
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
float * ProcessChannel(float **image, int w, int h, int gNumLocs, int **&gLocations, int gRadius, float *response, int *len)
Definition: Gabor.cpp:33
float pow(float a, double b)
Definition: utils.h:181
static deghosting::EMoR response(0.0f)
int ** CreateMatrix(int val, int row, int col)
Definition: Utilities.cpp:101
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
Definition: ROIImage.h:324
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
Definition: ROIImage.h:287
static void usage()
Definition: Main.cpp:32
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
Definition: ROIImage.h:312
static void info(const char *fmt,...)
Definition: svm.cpp:95
int main(int argc, char *argv[])
Definition: Main.cpp:167