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 #ifdef _OPENMP
00104 #include <omp.h>
00105 #endif
00106 using namespace std;
00107 
00108 
00156 int main(int argc, char **argv)
00157 {
00158 //Check arguments : IN/OUT;
00159     if (argc != 13)
00160     {
00161         std::cerr << " ****************************************** " << std::endl
00162         << " ******************  Flutter-Shutter  *************** " << std::endl
00163         << " **************************************************** " << std::endl
00164         << "Usage: " << argv[0] << "Image.png Flag_{code} SNR     " << std::endl
00165         << "Flag_{NUM | ANALOG} Velocity Deltat Imacquired.png    " << std::endl
00166         << "ImReconstructed.png Groundtruth.png Imdiff.png        " << std::endl
00167         << "Code_file_name.txt  FT_code_file_name.txt             " << std::endl
00168         << "Input : Image.png                                     " << std::endl
00169         << "Image to use for the simulation                       " << std::endl
00170         << "(grayscale or color) PNG.                             " << std::endl
00171         << "  Codes for the Flutter-Shutter Simulator             " << std::endl
00172         << "Code : can be                                         " << std::endl
00173         << "0 for Snapshot (classic strategy)                     " << std::endl
00174         << "or 1 for the Raskar-code                              " << std::endl
00175         << "or 2 for rand-code, a code whose coefficients come    " << std::endl
00176         << "from a uniform R.V on [-1,1]                          " << std::endl
00177         << "3 for constant 1 code (accumulation,                  " << std::endl
00178         << "4 for Sinc-code (sinc code is the best code given v)  " << std::endl
00179         << "5 for motion-invariant photography code               " << std::endl
00180         << "SNR for the level 100 :100 by default                 " << std::endl
00181         << "Flag_{NUM | ANALOG} 0 for Numerical Flutter           " << std::endl
00182         << "or 1 for Analog Flutter                               " << std::endl
00183         << "Velocity v                                            " << std::endl
00184         << " Deltat : temporal sampling (float default 1)         " << std::endl
00185         << "Outputs :                                             " << std::endl
00186         << "Imacquired.png: acquired image  in PNG.               " << std::endl
00187         << "Imdiff: difference image (groundtruth and             " << std::endl
00188         << "actual reconstruction) image  in PNG.                 " << std::endl
00189         << "ImReconstructed: reconstructed  in PNG.               " << std::endl
00190         << "code_file_name: txt files that contains the           " << std::endl
00191         << "code coefficients  $a_k$                              " << std::endl
00192         << "FT_code_file :txt file that contains the Fourier      " << std::endl
00193         << "transform of the flutter Shutter function             " << std::endl
00194         << "****************************************************  " << std::endl
00195         << "******  Yohann Tendero, 2012  **********************  " << std::endl
00196         << "**************************************************** " << std::endl;
00197         return 1;
00198     }
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00219     const int code_length=52; //Length of the code
00220     const int num_plot_points=100; //number of points used for plots
00225 
00226     float * Image_color;  
00227     size_t width, height, channel_number; 
00228     if (NULL == (Image_color = read_png_f32(argv[1], &width, &height,
00229                                             &channel_number)))
00230     {
00231         std::cerr << "Unable to load  file " << argv[1] << std::endl;
00232         return 1;
00233     }
00234 
00235 
00241 
00242 
00244     float** restored_out = new float*[channel_number];
00245     float** acquired_out = new float*[channel_number];
00246     const int acquired_width=width-code_length;
00247     const int border_size=acquired_width;
00248     //Classic mirror symmetry adding 2*code_length in the direction of
00249     //the blur on each sides.
00250     const int restored_width=acquired_width+border_size;
00251     const int out_width=acquired_width-2*code_length;// avoid border effects.
00252     const int crop_translation=round(code_length/2);
00253     double** restored = new double*[channel_number];
00254     double* acquired = new double[width*height];
00255     double* acquired_crop= new double[acquired_width*height];
00256 
00257     // Read parameter
00258     int code_number=atoi(argv[2]);
00259     float snr=atof(argv[3]);
00260     int flag_num_ana_flutter=atoi(argv[4]);
00261     float velocity=atof(argv[5]);
00262     float deltat=atof(argv[6]);
00263     //Init of random generator here so
00264     //it will produce independant RV
00265     // for all k in the following loop
00266     mt_init_genrand((unsigned long int) time(NULL));
00267     unsigned k;
00268 
00269 
00270 
00271     for ( k=0; k<channel_number; k++) // LOOP OVER CHANNELS
00272     {
00273 
00274 
00275 
00281 
00282 
00283 
00284 
00286 
00287 
00288         for (unsigned i=0; i<width*height; i++)
00289             acquired[i]=Image_color[k*width*height+i];
00291         if (flag_num_ana_flutter==0)//analog case
00292         {
00293             flutter_analog(acquired, code_number, width,
00294                            height, velocity, deltat, snr);
00295         }
00296         else
00297         {
00298 
00299             flutter_numerical(acquired, code_number, width, height,
00300                               velocity, deltat, snr);
00301         }
00302 
00304         for (int column=0; column<acquired_width; column++)
00305         {
00306             for (unsigned line=0; line<height; line++)
00307             {
00308                 acquired_crop[line*acquired_width+column]=
00309                     acquired[line*(width)+column+crop_translation];
00310             }
00311         }
00312 
00313 
00314 
00320 
00321 
00322 
00323 
00324 
00325 
00326         restored[k] = new double[restored_width*height];
00327 
00328         flutter_restore(acquired_crop, code_number, acquired_width, height,
00329                         velocity, restored[k], border_size, deltat);
00330 
00331 
00332 
00334         restored_out[k] = new float[out_width*height];
00335         acquired_out[k] = new float[out_width*height];
00336 
00337         for (int column=0; column<out_width; column++)
00338         {
00339             for (unsigned line=0; line<height; line++)
00340             {
00341                 restored_out[k][line*out_width+column]=
00342                     restored[k][line*(acquired_width+border_size)+column+
00343                                 2*crop_translation];
00344                 acquired_out[k][line*out_width+column]=
00345                     acquired[line*(acquired_width+code_length)+column+
00346                              3*crop_translation];
00347             }
00348         }
00349 
00350 
00351 
00352 
00353 
00354     } //END OF THE LOO FOR RGB
00355     for (unsigned k=0; k<channel_number; k++)
00356         delete [] restored[k];
00357     delete [] acquired;
00358     delete [] acquired_crop;
00359     delete [] restored;
00360 
00361     float normalization_factor=integral_code(code_number, deltat);
00364     float* acquired_color = new float[channel_number*out_width*height];
00365     float* restored_color = new float[channel_number*out_width*height];
00366     for (unsigned k=0; k<channel_number; k++)
00367         for (unsigned i=0; i<out_width*height; i++)
00368         {
00369             acquired_color[k*out_width*height+i]=acquired_out[k][i]
00370                                                  /normalization_factor;
00371             restored_color[k*out_width*height+i]=restored_out[k][i];
00372         }
00373 
00374     for (unsigned k=0; k<channel_number; k++)
00375     {
00376         delete [] acquired_out[k];
00377         delete [] restored_out[k];
00378     }
00379     delete [] acquired_out;
00380     delete [] restored_out;
00381 
00382 // the outputs with colors are acquired_color and acquired_color
00383 
00384 
00385 
00387     float* Image_crop = new float[channel_number*out_width*height];
00389     for (unsigned k=0; k<channel_number; k++)
00390     {
00391         for (int column=0; column<out_width; column++)
00392         {
00393             for (unsigned line=0; line<height; line++)
00394             {
00395                 Image_crop[line*out_width+column+k*height*out_width]=
00396                     Image_color[line*(width)+column+
00397                                 3*crop_translation+k*height*width];
00398             }
00399         }
00400     }
00401 
00402 
00403     free(Image_color);
00405     write_png_f32(argv[7],acquired_color,out_width,height,channel_number);
00406     delete [] acquired_color;
00407 
00409     write_png_f32(argv[8],restored_color,out_width,height,channel_number);
00410 
00412     write_png_f32(argv[9],Image_crop,out_width, height, channel_number);
00413 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426     float* difference = new float[channel_number*out_width*height];
00427     image_difference(Image_crop,restored_color, out_width, height,
00428                      channel_number,difference);
00429 
00431     RMSE(difference, out_width, height,channel_number,3*code_length,0);
00432 
00434     dynamic_renormalization(difference, out_width, height,channel_number);
00435 
00436 
00437 
00438 
00443 
00444 
00445 
00446 
00447 
00449     write_png_f32(argv[10],difference,out_width, height, channel_number);
00450     delete [] difference;
00451 
00452 
00455 
00457     ofstream file_code(argv[11], ios::out | ios::trunc);
00458     // opening the file (erase if previous exists)
00459     if (file_code)
00460     {
00461         for (int k=0; k<code_length; k++)
00462         {
00463             file_code << code[atoi(argv[2])][k] <<";" << endl;
00464         }
00465 
00466         file_code.close();
00467     }
00468     else
00469         cerr << "Unable to open file !" << endl;
00470 
00472     ofstream file_TFcode(argv[12], ios::out | ios::trunc);
00473     // opening the file (erase if previous exists)
00474     if (file_TFcode)
00475     {
00476         for (float xi=-2*M_PI*atof(argv[5])*atof(argv[6]);
00477                    xi<=2*M_PI*atof(argv[5])*atof(argv[6]);
00478                 xi=xi+4*M_PI/num_plot_points)
00479         {
00480             file_TFcode << xi << " " <<
00481             abs_hat_alpha(code[atoi(argv[2])],  code_length, xi) << endl;
00482         }
00483 
00484         file_TFcode.close();
00485     }
00486     else
00487         cerr << "Unable to open file !" << endl;
00488 
00489 
00490 
00495 
00497     int difference_crop2_width=out_width-2*code_length;
00498     float** Image_crop2 = new float*[channel_number];
00499     float** restored_crop2 = new float*[channel_number];
00500 
00501 
00502     for (unsigned k=0; k<channel_number; k++)
00503     {
00504         Image_crop2[k] =  new float[difference_crop2_width*height];
00505         restored_crop2[k] = new float[difference_crop2_width*height];
00506 
00507 
00508         for (unsigned j=0; j<height; j++)
00509         {
00510             for (int i=0; i<difference_crop2_width; i++)
00513             {
00514                 restored_crop2[k][i+(difference_crop2_width)*j]=
00515                     restored_color[i+out_width*j+code_length
00516                                    +k*height*out_width];
00517                 Image_crop2[k][i+(difference_crop2_width)*j]=
00518                     Image_crop[i+out_width*j+code_length+k*height*out_width];
00519 
00520             }
00521         }
00522 
00523         midway(Image_crop2[k],restored_crop2[k],difference_crop2_width,height);
00524     }
00525 
00526 
00527 
00528 
00529 
00530     delete [] restored_color;
00531     delete [] Image_crop;
00532 
00533 
00534     float* difference_crop2=
00535         new float[channel_number*difference_crop2_width*height];
00536     float* Image_crop2_final =
00537         new float[channel_number*difference_crop2_width*height];
00538     float* restored_crop2_final =
00539         new float[channel_number*difference_crop2_width*height];
00540 
00541 
00542 
00543     for ( k=0; k<channel_number; k++)
00544         for (unsigned i=0; i<difference_crop2_width*height; i++)
00545         {
00546             Image_crop2_final[k*difference_crop2_width*height+i]=
00547                 Image_crop2[k][i];
00548             restored_crop2_final[k*difference_crop2_width*height+i]=
00549                 restored_crop2[k][i];
00550         }
00551 
00552 
00553     for (unsigned k=0; k<channel_number; k++)
00554     {
00555         delete [] Image_crop2[k];
00556         delete [] restored_crop2[k];
00557     }
00558     delete [] Image_crop2;
00559     delete [] restored_crop2;
00560 
00561 
00562 
00563     image_difference(Image_crop2_final,restored_crop2_final,
00564                      difference_crop2_width, height,channel_number,
00565                      difference_crop2);
00566 
00567 
00568     delete [] Image_crop2_final;
00569     delete [] restored_crop2_final;
00570 
00571 
00572 
00575     RMSE(difference_crop2, difference_crop2_width, height, channel_number,0,1);
00576 
00577     delete [] difference_crop2;
00578 
00579 
00580 
00581 
00582     return 0;
00583 }
 All Files Functions Variables Typedefs Defines