~ubuntu-branches/ubuntu/trusty/hugin/trusty-proposed

« back to all changes in this revision

Viewing changes to src/celeste/Celeste.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2011-01-06 14:28:24 UTC
  • mfrom: (1.1.9 upstream) (0.1.21 experimental)
  • Revision ID: james.westby@ubuntu.com-20110106142824-zn9lxylg5z44dynn
* Drop Cyril Brulebois from Uploaders. Thank you very much for your work.
* Bump package version. (rc3 was re-released as 2010.4.0).

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 ***************************************************************************/
20
20
 
21
21
#include <iostream>
22
 
#include "vigra/stdimage.hxx"
23
 
#include "vigra/resizeimage.hxx"
24
 
#include "vigra/impex.hxx"
 
22
#include <vigra/stdimage.hxx>
 
23
#include <vigra/resizeimage.hxx>
 
24
#include <vigra/inspectimage.hxx>
 
25
#include <vigra/copyimage.hxx>
 
26
#include <vigra/transformimage.hxx>
 
27
#include <vigra/initimage.hxx>
25
28
#include "vigra/colorconversions.hxx"
26
29
#include <sys/types.h>
27
30
#include <sys/stat.h>
38
41
using namespace vigra; 
39
42
using namespace std; 
40
43
 
 
44
namespace celeste
 
45
{
 
46
 
41
47
typedef vigra::BRGBImage::PixelType RGB;
42
48
 
43
 
void get_gabor_response(string& imagefile, unsigned int& mask, string& model_file, double& threshold,string&
44
 
mask_format,vector<double>& svm_responses){
45
 
 
46
 
        // Open SVM model file
47
 
        struct svm_model* model;
48
 
        
49
 
        if((model = svm_load_model(model_file.c_str())) == 0){
50
 
                cout << "Couldn't load model file '" << model_file << "'" << endl << endl;
51
 
                for (int j = 0; j < gNumLocs; j++){
52
 
                        svm_responses.push_back(0);
53
 
                }               
54
 
                return;
55
 
        }else{
56
 
                cout << "Loaded model file:\t" << model_file << endl;
57
 
        }       
58
 
        
59
 
        // Integers and containers for libsvm
60
 
        int nr_class=svm_get_nr_class(model);
61
 
        int max_nr_attr = 56;
62
 
        struct svm_node *gabor_responses = (struct svm_node *) malloc(max_nr_attr*sizeof(struct svm_node));
63
 
        double *prob_estimates = (double *) malloc(nr_class*sizeof(double));
64
 
        
65
 
        // Open image using Vigra
66
 
        try{
67
 
 
68
 
                cout << "Opening image file:\t" << imagefile << endl;
69
 
 
70
 
                // Read image given as first argument
71
 
                // File type is determined automatically
72
 
                vigra::ImageImportInfo info(imagefile.c_str());
73
 
 
74
 
                // Create RGB images of appropriate size        
75
 
                //vigra::FRGBImage in(info.width(), info.height());
76
 
                vigra::UInt16RGBImage in(info.width(), info.height());
77
 
 
78
 
                // Import the image
79
 
                importImage(info, destImage(in));
80
 
 
81
 
                // Max dimension
82
 
                double sizefactor = 1;
83
 
                int nw = info.width(), nh = info.height();
84
 
 
85
 
                // In case we want to save filters
86
 
                // Create this directory and change option in Globals.cpp
87
 
                char basename[] = "gabor_filters/celeste"; 
88
 
                                
89
 
                if (info.width() >= info.height()){
90
 
                        if (resize_dimension >= info.width() ){
91
 
                                resize_dimension = info.width();
92
 
                        }
93
 
                }else{
94
 
                        if (resize_dimension >= info.height()){
95
 
                                resize_dimension = info.height();
96
 
                        }               
97
 
                }
98
 
                //cout << "Re-size dimenstion:\t" << resize_dimension << endl;
99
 
                
100
 
                cout << "Image dimensions:\t" << info.width() << " x " << info.height() << endl;
101
 
                
102
 
                // Re-size to max dimension
103
 
                if (info.width() > resize_dimension || info.height() > resize_dimension){
104
 
                                
105
 
                        if (info.width() >= info.height()){
106
 
 
107
 
 
108
 
                                sizefactor = (double)resize_dimension/info.width();
109
 
 
110
 
                                // calculate new image size
111
 
                                nw = resize_dimension;
112
 
                                nh = static_cast<int>(0.5 + (sizefactor*info.height()));
113
 
                                                        
114
 
                        }else{
115
 
                                sizefactor = (double)resize_dimension/info.height();
116
 
 
117
 
 
118
 
                                // calculate new image size
119
 
                                nw = static_cast<int>(0.5 + (sizefactor*info.width()));
120
 
                                nh = resize_dimension;
121
 
                                
122
 
                        }
123
 
                                
124
 
                        cout << "Scaling by:\t\t" << sizefactor << endl;
125
 
                        cout << "New dimensions:\t\t" << nw << " x " << nh << endl;
126
 
        
127
 
                        // create a RGB image of appropriate size               
128
 
                        //vigra::FRGBImage out(nw, nh);
129
 
                        vigra::UInt16RGBImage out(nw, nh);
130
 
        
131
 
                        // resize the image, using a bi-cubic spline algorithm
132
 
                        resizeImageNoInterpolation(srcImageRange(in),destImageRange(out));
133
 
 
134
 
                        in = out;
135
 
 
136
 
                }
137
 
                //exportImage(srcImageRange(in), ImageExportInfo("test.tif").setPixelType("UINT16"));
138
 
        
139
 
                // Convert to LUV colour space
140
 
                UInt16RGBImage luv(in.width(),in.height());
141
 
                transformImage(srcImageRange(in), destImage(luv), RGB2LuvFunctor<double>() );
142
 
                //transformImage(srcImageRange(in), destImage(luv), RGBPrime2LuvFunctor<double>() );
143
 
 
144
 
                //exportImage(srcImageRange(luv), ImageExportInfo("test_luv.tif").setPixelType("UINT16"));
145
 
 
146
 
                // Prepare Gabor API array
147
 
                float *frameBuf = new float[in.width()*in.height()];
148
 
                float *u_values = new float[in.width()*in.height()];
149
 
                float *v_values = new float[in.width()*in.height()];
150
 
                float** pixels = CreateMatrix( (float)0, in.height(), in.width() );
151
 
 
152
 
                // Do something with each pixel...
153
 
                unsigned int counter = 0;
154
 
                vigra::UInt16RGBImage::iterator img_iter(luv.begin()),end(luv.end());
155
 
                //vigra::FRGBImage::iterator img_iter(luv.begin()),end(luv.end());
156
 
                
157
 
                for(; img_iter != end; ++img_iter) {
158
 
 
159
 
                        // [0] is L, [1] is U, [2] is V
160
 
                        // We only want L for Gabor filtering
161
 
                        frameBuf[counter] = (*img_iter)[0];
162
 
                        
163
 
                        u_values[counter] = (*img_iter)[1];
164
 
                        v_values[counter] = (*img_iter)[2];
165
 
                
166
 
                        //cout << "Pixel " << counter << " - L: " << (*img_iter)[0] << endl;
167
 
                        //cout << "Pixel " << counter << " - U: " << (*img_iter)[1] << endl;
168
 
                        //cout << "Pixel " << counter << " - V: " << (*img_iter)[2] << endl;
169
 
                        counter++;
170
 
                }
171
 
 
172
 
                // Prepare framebuf for Gabor API
173
 
                unsigned int k = 0;
174
 
                for (int i = 0; i < in.height(); i++ ){
175
 
                        for (int j = 0; j < in.width(); j++ ){
176
 
                                pixels[i][j] = frameBuf[k];
177
 
                                //cout << i << " " << j << " = " << k << " - " << frameBuf[k] << endl;
178
 
                                k++;
179
 
                        }
180
 
                }
181
 
 
182
 
                if (gNumLocs){
183
 
 
184
 
                        float *response = NULL;
185
 
                        int len = 0;
186
 
        
187
 
                        // Scale control points by sizefactor
188
 
                        for (int j = 0; j < gNumLocs; j++){
189
 
                
190
 
                                //cout << sizefactor << ": " << gLocations[j][0] << "," << gLocations[j][1] << " ---> ";
191
 
                                gLocations[j][0] = int(gLocations[j][0] * sizefactor);
192
 
                                gLocations[j][1] = int(gLocations[j][1] * sizefactor);
193
 
                                //cout << gLocations[j][0] << "," << gLocations[j][1] << endl;
194
 
 
195
 
                                // Move CPs to border if the filter radius is out of bounds
196
 
                                if (gLocations[j][0] <= gRadius){
197
 
                                        //cout << "Moving CP to border" << endl;
198
 
                                        gLocations[j][0] = gRadius + 1;
199
 
                                }       
200
 
                                if (gLocations[j][1] <= gRadius){
201
 
                                        //cout << "Moving CP to border" << endl;
202
 
                                        gLocations[j][1] = gRadius + 1;
203
 
                                }
204
 
                                if (gLocations[j][0] >= nw - gRadius){
205
 
                                        //cout << "Moving CP to border" << endl;
206
 
                                        gLocations[j][0] = nw - gRadius - 1;
207
 
                                }
208
 
                                if (gLocations[j][1] >= nh - gRadius){
209
 
                                        //cout << "Moving CP to border" << endl;
210
 
                                        gLocations[j][1] = nh - gRadius - 1;
211
 
                                }
212
 
                        }
213
 
 
214
 
                        // Do Gabor filtering                   
215
 
                        cout << "Generating feature vector by Gabor filtering..." << endl;
216
 
                        response = ProcessChannel( pixels, in.height(), in.width(), response, &len, basename );
217
 
                        
218
 
                        // Turn the response into SVM vector, and add colour features                                   
219
 
                        int vector_length = (int)len/gNumLocs;
220
 
                
221
 
                        cout << "Classifying control points using SVM..." << endl;
222
 
                        for (int j = 0; j < gNumLocs; j++){
223
 
 
224
 
                                int pixel_number = gLocations[j][0] + (in.width() * (gLocations[j][1] - 1)) - 1;
225
 
                                unsigned int feature = 1;
226
 
                                double score = 0;
227
 
                                                        
228
 
                                //cout << "0 ";                         
229
 
                                for ( int v = (j * vector_length); v < ((j + 1) * vector_length); v++){
230
 
                                        gabor_responses[feature-1].index = feature;
231
 
                                        gabor_responses[feature-1].value = response[v];                                 
232
 
                                        //cout << feature << ":" << response[v] << " ";
233
 
                                        feature++;
234
 
                                }
235
 
 
236
 
                                // Work out average colour - U + V channels                     
237
 
                                float u_sum = 0, v_sum = 0;
238
 
                                unsigned int pixels_in_region = (gRadius * 2)*(gRadius * 2);
239
 
                        
240
 
                                for (int t = 1 - gRadius; t <= gRadius; t++){                   
241
 
                        
242
 
                                        unsigned int this_y_pixel = pixel_number + (t * in.width());
243
 
 
244
 
                                        for (int r = 1 - gRadius; r <= gRadius; r++){                   
245
 
                        
246
 
                                                unsigned int this_x_pixel = this_y_pixel + r;
247
 
                                                u_sum += u_values[this_x_pixel];
248
 
                                                v_sum += v_values[this_x_pixel];                        
249
 
                                        }
250
 
                                }
251
 
 
252
 
 
253
 
                                float u_ave = (float)u_sum/pixels_in_region;
254
 
                                float v_ave = (float)v_sum/pixels_in_region;
255
 
 
256
 
                                // Now work out standard deviation for U and V channels
257
 
                                u_sum = 0, v_sum = 0;
258
 
 
259
 
                                for (int t = 1 - gRadius; t <= gRadius; t++){                   
260
 
                                        
261
 
                                        unsigned int this_y_pixel = pixel_number + (t * in.width());
262
 
                                
263
 
                                        for (int r = 1 - gRadius; r <= gRadius; r++){                   
264
 
                        
265
 
                                                unsigned int this_x_pixel = this_y_pixel + r;
266
 
                                        
267
 
                                                u_sum +=  pow(u_values[this_x_pixel]-u_ave,2);
268
 
                                                v_sum +=  pow(v_values[this_x_pixel]-v_ave,2);
269
 
 
270
 
                                        }
271
 
                                }
272
 
                        
273
 
                        
274
 
                                float std_u = sqrt(u_sum/(pixels_in_region-1));
275
 
                                float std_v = sqrt(v_sum/(pixels_in_region-1)); 
276
 
                        
277
 
                                // Add these colour features to feature vector                                                  
278
 
                                gabor_responses[feature-1].index = feature;
279
 
                                gabor_responses[feature-1].value = u_ave;
280
 
                                //cout << feature << ":" << u_ave << " ";
281
 
                                feature++;
282
 
                                gabor_responses[feature-1].index = feature;
283
 
                                gabor_responses[feature-1].value = std_u;
284
 
                                //cout << feature << ":" << std_u << " ";
285
 
                                feature++;
286
 
                                gabor_responses[feature-1].index = feature;
287
 
                                gabor_responses[feature-1].value = v_ave;
288
 
                                //cout << feature << ":" << v_ave << " ";
289
 
                                feature++;                                                              
290
 
                                gabor_responses[feature-1].index = feature;
291
 
                                gabor_responses[feature-1].value = std_v;
292
 
                                //cout << feature << ":" << std_v << " ";
293
 
                                feature++;
294
 
                                gabor_responses[feature-1].index = feature;
295
 
                                gabor_responses[feature-1].value = u_values[pixel_number];
296
 
                                //cout << feature << ":" << u_values[pixel_number] << " ";
297
 
                                feature++;                                                              
298
 
                                gabor_responses[feature-1].index = feature;
299
 
                                gabor_responses[feature-1].value = v_values[pixel_number];
300
 
                                //cout << feature << ":" << v_values[pixel_number] << " " << endl;
301
 
                                gabor_responses[feature].index = -1;                            
302
 
                
303
 
                                score = svm_predict_probability(model,gabor_responses,prob_estimates);  
304
 
                                svm_responses.push_back(prob_estimates[0]);
305
 
 
306
 
                        }
307
 
 
308
 
                        delete[] response;
309
 
                }
310
 
                
311
 
                // Create mask
312
 
                if (mask){
313
 
 
314
 
                        // Create mask file name
315
 
                        string mask_name = ("");
316
 
                        if (imagefile.substr(imagefile.length()-4,1) == (".")){
317
 
                        
318
 
                                mask_name.append(imagefile.substr(0,imagefile.length()-4));
319
 
                                                                
320
 
                        }else{
321
 
                        
322
 
                                mask_name.append(imagefile.substr(0,imagefile.length()-4));
323
 
                        }
324
 
                        mask_name.append("_mask.");
325
 
                        mask_name.append(mask_format);
326
 
 
327
 
                        cout << "Generating mask:\t" << mask_name << endl;                              
328
 
                        // Create mask of same dimensions
329
 
                        vigra::BRGBImage mask_out(nw, nh);
330
 
                                
331
 
                        // Set mask to white
332
 
                        vigra::initImage(srcIterRange(mask_out.upperLeft(),
333
 
                        mask_out.upperLeft() + vigra::Diff2D(nw,nh)),
334
 
                        RGB(255,255,255) );
335
 
 
336
 
                        float *mask_response = NULL;
337
 
                        gLocations = NULL;
338
 
                        gNumLocs = 0;
339
 
 
340
 
                        // Create grid of fiducial points
341
 
                        for (int i = gRadius; i < in.height() - gRadius; i += spacing ){
342
 
                                for (int j = gRadius; j < in.width() - gRadius; j += spacing ){
343
 
                                        gNumLocs++;
344
 
                                }
345
 
                                // Add extra FP at the end of each row in case nw % gRadius
346
 
                                gNumLocs++;
347
 
                        }
348
 
 
349
 
                        // Add extra FP at the end of each row in case nh % gRadius     
350
 
                        for (int j = gRadius; j < in.width() - gRadius; j += spacing ){
351
 
                                gNumLocs++;
352
 
                        }
353
 
 
354
 
                        // Create the storage matrix
355
 
                        gLocations = CreateMatrix( (int)0, gNumLocs, 2);
356
 
                        gNumLocs = 0;
357
 
                        for (int i = gRadius; i < in.height() - gRadius; i += spacing ){
358
 
                                for (int j = gRadius; j < in.width() - gRadius; j += spacing ){
359
 
                        
360
 
                                        gLocations[gNumLocs][0] = j;
361
 
                                        gLocations[gNumLocs][1] = i;
362
 
                                        //cout << "fPoint " << gNumLocs << ":\t" << i << " " << j << endl;
363
 
                                        gNumLocs++;
364
 
                                }
365
 
                                
366
 
                                // Add extra FP at the end of each row in case nw % spacing
367
 
                                if (nw % spacing){
368
 
                                
369
 
                                        gLocations[gNumLocs][0] = nw - gRadius - 1;
370
 
                                        gLocations[gNumLocs][1] = i;
371
 
                                        //cout << "efPoint " << gNumLocs << ":\t" << i << " " << nw - gRadius - 1 << endl;
372
 
                                        gNumLocs++;
373
 
                                }
374
 
                                
375
 
                        }
376
 
 
377
 
                        // Add extra FP at the end of each row in case nh % spacing
378
 
                        if (nh % spacing){
379
 
                                                
380
 
                                for (int j = gRadius; j < in.width() - gRadius; j += spacing ){
381
 
                        
382
 
                                        gLocations[gNumLocs][0] = j;
383
 
                                        gLocations[gNumLocs][1] = nh - gRadius - 1;
384
 
                                        //cout << "efPoint " << gNumLocs << ":\t" << nh - gRadius - 1 << " " << j << endl;
385
 
                                        gNumLocs++;
386
 
                                
387
 
                                }
388
 
                        }
389
 
 
390
 
                        //cout << "Total FPs:\t" << gNumLocs << endl;
391
 
 
392
 
                        int len = 0;    
393
 
                                
394
 
                        //cout << "Pre-response " << in.height() << ","<<  in.width() << " " << gNumLocs << endl;       
395
 
                        mask_response = ProcessChannel( pixels, in.height(), in.width(), mask_response, &len, basename );
396
 
                        //cout << "Post-response" << endl;
397
 
 
398
 
                        // Turn the response into SVM vector, and add colour features
399
 
                
400
 
                        int vector_length = (int)len/gNumLocs;
401
 
 
402
 
                        for ( int j = 0; j < gNumLocs; j++ ){
403
 
 
404
 
                                //cout << j << ":"<<endl;
405
 
 
406
 
                                unsigned int pixel_number = gLocations[j][0] + (in.width() * (gLocations[j][1] - 1)) - 1;
407
 
                                unsigned int feature = 1;
408
 
                                double score = 0;
409
 
                        
410
 
                                // need one more for index = -1
411
 
                                if(j >= max_nr_attr - 1){
412
 
                                        max_nr_attr *= 2;
413
 
                                        gabor_responses = (struct svm_node *) realloc(gabor_responses,max_nr_attr*sizeof(struct svm_node));
414
 
                                }       
415
 
                        
416
 
                        
417
 
                                for ( int v = (j * vector_length); v < ((j + 1) * vector_length); v++){                                 
418
 
                                        gabor_responses[feature-1].index = feature;
419
 
                                        gabor_responses[feature-1].value = mask_response[v];                                    
420
 
                                        //cout << feature << ":" << mask_response[v] << " ";
421
 
                                        feature++;
422
 
                                }
423
 
 
424
 
                                // Work out average colour - U + V channels                     
425
 
                                float u_sum = 0, v_sum = 0;
426
 
                                int pixels_in_region = (gRadius * 2)*(gRadius * 2);
427
 
                        
428
 
                                for (int t = 1 - gRadius; t <= gRadius; t++){                   
429
 
                        
430
 
                                        unsigned int this_y_pixel = pixel_number + (t * in.width());
431
 
 
432
 
                                        for (int r = 1 - gRadius; r <= gRadius; r++){                   
433
 
                        
434
 
                                                unsigned int this_x_pixel = this_y_pixel + r;
435
 
                                        
436
 
                                                u_sum += u_values[this_x_pixel];
437
 
                                                v_sum += v_values[this_x_pixel];
438
 
 
439
 
                                        }
440
 
                                }
441
 
 
442
 
                                float u_ave = (float)u_sum/pixels_in_region;
443
 
                                float v_ave = (float)v_sum/pixels_in_region;
444
 
 
445
 
                                // Now work out standard deviation for U and V channels
446
 
                                u_sum = 0, v_sum = 0;
447
 
 
448
 
                                for (int t = 1 - gRadius; t <= gRadius; t++){   
449
 
                                                
450
 
                                        unsigned int this_y_pixel = pixel_number + (t * in.width());
451
 
                                
452
 
                                        for (int r = 1 - gRadius; r <= gRadius; r++){                   
453
 
                        
454
 
                                                unsigned int this_x_pixel = this_y_pixel + r;
455
 
                                        
456
 
                                                u_sum +=  pow(u_values[this_x_pixel]-u_ave,2);
457
 
                                                v_sum +=  pow(v_values[this_x_pixel]-v_ave,2);
458
 
 
459
 
                                        }
460
 
                                }                       
461
 
 
462
 
                                float std_u = sqrt(u_sum/(pixels_in_region-1));
463
 
                                float std_v = sqrt(v_sum/(pixels_in_region-1)); 
464
 
 
465
 
                                // Add these colour features to feature vector                                                  
466
 
                                gabor_responses[feature-1].index = feature;
467
 
                                gabor_responses[feature-1].value = u_ave;
468
 
                                //cout << feature << ":" << u_ave << " ";
469
 
                                feature++;
470
 
                                gabor_responses[feature-1].index = feature;
471
 
                                gabor_responses[feature-1].value = std_u;
472
 
                                //cout << feature << ":" << std_u << " ";
473
 
                                feature++;
474
 
                                gabor_responses[feature-1].index = feature;
475
 
                                gabor_responses[feature-1].value = v_ave;
476
 
                                //cout << feature << ":" << v_ave << " ";
477
 
                                feature++;                                                              
478
 
                                gabor_responses[feature-1].index = feature;
479
 
                                gabor_responses[feature-1].value = std_v;
480
 
                                //cout << feature << ":" << std_v << " ";
481
 
                                feature++;
482
 
                                gabor_responses[feature-1].index = feature;
483
 
                                gabor_responses[feature-1].value = u_values[pixel_number];
484
 
                                //cout << feature << ":" << u_values[pixel_number] << " ";
485
 
                                feature++;                                                              
486
 
                                gabor_responses[feature-1].index = feature;
487
 
                                gabor_responses[feature-1].value = v_values[pixel_number];
488
 
                                //cout << feature << ":" << v_values[pixel_number] << " " << endl;
489
 
                                gabor_responses[feature].index = -1;    
490
 
 
491
 
                                score = svm_predict_probability(model,gabor_responses,prob_estimates);
492
 
                                //cout << score << " " << prob_estimates[0] << endl;
493
 
 
494
 
                                if (prob_estimates[0] >= threshold){
495
 
                                                
496
 
                                        //cout << "Cloud\t\t(score " << prob_estimates[0] << " > " << threshold << ")" << endl; 
497
 
                                                        
498
 
                                        unsigned int sub_x0 = gLocations[j][0] - gRadius;
499
 
                                        unsigned int sub_y0 = gLocations[j][1] - gRadius;
500
 
                                        unsigned int sub_x1 = gLocations[j][0] + gRadius + 1;
501
 
                                        unsigned int sub_y1 = gLocations[j][1] + gRadius + 1;
502
 
                                        
503
 
                                        //cout << sub_x0 << ","<< sub_y0 << " - " << sub_x1 << "," << sub_y1 << endl;
504
 
                                        
505
 
                                        // Set region to black
506
 
                                        vigra::initImage(srcIterRange(mask_out.upperLeft() + vigra::Diff2D(sub_x0, sub_y0),
507
 
                                        mask_out.upperLeft() + vigra::Diff2D(sub_x1, sub_y1)),
508
 
                                        RGB(0,0,0) );                           
509
 
                                
510
 
                                }else{                          
511
 
                                        //cout << "Non-cloud\t(score " << prob_estimates[0] << " <= " << threshold << ")" << endl;      
512
 
                                                                
513
 
                                }                                               
514
 
                                //cout << feature_vector << endl;                       
515
 
 
516
 
                        }
517
 
        
518
 
                        delete [] mask_response;
519
 
 
520
 
                        // Re-size mask to match original image
521
 
                        vigra::BRGBImage mask_resize(info.width(),info.height());                          
522
 
                        resizeImageNoInterpolation(srcImageRange(mask_out),destImageRange(mask_resize));                
523
 
                        exportImage(srcImageRange(mask_resize), ImageExportInfo(mask_name.c_str()).setPixelType("UINT8"));
524
 
                
525
 
                }
526
 
 
527
 
                DisposeMatrix( pixels, in.height() );
528
 
                delete[] frameBuf;
529
 
                delete[] u_values;
530
 
                delete[] v_values;
531
 
                gNumLocs = 0;           
532
 
                cout << endl;
533
 
 
534
 
        }catch (vigra::StdException & e){
535
 
        
536
 
                // catch any errors that might have occured and print their reason
537
 
                cout << "Unable to open file:\t" << imagefile << endl << endl;
538
 
                cout << e.what() << endl << endl;
539
 
                for (int j = 0; j < gNumLocs; j++){
540
 
                        svm_responses.push_back(0);
541
 
                }
542
 
                return;
543
 
                
544
 
        }
545
 
        
546
 
        // Free up libsvm stuff
547
 
        free(gabor_responses);
548
 
        free(prob_estimates);
549
 
        svm_destroy_model(model);
550
 
        
551
 
}
552
 
 
 
49
// load SVM model
 
50
bool loadSVMmodel(struct svm_model*& model, string& model_file)
 
51
{
 
52
    if((model = svm_load_model(model_file.c_str())) == 0)
 
53
    {
 
54
        cout << "Couldn't load model file '" << model_file << "'" << endl << endl;
 
55
        return false;
 
56
    }
 
57
    else
 
58
    {
 
59
        cout << "Loaded model file:\t" << model_file << endl;
 
60
        return true;
 
61
    }
 
62
};
 
63
 
 
64
// destroy SVM model
 
65
void destroySVMmodel(struct svm_model*& model)
 
66
{
 
67
    svm_destroy_model(model);
 
68
};
 
69
 
 
70
// prepare image for use with celeste (downscale, converting in Luv)
 
71
void prepareCelesteImage(vigra::UInt16RGBImage& rgb,vigra::UInt16RGBImage& luv, int& resize_dimension, double& sizefactor,bool verbose)
 
72
{
 
73
    // Max dimension
 
74
    sizefactor = 1;
 
75
    int nw=rgb.width();
 
76
    int nh=rgb.height();
 
77
 
 
78
    if(nw >= nh)
 
79
    {
 
80
        if (resize_dimension >= nw )
 
81
        {
 
82
            resize_dimension = nw;
 
83
        }
 
84
    }
 
85
    else
 
86
    {
 
87
        if (resize_dimension >= nh)
 
88
        {
 
89
            resize_dimension = nh;
 
90
        }
 
91
    }
 
92
    //cout << "Re-size dimenstion:\t" << resize_dimension << endl;
 
93
    if(verbose)
 
94
        cout << "Image dimensions:\t" << rgb.width() << " x " << rgb.height() << endl;
 
95
 
 
96
    // Re-size to max dimension
 
97
    vigra::UInt16RGBImage temp;
 
98
 
 
99
    if (rgb.width() > resize_dimension || rgb.height() > resize_dimension)
 
100
    {
 
101
        if (rgb.width() >= rgb.height())
 
102
        {
 
103
            sizefactor = (double)resize_dimension/rgb.width();
 
104
            // calculate new image size
 
105
            nw = resize_dimension;
 
106
            nh = static_cast<int>(0.5 + (sizefactor*rgb.height()));
 
107
        }
 
108
        else
 
109
        {
 
110
            sizefactor = (double)resize_dimension/rgb.height();
 
111
            // calculate new image size
 
112
            nw = static_cast<int>(0.5 + (sizefactor*rgb.width()));
 
113
            nh = resize_dimension;
 
114
        }
 
115
 
 
116
        if(verbose)
 
117
        {
 
118
            cout << "Scaling by:\t\t" << sizefactor << endl;
 
119
            cout << "New dimensions:\t\t" << nw << " x " << nh << endl;
 
120
        };
 
121
 
 
122
        // create a RGB image of appropriate size
 
123
        temp.resize(nw,nh);
 
124
 
 
125
        // resize the image, using a bi-cubic spline algorithm
 
126
        vigra::resizeImageNoInterpolation(srcImageRange(rgb),destImageRange(temp));
 
127
        //exportImage(srcImageRange(out), ImageExportInfo("test.tif").setPixelType("UINT16"));
 
128
    }
 
129
    else
 
130
    {
 
131
        temp.resize(nw,nh);
 
132
        vigra::copyImage(srcImageRange(rgb),destImage(temp));
 
133
    };
 
134
 
 
135
    // Convert to Luv colour space
 
136
    luv.resize(temp.width(),temp.height());
 
137
    vigra::transformImage(srcImageRange(temp), destImage(luv), RGB2LuvFunctor<double>() );
 
138
    //exportImage(srcImageRange(luv), ImageExportInfo("test_luv.tif").setPixelType("UINT16"));
 
139
    temp.resize(0,0);
 
140
};
 
141
 
 
142
// converts the given Luv image into arrays for Gabors filtering
 
143
void prepareGaborImage(vigra::UInt16RGBImage& luv, float**& pixels)
 
144
{
 
145
    pixels = CreateMatrix( (float)0, luv.height(), luv.width() );
 
146
    // Prepare framebuf for Gabor API, we need only L channel
 
147
    for (int i = 0; i < luv.height(); i++ )
 
148
    {
 
149
        for (int j = 0; j < luv.width(); j++ )
 
150
        {
 
151
            pixels[i][j] = luv(j,i)[0];
 
152
            //cout << i << " " << j << " = " << k << " - " << frameBuf[k] << endl;
 
153
        }
 
154
    }
 
155
};
 
156
 
 
157
//classify the points with SVM
 
158
vector<double> classifySVM(struct svm_model* model, int gNumLocs,int**& gLocations,int width,int height,int vector_length, float*& response,int gRadius,vigra::UInt16RGBImage& luv,bool needsMoreIndex=false)
 
159
{
 
160
    std::vector<double> svm_response;
 
161
    // Integers and containers for libsvm
 
162
    int max_nr_attr = 56;
 
163
    int nr_class=svm_get_nr_class(model);
 
164
    struct svm_node *gabor_responses = (struct svm_node *) malloc(max_nr_attr*sizeof(struct svm_node));
 
165
    double *prob_estimates = (double *) malloc(nr_class*sizeof(double));
 
166
 
 
167
    for (int j = 0; j < gNumLocs; j++)
 
168
    {
 
169
        unsigned int feature = 1;
 
170
 
 
171
        if(needsMoreIndex)
 
172
        {
 
173
            if(j >= max_nr_attr - 1)
 
174
            {
 
175
                max_nr_attr *= 2;
 
176
                gabor_responses = (struct svm_node *) realloc(gabor_responses,max_nr_attr*sizeof(struct svm_node));
 
177
            }
 
178
        };
 
179
 
 
180
        for ( int v = (j * vector_length); v < ((j + 1) * vector_length); v++)
 
181
        {
 
182
            gabor_responses[feature-1].index = feature;
 
183
            gabor_responses[feature-1].value = response[v];                                     
 
184
            //cout << feature << ":" << response[v] << " ";
 
185
            feature++;
 
186
        }
 
187
 
 
188
        // Work out average colour and variance
 
189
        vigra::FindAverageAndVariance<vigra::UInt16RGBImage::PixelType> average;
 
190
        vigra::inspectImage(srcIterRange(
 
191
            luv.upperLeft()+vigra::Diff2D(gLocations[j][0]-gRadius,gLocations[j][1]-gRadius),
 
192
            luv.upperLeft()+vigra::Diff2D(gLocations[j][0]+gRadius,gLocations[j][1]+gRadius)
 
193
            ),average);
 
194
        // Add these colour features to feature vector                                                  
 
195
 
 
196
        gabor_responses[feature-1].index = feature;
 
197
        gabor_responses[feature-1].value = average.average()[1];
 
198
        //cout << feature << ":" << u_ave << " ";
 
199
        feature++;
 
200
        gabor_responses[feature-1].index = feature;
 
201
        gabor_responses[feature-1].value = sqrt(average.variance()[1]);
 
202
        //cout << feature << ":" << std_u << " ";
 
203
        feature++;
 
204
        gabor_responses[feature-1].index = feature;
 
205
        gabor_responses[feature-1].value = average.average()[2];
 
206
        //cout << feature << ":" << v_ave << " ";
 
207
        feature++;
 
208
        gabor_responses[feature-1].index = feature;
 
209
        gabor_responses[feature-1].value = sqrt(average.variance()[2]);
 
210
        //cout << feature << ":" << std_v << " ";
 
211
        feature++;
 
212
        gabor_responses[feature-1].index = feature;
 
213
        gabor_responses[feature-1].value = luv(gLocations[j][0],gLocations[j][1])[1];
 
214
        //cout << feature << ":" << u_values[pixel_number] << " ";
 
215
        feature++;
 
216
        gabor_responses[feature-1].index = feature;
 
217
        gabor_responses[feature-1].value = luv(gLocations[j][0],gLocations[j][1])[2];
 
218
        //cout << feature << ":" << v_values[pixel_number] << " " << endl;
 
219
        gabor_responses[feature].index = -1;
 
220
 
 
221
        svm_predict_probability(model,gabor_responses,prob_estimates);  
 
222
        svm_response.push_back(prob_estimates[0]);
 
223
    }
 
224
    // Free up libsvm stuff
 
225
    free(gabor_responses);
 
226
    free(prob_estimates);
 
227
    return svm_response;
 
228
};
 
229
 
 
230
// create a grid of control points for creating masks
 
231
void createGrid(int& gNumLocs,int**& gLocations,int gRadius,int width, int height)
 
232
{
 
233
    int spacing=(gRadius*2)+1;
 
234
    for (int i = gRadius; i < height - gRadius; i += spacing )
 
235
    {
 
236
        for (int j = gRadius; j < width - gRadius; j += spacing )
 
237
        {
 
238
            gNumLocs++;
 
239
        }
 
240
        // Add extra FP at the end of each row in case width % gRadius
 
241
        gNumLocs++;
 
242
    }
 
243
 
 
244
    // Add extra FP at the end of each row in case nh % gRadius 
 
245
    for (int j = gRadius; j < width - gRadius; j += spacing )
 
246
    {
 
247
        gNumLocs++;
 
248
    }
 
249
 
 
250
    // Create the storage matrix
 
251
    gLocations = CreateMatrix( (int)0, gNumLocs, 2);
 
252
    gNumLocs = 0;
 
253
    for (int i = gRadius; i < height - gRadius; i += spacing )
 
254
    {
 
255
        for (int j = gRadius; j < width - gRadius; j += spacing )
 
256
        {
 
257
            gLocations[gNumLocs][0] = j;
 
258
            gLocations[gNumLocs][1] = i;
 
259
            //cout << "fPoint " << gNumLocs << ":\t" << i << " " << j << endl;
 
260
            gNumLocs++;
 
261
        }
 
262
 
 
263
        // Add extra FP at the end of each row in case width % spacing
 
264
        if (width % spacing)
 
265
        {
 
266
            gLocations[gNumLocs][0] = width - gRadius - 1;
 
267
            gLocations[gNumLocs][1] = i;
 
268
            //cout << "efPoint " << gNumLocs << ":\t" << i << " " << nw - gRadius - 1 << endl;
 
269
            gNumLocs++;
 
270
        }
 
271
    }
 
272
 
 
273
    // Add extra FP at the end of each row in case height % spacing
 
274
    if (height % spacing)
 
275
    {
 
276
        for (int j = gRadius; j < width - gRadius; j += spacing )
 
277
        {
 
278
            gLocations[gNumLocs][0] = j;
 
279
            gLocations[gNumLocs][1] = height - gRadius - 1;
 
280
            //cout << "efPoint " << gNumLocs << ":\t" << nh - gRadius - 1 << " " << j << endl;
 
281
            gNumLocs++;
 
282
        }
 
283
    }
 
284
};
 
285
 
 
286
//generates the celeste mask on base of given responses and locations
 
287
void generateMask(vigra::BImage& mask,int& gNumLocs, int**& gLocations,std::vector<double> svm_responses,int gRadius, double threshold)
 
288
{
 
289
    for ( int j = 0; j < gNumLocs; j++ )
 
290
    {
 
291
        if (svm_responses[j] >= threshold)
 
292
        {
 
293
            unsigned int sub_x0 = gLocations[j][0] - gRadius;
 
294
            unsigned int sub_y0 = gLocations[j][1] - gRadius;
 
295
            unsigned int sub_x1 = gLocations[j][0] + gRadius + 1;
 
296
            unsigned int sub_y1 = gLocations[j][1] + gRadius + 1;
 
297
            //cout << sub_x0 << ","<< sub_y0 << " - " << sub_x1 << "," << sub_y1 << endl;
 
298
 
 
299
            // Set region to black
 
300
            vigra::initImage(srcIterRange(mask.upperLeft() + vigra::Diff2D(sub_x0, sub_y0),
 
301
                        mask.upperLeft() + vigra::Diff2D(sub_x1, sub_y1)), 0);                          
 
302
        }
 
303
        else
 
304
        {
 
305
            //cout << "Non-cloud\t(score " << prob_estimates[0] << " <= " << threshold << ")" << endl;  
 
306
        }
 
307
    }
 
308
};
 
309
 
 
310
vigra::BImage getCelesteMask(struct svm_model* model, vigra::UInt16RGBImage& input, int radius, float threshold, int resize_dimension,bool adaptThreshold,bool verbose)
 
311
{
 
312
    vigra::UInt16RGBImage luv;
 
313
    double sizefactor=1.0;
 
314
    prepareCelesteImage(input,luv,resize_dimension,sizefactor,verbose);
 
315
 
 
316
    // Prepare Gabor API array
 
317
    float** pixels=NULL;
 
318
    prepareGaborImage(luv,pixels);
 
319
 
 
320
    int** gLocations = NULL;
 
321
    int gNumLocs = 0;
 
322
 
 
323
    // Create grid of fiducial points
 
324
    createGrid(gNumLocs,gLocations,radius,luv.width(),luv.height());
 
325
 
 
326
    int len = 0;
 
327
    float* mask_response=NULL;
 
328
    mask_response = ProcessChannel(pixels,luv.width(),luv.height(),gNumLocs,gLocations,radius,mask_response,&len);
 
329
    // Turn the response into SVM vector, and add colour features
 
330
    vector<double> svm_responses=classifySVM(model,gNumLocs,gLocations,luv.width(),luv.height(),(int)len/gNumLocs,mask_response,radius,luv);
 
331
    delete [] mask_response;
 
332
 
 
333
    if(adaptThreshold)
 
334
    {
 
335
        double minVal=1;
 
336
        for(unsigned int i=0;i<svm_responses.size();i++)
 
337
        {
 
338
            if(svm_responses[i]<minVal)
 
339
            {
 
340
                minVal=svm_responses[i];
 
341
            };
 
342
        };
 
343
        if(threshold<minVal)
 
344
        {
 
345
            threshold=min(minVal+0.1,1.0);
 
346
        };
 
347
    };
 
348
    // Create mask of same dimensions
 
349
    vigra::BImage mask_out(luv.width(), luv.height(),255);
 
350
    generateMask(mask_out,gNumLocs,gLocations,svm_responses,radius,threshold);
 
351
    // Re-size mask to match original image
 
352
    vigra::BImage mask_resize(input.width(),input.height());                       
 
353
    resizeImageNoInterpolation(srcImageRange(mask_out),destImageRange(mask_resize));            
 
354
    DisposeMatrix(pixels,luv.height());
 
355
    DisposeMatrix(gLocations,gNumLocs);
 
356
    mask_out.resize(0,0);
 
357
    return mask_resize;
 
358
};
 
359
 
 
360
HuginBase::UIntSet getCelesteControlPoints(struct svm_model* model, vigra::UInt16RGBImage& input, HuginBase::CPointVector cps, int radius, float threshold, int resize_dimension,bool verbose)
 
361
{
 
362
    HuginBase::UIntSet cloudCP;
 
363
    vigra::UInt16RGBImage luv;
 
364
    double sizefactor=1.0;
 
365
    prepareCelesteImage(input,luv,resize_dimension,sizefactor,verbose);
 
366
 
 
367
    // Prepare Gabor API array
 
368
    float** pixels=NULL;
 
369
    prepareGaborImage(luv,pixels);
 
370
 
 
371
    int gNumLocs = cps.size();
 
372
    int** gLocations = CreateMatrix( (int)0, gNumLocs, 2);
 
373
    for(unsigned int j=0;j<cps.size();j++)
 
374
    {
 
375
        HuginBase::ControlPoint cp=cps[j].second;
 
376
        gLocations[j][0] = int(cp.x1 * sizefactor);
 
377
        gLocations[j][1] = int(cp.y1 * sizefactor);
 
378
        // Move CPs to border if the filter radius is out of bounds
 
379
        if (gLocations[j][0] <= radius)
 
380
        {
 
381
            gLocations[j][0] = radius + 1;
 
382
        }
 
383
        if (gLocations[j][1] <= radius)
 
384
        {
 
385
            gLocations[j][1] = radius + 1;
 
386
        }
 
387
        if (gLocations[j][0] >= luv.width() - radius)
 
388
        {
 
389
            gLocations[j][0] = luv.width() - radius - 1;
 
390
        }
 
391
        if (gLocations[j][1] >= luv.height() - radius)
 
392
        {
 
393
            gLocations[j][1] = luv.height() - radius - 1;
 
394
        }
 
395
    };
 
396
 
 
397
    int len = 0;
 
398
    float* response=NULL;
 
399
    response = ProcessChannel(pixels,luv.width(),luv.height(),gNumLocs,gLocations,radius,response,&len);
 
400
    // Turn the response into SVM vector, and add colour features
 
401
    vector<double> svm_responses=classifySVM(model,gNumLocs,gLocations,luv.width(),luv.height(),(int)len/gNumLocs,response,radius,luv);
 
402
    delete [] response;
 
403
 
 
404
    for(unsigned int i=0;i<svm_responses.size();i++)
 
405
    {
 
406
        if(svm_responses[i]>=threshold)
 
407
        {
 
408
            cloudCP.insert(cps[i].first);
 
409
        };
 
410
    };
 
411
    DisposeMatrix(pixels,luv.height());
 
412
    DisposeMatrix(gLocations,gNumLocs);
 
413
 
 
414
    return cloudCP;
 
415
};
 
416
 
 
417
} // end of namespace
 
 
b'\\ No newline at end of file'