Hugin trunk 0.1
Loading...
Searching...
No Matches
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
31using namespace vigra;
32using namespace std;
33
34void 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
42int 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));
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
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());
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
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
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}
int main(int argc, char **argv)
static void usage()
Definition Main.cpp:32
static deghosting::EMoR response(0.0f)
Implementation of fast vector type with support of linear algebra operations Copyright (C) 2009 Lukáš...
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41