The flutter shutter camera simulator
demo_flutter.cpp
Go to the documentation of this file.
00001 /*demo_flutter.cpp*/
00002 /*
00003 * Copyright 2012 IPOL Image Processing On Line http://www.ipol.im/
00004 *
00005 * This program is free software: you can redistribute it and/or modify
00006 * it under the terms of the GNU General Public License as published by
00007 * the Free Software Foundation, either version 3 of the License, or
00008 * (at your option) any later version.
00009 *
00010 * This program is distributed in the hope that it will be useful,
00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 * GNU General Public License for more details.
00014 *
00015 * You should have received a copy of the GNU General Public License
00016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 */
00018 
00085 #include <stdio.h>
00086 #include <stdlib.h>
00087 #include <iostream>
00088 #include <fstream>
00089 #include "mt19937ar.h"
00090 #include <math.h>
00091 #ifndef M_PI
00092 
00095 #define M_PI 3.14159265358979323846
00096 #endif
00097 #include "io_png/io_png.h"
00098 #include "flutter.h"
00099 #include "standard_routines.h"
00100 #include "midway.h"
00101 #include "borders.h"
00102 #include "codes_flutter.cpp"
00103 using namespace std;
00104 
00105 
00153 int main(int argc, char **argv)
00154 {
00155 //Check arguments : IN/OUT;
00156     if (argc != 13)
00157     {
00158         std::cerr << " ****************************************** " << std::endl
00159         << " ******************  Flutter-Shutter  *************** " << std::endl
00160         << " **************************************************** " << std::endl
00161         << "Usage: " << argv[0] << "Image.png Flag_{code} SNR     " << std::endl
00162         << "Flag_{NUM | ANALOG} Velocity Deltat Imacquired.png    " << std::endl
00163         << "ImReconstructed.png Groundtruth.png Imdiff.png        " << std::endl
00164         << "Code_file_name.txt  FT_code_file_name.txt             " << std::endl
00165         << "Input : Image.png                                     " << std::endl
00166         << "Image to use for the simulation                       " << std::endl
00167         << "(grayscale or color) PNG.                             " << std::endl
00168         << "  Codes for the Flutter-Shutter Simulator             " << std::endl
00169         << "Code : can be                                         " << std::endl
00170         << "0 for Snapshot (classic strategy)                     " << std::endl
00171         << "or 1 for the Raskar-code                              " << std::endl
00172         << "or 2 for rand-code, a code whose coefficients come    " << std::endl
00173         << "from a uniform R.V on [-1,1]                          " << std::endl
00174         << "3 for constant 1 code (accumulation,                  " << std::endl
00175         << "4 for Sinc-code (sinc code is the best code given v)  " << std::endl
00176         << "5 for motion-invariant photography code               " << std::endl
00177         << "SNR for the level 100 :100 by default                 " << std::endl
00178         << "Flag_{NUM | ANALOG} 0 for Numerical Flutter           " << std::endl
00179         << "or 1 for Analog Flutter                               " << std::endl
00180         << "Velocity v                                            " << std::endl
00181         << " Deltat : temporal sampling (float default 1)         " << std::endl
00182         << "Outputs :                                             " << std::endl
00183         << "Imacquired.png: acquired image  in PNG.               " << std::endl
00184         << "Imdiff: difference image (groundtruth and             " << std::endl
00185         << "actual reconstruction) image  in PNG.                 " << std::endl
00186         << "ImReconstructed: reconstructed  in PNG.               " << std::endl
00187         << "code_file_name: txt files that contains the           " << std::endl
00188         << "code coefficients  $a_k$                              " << std::endl
00189         << "FT_code_file :txt file that contains the Fourier      " << std::endl
00190         << "transform of the flutter Shutter function             " << std::endl
00191         << "****************************************************  " << std::endl
00192         << "******  Yohann Tendero, 2012  **********************  " << std::endl
00193         << "**************************************************** " << std::endl;
00194         return 1;
00195     }
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00216     const int code_length=52; //Length of the code
00217     const int num_plot_points=100; //number of points used for plots
00222 
00223     float * Image_color;  
00224     size_t width, height, channel_number; 
00225     if (NULL == (Image_color = read_png_f32(argv[1], &width, &height,
00226                                             &channel_number)))
00227     {
00228         std::cerr << "Unable to load  file " << argv[1] << std::endl;
00229         return 1;
00230     }
00231 
00232 
00238 
00239 
00241     float** restored_out = new float*[channel_number];
00242     float** acquired_out = new float*[channel_number];
00243     const int acquired_width=width-code_length;
00244     const int border_size=acquired_width;
00245     //Classic mirror symmetry adding 2*code_length in the direction of
00246     //the blur on each sides.
00247     const int restored_width=acquired_width+border_size;
00248     const int out_width=acquired_width-2*code_length;// avoid border effects.
00249     const int crop_translation=round(code_length/2);
00250     double** restored = new double*[channel_number];
00251     double* acquired = new double[width*height];
00252     double* acquired_crop= new double[acquired_width*height];
00253 
00254     // Read parameter
00255     int code_number=atoi(argv[2]);
00256     float snr=atof(argv[3]);
00257     int flag_num_ana_flutter=atoi(argv[4]);
00258     float velocity=atof(argv[5]);
00259     float deltat=atof(argv[6]);
00260     //Init of random generator here so
00261     //it will produce independant RV
00262     // for all k in the following loop
00263     mt_init_genrand((unsigned long int) time(NULL));
00264     unsigned k;
00265 
00266 
00267 
00268     for ( k=0; k<channel_number; k++) // LOOP OVER CHANNELS
00269     {
00270 
00271 
00272 
00278 
00279 
00280 
00281 
00283 
00284 
00285         for (unsigned i=0; i<width*height; i++)
00286             acquired[i]=Image_color[k*width*height+i];
00288         if (flag_num_ana_flutter==0)//analog case
00289         {
00290             flutter_analog(acquired, code_number, width,
00291                            height, velocity, deltat, snr);
00292         }
00293         else
00294         {
00295 
00296             flutter_numerical(acquired, code_number, width, height,
00297                               velocity, deltat, snr);
00298         }
00299 
00301         for (int column=0; column<acquired_width; column++)
00302         {
00303             for (unsigned line=0; line<height; line++)
00304             {
00305                 acquired_crop[line*acquired_width+column]=
00306                     acquired[line*(width)+column+crop_translation];
00307             }
00308         }
00309 
00310 
00311 
00317 
00318 
00319 
00320 
00321 
00322 
00323         restored[k] = new double[restored_width*height];
00324 
00325         flutter_restore(acquired_crop, code_number, acquired_width, height,
00326                         velocity, restored[k], border_size, deltat);
00327 
00328 
00329 
00331         restored_out[k] = new float[out_width*height];
00332         acquired_out[k] = new float[out_width*height];
00333 
00334         for (int column=0; column<out_width; column++)
00335         {
00336             for (unsigned line=0; line<height; line++)
00337             {
00338                 restored_out[k][line*out_width+column]=
00339                     restored[k][line*(acquired_width+border_size)+column+
00340                                 2*crop_translation];
00341                 acquired_out[k][line*out_width+column]=
00342                     acquired[line*(acquired_width+code_length)+column+
00343                              3*crop_translation];
00344             }
00345         }
00346 
00347 
00348 
00349 
00350 
00351     } //END OF THE LOO FOR RGB
00352     for (unsigned k=0; k<channel_number; k++)
00353         delete [] restored[k];
00354     delete [] acquired;
00355     delete [] acquired_crop;
00356     delete [] restored;
00357 
00358     float normalization_factor=integral_code(code_number, deltat);
00361     float* acquired_color = new float[channel_number*out_width*height];
00362     float* restored_color = new float[channel_number*out_width*height];
00363     for (unsigned k=0; k<channel_number; k++)
00364         for (unsigned i=0; i<out_width*height; i++)
00365         {
00366             acquired_color[k*out_width*height+i]=acquired_out[k][i]
00367                                                  /normalization_factor;
00368             restored_color[k*out_width*height+i]=restored_out[k][i];
00369         }
00370 
00371     for (unsigned k=0; k<channel_number; k++)
00372     {
00373         delete [] acquired_out[k];
00374         delete [] restored_out[k];
00375     }
00376     delete [] acquired_out;
00377     delete [] restored_out;
00378 
00379 // the outputs with colors are acquired_color and acquired_color
00380 
00381 
00382 
00384     float* Image_crop = new float[channel_number*out_width*height];
00386     for (unsigned k=0; k<channel_number; k++)
00387     {
00388         for (int column=0; column<out_width; column++)
00389         {
00390             for (unsigned line=0; line<height; line++)
00391             {
00392                 Image_crop[line*out_width+column+k*height*out_width]=
00393                     Image_color[line*(width)+column+
00394                                 3*crop_translation+k*height*width];
00395             }
00396         }
00397     }
00398 
00399 
00400     free(Image_color);
00402     write_png_f32(argv[7],acquired_color,out_width,height,channel_number);
00403     delete [] acquired_color;
00404 
00406     write_png_f32(argv[8],restored_color,out_width,height,channel_number);
00407 
00409     write_png_f32(argv[9],Image_crop,out_width, height, channel_number);
00410 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423     float* difference = new float[channel_number*out_width*height];
00424     image_difference(Image_crop,restored_color, out_width, height,
00425                      channel_number,difference);
00426 
00428     RMSE(difference, out_width, height,channel_number,3*code_length,0);
00429 
00431     dynamic_renormalization(difference, out_width, height,channel_number);
00432 
00433 
00434 
00435 
00440 
00441 
00442 
00443 
00444 
00446     write_png_f32(argv[10],difference,out_width, height, channel_number);
00447     delete [] difference;
00448 
00449 
00452 
00454     ofstream file_code(argv[11], ios::out | ios::trunc);
00455     // opening the file (erase if previous exists)
00456     if (file_code)
00457     {
00458         for (int k=0; k<code_length; k++)
00459         {
00460             file_code << code[atoi(argv[2])][k] <<";" << endl;
00461         }
00462 
00463         file_code.close();
00464     }
00465     else
00466         cerr << "Unable to open file !" << endl;
00467 
00469     ofstream file_TFcode(argv[12], ios::out | ios::trunc);
00470     // opening the file (erase if previous exists)
00471     if (file_TFcode)
00472     {
00473         for (float xi=-M_PI;
00474                    xi<=M_PI;
00475                 xi=xi+2*M_PI/num_plot_points)
00476         {
00477             file_TFcode << xi << " " <<
00478             abs_hat_alpha(code[atoi(argv[2])],  code_length, xi*velocity,
00479                           deltat) << endl;
00480         }
00481 
00482         file_TFcode.close();
00483     }
00484     else
00485         cerr << "Unable to open file !" << endl;
00486 
00487 
00488 
00493 
00495     int difference_crop2_width=out_width-2*code_length;
00496     float** Image_crop2 = new float*[channel_number];
00497     float** restored_crop2 = new float*[channel_number];
00498 
00499 
00500     for (unsigned k=0; k<channel_number; k++)
00501     {
00502         Image_crop2[k] =  new float[difference_crop2_width*height];
00503         restored_crop2[k] = new float[difference_crop2_width*height];
00504 
00505 
00506         for (unsigned j=0; j<height; j++)
00507         {
00508             for (int i=0; i<difference_crop2_width; i++)
00511             {
00512                 restored_crop2[k][i+(difference_crop2_width)*j]=
00513                     restored_color[i+out_width*j+code_length
00514                                    +k*height*out_width];
00515                 Image_crop2[k][i+(difference_crop2_width)*j]=
00516                     Image_crop[i+out_width*j+code_length+k*height*out_width];
00517 
00518             }
00519         }
00520 
00521         midway(Image_crop2[k],restored_crop2[k],difference_crop2_width,height);
00522     }
00523 
00524 
00525 
00526 
00527 
00528     delete [] restored_color;
00529     delete [] Image_crop;
00530 
00531 
00532     float* difference_crop2=
00533         new float[channel_number*difference_crop2_width*height];
00534     float* Image_crop2_final =
00535         new float[channel_number*difference_crop2_width*height];
00536     float* restored_crop2_final =
00537         new float[channel_number*difference_crop2_width*height];
00538 
00539 
00540 
00541     for ( k=0; k<channel_number; k++)
00542         for (unsigned i=0; i<difference_crop2_width*height; i++)
00543         {
00544             Image_crop2_final[k*difference_crop2_width*height+i]=
00545                 Image_crop2[k][i];
00546             restored_crop2_final[k*difference_crop2_width*height+i]=
00547                 restored_crop2[k][i];
00548         }
00549 
00550 
00551     for (unsigned k=0; k<channel_number; k++)
00552     {
00553         delete [] Image_crop2[k];
00554         delete [] restored_crop2[k];
00555     }
00556     delete [] Image_crop2;
00557     delete [] restored_crop2;
00558 
00559 
00560 
00561     image_difference(Image_crop2_final,restored_crop2_final,
00562                      difference_crop2_width, height,channel_number,
00563                      difference_crop2);
00564 
00565 
00566     delete [] Image_crop2_final;
00567     delete [] restored_crop2_final;
00568 
00569 
00570 
00573     RMSE(difference_crop2, difference_crop2_width, height, channel_number,0,1);
00574 
00575     delete [] difference_crop2;
00576 
00577 
00578 
00579 
00580     return 0;
00581 }
 All Files Functions Variables Typedefs Defines