The flutter shutter camera simulator
|
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 }