1.1 diff -r 5edfbd3e7a46 -r 1204ebf9340d PTdecode/CImg-1.3.0/examples/greycstoration.cpp 1.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 +++ b/PTdecode/CImg-1.3.0/examples/greycstoration.cpp Mon Aug 03 14:09:20 2009 +0100 1.4 @@ -0,0 +1,576 @@ 1.5 +/* 1.6 + # 1.7 + # File : greycstoration.cpp 1.8 + # ( C++ source file ) 1.9 + # 1.10 + # Description : GREYCstoration - A tool to denoise, inpaint and resize images. 1.11 + # This file is a part of the CImg Library project. 1.12 + # ( http://cimg.sourceforge.net ) 1.13 + # See also the GREYCstoration web page 1.14 + # ( http://www.greyc.ensicaen.fr/~dtschump/greycstoration ) 1.15 + # 1.16 + # The GREYCstoration algorithm is an implementation of tensor-directed and 1.17 + # patch-based diffusion PDE's for image regularization and interpolation, 1.18 + # published in 1.19 + # 1.20 + # "Defining Some Variational Methods on the Space of Patches : 1.21 + # Application to Multi-Valued Image Denoising and Registration" 1.22 + # (D. Tschumperle, L. Brun) 1.23 + # Rapport de recherche : Les cahiers du GREYC No 08-01, Mars 2008. 1.24 + # 1.25 + # "Fast Anisotropic Smoothing of Multi-Valued Images 1.26 + # using Curvature-Preserving PDE's" 1.27 + # (D. Tschumperle) 1.28 + # International Journal of Computer Vision, May 2006. 1.29 + # 1.30 + # "Vector-Valued Image Regularization with PDE's : A Common Framework 1.31 + # for Different Applications" 1.32 + # (D. Tschumperle, R. Deriche). 1.33 + # IEEE Transactions on Pattern Analysis and Machine Intelligence, 1.34 + # Vol 27, No 4, pp 506-517, April 2005. 1.35 + # 1.36 + # Copyright : David Tschumperle 1.37 + # ( http://www.greyc.ensicaen.fr/~dtschump/ ) 1.38 + # 1.39 + # License : CeCILL v2.0 1.40 + # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html ) 1.41 + # 1.42 + # This software is governed by the CeCILL license under French law and 1.43 + # abiding by the rules of distribution of free software. You can use, 1.44 + # modify and/ or redistribute the software under the terms of the CeCILL 1.45 + # license as circulated by CEA, CNRS and INRIA at the following URL 1.46 + # "http://www.cecill.info". 1.47 + # 1.48 + # As a counterpart to the access to the source code and rights to copy, 1.49 + # modify and redistribute granted by the license, users are provided only 1.50 + # with a limited warranty and the software's author, the holder of the 1.51 + # economic rights, and the successive licensors have only limited 1.52 + # liability. 1.53 + # 1.54 + # In this respect, the user's attention is drawn to the risks associated 1.55 + # with loading, using, modifying and/or developing or reproducing the 1.56 + # software by the user in light of its specific status of free software, 1.57 + # that may mean that it is complicated to manipulate, and that also 1.58 + # therefore means that it is reserved for developers and experienced 1.59 + # professionals having in-depth computer knowledge. Users are therefore 1.60 + # encouraged to load and test the software's suitability as regards their 1.61 + # requirements in conditions enabling the security of their systems and/or 1.62 + # data to be ensured and, more generally, to use and operate it in the 1.63 + # same conditions as regards security. 1.64 + # 1.65 + # The fact that you are presently reading this means that you have had 1.66 + # knowledge of the CeCILL license and that you accept its terms. 1.67 + # 1.68 +*/ 1.69 + 1.70 +#define cimg_plugin "plugins/greycstoration.h" 1.71 +#ifndef cimg_debug 1.72 +#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ 1.73 + || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) 1.74 +#define cimg_debug 2 1.75 +#else 1.76 +#define cimg_debug 1 1.77 +#endif 1.78 +#endif 1.79 +#include "CImg.h" 1.80 +#if cimg_OS!=2 1.81 +#include <pthread.h> 1.82 +#endif 1.83 +#define gprintf if (verbose) std::fprintf 1.84 +using namespace cimg_library; 1.85 + 1.86 +// The lines below are necessary when using a non-standard compiler as visualcpp6. 1.87 +#ifdef cimg_use_visualcpp6 1.88 +#define std 1.89 +#endif 1.90 +#ifdef min 1.91 +#undef min 1.92 +#undef max 1.93 +#endif 1.94 + 1.95 +//----------- 1.96 +// get_geom() : read geometry from a string (for instance '320x256' or '200%x200%'). 1.97 +//----------- 1.98 +void get_geom(const char *geom, int &geom_w, int &geom_h) { 1.99 + char tmp[16]; 1.100 + std::sscanf(geom,"%d%7[^0-9]%d%7[^0-9]",&geom_w,tmp,&geom_h,tmp+1); 1.101 + if (tmp[0]=='%') geom_w=-geom_w; 1.102 + if (tmp[1]=='%') geom_h=-geom_h; 1.103 +} 1.104 + 1.105 +//-------------------------- 1.106 +// GREYCstoration main code 1.107 +//-------------------------- 1.108 +template<typename T> void greycstoration(int argc, char **argv, T pixel_type) { 1.109 + pixel_type = (T)0; 1.110 + cimg_usage(" Open Source Algorithms for Image Denoising and Interpolation."); 1.111 + cimg_help("-------------------------------------------------------------------------\n" 1.112 + " GREYCstoration v3.0, by David Tschumperle. \n" 1.113 + " ------------------------------------------------------------------------\n" 1.114 + " This program allows to denoise, inpaint and resize 2D color images. \n" 1.115 + " It is the result of the research work done in the IMAGE group of the \n" 1.116 + " GREYC Lab (CNRS, UMR 6072) (http://www.greyc.ensicaen.fr/EquipeImage/) \n" 1.117 + " by David Tschumperle (http://www.greyc.ensicaen.fr/~dtschump/). This \n" 1.118 + " program has been primarily released to help people processing image data\n" 1.119 + " and to allow comparisons between regularization algorithms. This is an \n" 1.120 + " open source software, distributed within the CImg Library package \n" 1.121 + " (http://cimg.sourceforge.net), and submitted to the CeCILL License. If \n" 1.122 + " you are interested to distribute it in a closed-source product, please \n" 1.123 + " read the licence file carefully. If you are using 'GREYCstored' images \n" 1.124 + " in your own publications, be kind to reference the GREYCstoration web \n" 1.125 + " site or the related scientific papers. More informations available at : \n" 1.126 + " ** http://cimg.sourceforge.net/greycstoration/ ** \n" 1.127 + "-------------------------------------------------------------------------\n"); 1.128 + 1.129 + // Read Global parameters 1.130 + //------------------------ 1.131 + cimg_help(" + Global parameters\n -----------------------"); 1.132 + const char *restore_mode = cimg_option("-restore",(char*)0,"Restore image specified after '-restore'"); 1.133 + const char *inpaint_mode = cimg_option("-inpaint",(char*)0,"Inpaint image specified after '-inpaint'"); 1.134 + const char *resize_mode = cimg_option("-resize",(char*)0,"Resize image specified after '-resize'"); 1.135 + const char *clean_mode = cimg_option("-clean",(char*)0,"Clean image specified after '-clean'"); 1.136 + const char *reference_image = cimg_option("-ref",(char*)0,"Reference image to compare with"); 1.137 + const char nb_bits = cimg_option("-bits",8,"Define input value type (8='uchar', 16='ushort', 32='float')"); 1.138 + const unsigned int value_factor = cimg_option("-fact",0,"Define input value factor (0=auto)"); 1.139 + const float noise_g = cimg_option("-ng",0.0f,"Add Gaussian noise before denoising"); 1.140 + const float noise_u = cimg_option("-nu",0.0f,"Add Uniform noise before denoising"); 1.141 + const float noise_s = cimg_option("-ns",0.0f,"Add Salt&Pepper noise before denoising"); 1.142 + const unsigned int color_base = cimg_option("-cbase",0,"Processed color base (0=RGB, 1=YCbCr)"); 1.143 + const char *channel_range = cimg_option("-crange",(char*)0,"Processed channels (ex: '0-2')"); 1.144 + const unsigned int saving_step = cimg_option("-save",0,"Iteration saving step (>=0)"); 1.145 + const bool visu = cimg_option("-visu",cimg_display?true:false,"Enable/Disable visualization windows (0 or 1)"); 1.146 + const char *file_o = cimg_option("-o",(char*)0,"Filename of output image"); 1.147 + const bool append_result = cimg_option("-append",false,"Append images in output file"); 1.148 + const bool verbose = cimg_option("-verbose",true,"Verbose mode"); 1.149 + const unsigned int jpg_quality = cimg_option("-quality",100,"Output compression quality (if JPEG format)"); 1.150 + unsigned int nb_iterations = cimg_option("-iter",(restore_mode||clean_mode)?1:(inpaint_mode?1000:3), 1.151 + "Number of iterations (>0)"); 1.152 + const float sdt = cimg_option("-sharp",(restore_mode||clean_mode)?0.0f:(inpaint_mode?0.0f:10.0f), 1.153 + "Sharpening strength (activate sharpening filter, >=0)"); 1.154 + const float sp = cimg_option("-se",(restore_mode||clean_mode)?0.5f:(inpaint_mode?0.5f:3.0f), 1.155 + "Sharpening edge threshold (>=0)"); 1.156 + const unsigned int tile_size = cimg_option("-tile",512,"Activate tiled mode and set tile size (>=0)"); 1.157 + const unsigned int tile_border = cimg_option("-btile",4,"Size of tile borders (>=0)"); 1.158 + const unsigned int nb_threads = cimg_option("-threads",1,"Number of threads used (*experimental*, tile mode only, >0)"); 1.159 + const bool fast_approx = cimg_option("-fast",true,"Try faster algorithm (true or false)"); 1.160 + 1.161 + // Declare specific algorithm parameters 1.162 + //-------------------------------------- 1.163 + float amplitude = 0, sharpness = 0, anisotropy = 0, alpha = 0, sigma = 0, gauss_prec = 0, dl = 0, da = 0, sigma_s = 0, sigma_p = 0; 1.164 + unsigned int interpolation = 0, patch_size = 0, lookup_size = 0; 1.165 + 1.166 + if (argc==1 || 1.167 + (!restore_mode && !inpaint_mode && !resize_mode && !clean_mode) || 1.168 + (restore_mode && inpaint_mode) || (restore_mode && resize_mode) || (restore_mode && clean_mode) || 1.169 + (inpaint_mode && resize_mode) || (inpaint_mode && clean_mode)) { 1.170 + std::fprintf(stderr,"\n%s : You must specify (only) one of the '-restore', '-inpaint', '-resize' or '-clean' options.\n" 1.171 + "(try option '-h', '-h -restore','-h -inpaint', '-h -resize' or '-h -clean' to get options relative to specific actions\n\n", 1.172 + cimg::basename(argv[0])); 1.173 + std::exit(0); 1.174 + } 1.175 + 1.176 + // Init variables 1.177 + //---------------- 1.178 + CImg<T> img0, img, imgr; 1.179 + CImg<unsigned char> mask; 1.180 + CImgDisplay disp; 1.181 + 1.182 + // Read specific parameters for image restoration 1.183 + //------------------------------------------------ 1.184 + if (restore_mode) { 1.185 + cimg_help("\n + Restoration mode parameters\n ---------------------------"); 1.186 + amplitude = cimg_option("-dt",40.0f,"Regularization strength per iteration (>=0)"); 1.187 + sharpness = cimg_option("-p",0.9f,"Contour preservation (>=0)"); 1.188 + anisotropy = cimg_option("-a",0.15f,"Smoothing anisotropy (0<=a<=1)"); 1.189 + alpha = cimg_option("-alpha",0.6f,"Noise scale (>=0)"); 1.190 + sigma = cimg_option("-sigma",1.1f,"Geometry regularity (>=0)"); 1.191 + gauss_prec = cimg_option("-prec",2.0f,"Computation precision (>0)"); 1.192 + dl = cimg_option("-dl",0.8f,"Spatial integration step (0<=dl<=1)"); 1.193 + da = cimg_option("-da",30.0f,"Angular integration step (0<=da<=90)"); 1.194 + interpolation = cimg_option("-interp",0,"Interpolation type (0=Nearest-neighbor, 1=Linear, 2=Runge-Kutta)"); 1.195 + 1.196 + gprintf(stderr,"- Image Restoration mode\n"); 1.197 + if (!cimg::strcmp("-restore",restore_mode)) { 1.198 + std::fprintf(stderr,"%s : You must specify a valid input image filename after the '-restore' flag.\n\n",cimg::basename(argv[0])); 1.199 + std::exit(0); 1.200 + } 1.201 + gprintf(stderr,"- Load input image '%s'...",cimg::basename(restore_mode)); 1.202 + img.load(restore_mode); 1.203 + gprintf(stderr,"\r- Input image : '%s' (size %dx%d, value range [%g,%g])\n", 1.204 + cimg::basename(restore_mode),img.dimx(),img.dimy(),(double)img.min(),(double)img.max()); 1.205 + if (noise_g || noise_u || noise_s) { 1.206 + img0 = img; 1.207 + img.noise(noise_g,0).noise(noise_u,1).noise(noise_s,2); 1.208 + gprintf(stderr,"\r- Noisy image : value range [%g,%g], PSNR Noisy / Original : %g\n", 1.209 + (double)img.min(),(double)img.max(),img.PSNR(img0)); 1.210 + } 1.211 + } 1.212 + 1.213 + // Specific parameters for image inpainting 1.214 + //----------------------------------------- 1.215 + if (inpaint_mode) { 1.216 + cimg_help("\n + Inpainting mode parameters\n --------------------------"); 1.217 + const char *file_m = cimg_option("-m",(char*)0,"Input inpainting mask"); 1.218 + const unsigned int dilate = cimg_option("-dilate",0,"Inpainting mask dilatation (>=0)"); 1.219 + const unsigned int init = cimg_option("-init",4,"Inpainting init (0=black, 1=white, 2=noise, 3=unchanged, 4=smart)"); 1.220 + amplitude = cimg_option("-dt",20.0f,"Regularization strength per iteration (>=0)"); 1.221 + sharpness = cimg_option("-p",0.3f,"Contour preservation (>=0)"); 1.222 + anisotropy = cimg_option("-a",1.0f,"Smoothing anisotropy (0<=a<=1)"); 1.223 + alpha = cimg_option("-alpha",0.8f,"Noise scale (>=0)"); 1.224 + sigma = cimg_option("-sigma",2.0f,"Geometry regularity (>=0)"); 1.225 + gauss_prec = cimg_option("-prec",2.0f,"Computation precision (>0)"); 1.226 + dl = cimg_option("-dl",0.8f,"Spatial integration step (0<=dl<=1)"); 1.227 + da = cimg_option("-da",30.0f,"Angular integration step (0<=da<=90)"); 1.228 + interpolation = cimg_option("-interp",0,"Interpolation type (0=Nearest-neighbor, 1=Linear, 2=Runge-Kutta)"); 1.229 + 1.230 + gprintf(stderr,"- Image Inpainting mode\n"); 1.231 + if (!cimg::strcmp("-inpaint",inpaint_mode)) { 1.232 + std::fprintf(stderr,"%s : You must specify a valid input image filename after the '-inpaint' flag.\n\n", 1.233 + cimg::basename(argv[0])); 1.234 + std::exit(0); 1.235 + } 1.236 + gprintf(stderr,"- Load input image '%s'...",cimg::basename(inpaint_mode)); 1.237 + img.load(inpaint_mode); 1.238 + gprintf(stderr,"\r- Input image : '%s' (size %dx%d, value range [%g,%g])\n", 1.239 + cimg::basename(inpaint_mode),img.dimx(),img.dimy(),(double)img.min(),(double)img.max()); 1.240 + if (noise_g || noise_u || noise_s) { 1.241 + img0 = img; 1.242 + img.noise(noise_g,0).noise(noise_u,1).noise(noise_s,2); 1.243 + gprintf(stderr,"\r- Noisy image : value range [%g,%g], PSNR Noisy / Original : %g\n", 1.244 + (double)img.min(),(double)img.max(),img.PSNR(img0)); 1.245 + } 1.246 + if (!file_m) { 1.247 + std::fprintf(stderr,"%s : You need to specify a valid inpainting mask filename after the '-m' flag.\n\n", 1.248 + cimg::basename(argv[0])); 1.249 + std::exit(0); 1.250 + } 1.251 + if (cimg::strncasecmp("block",file_m,5)) { 1.252 + gprintf(stderr,"- Load inpainting mask '%s'...",cimg::basename(file_m)); 1.253 + mask.load(file_m); 1.254 + gprintf(stderr,"\r- Inpainting mask : '%s' (size %dx%d)\n", 1.255 + cimg::basename(file_m),mask.dimx(),mask.dimy()); 1.256 + } 1.257 + else { 1.258 + unsigned int l = 16; std::sscanf(file_m,"block%u",&l); 1.259 + mask.assign(img.dimx()/l,img.dimy()/l); 1.260 + cimg_forXY(mask,x,y) mask(x,y) = (x+y)%2; 1.261 + img0 = img; 1.262 + } 1.263 + mask.resize(img.dimx(),img.dimy(),1,1); 1.264 + if (dilate) mask.dilate(dilate); 1.265 + switch (init) { 1.266 + case 0 : { cimg_forXYV(img,x,y,k) if (mask(x,y)) img(x,y,k) = 0; } break; 1.267 + case 1 : { cimg_forXYV(img,x,y,k) if (mask(x,y)) img(x,y,k) = 255; } break; 1.268 + case 2 : { cimg_forXYV(img,x,y,k) if (mask(x,y)) img(x,y,k) = (T)(255*cimg::rand()); } break; 1.269 + case 3 : break; 1.270 + default: { 1.271 + typedef unsigned char uchar; 1.272 + CImg<unsigned char> tmask(mask), ntmask(tmask); 1.273 + CImg_3x3(M,uchar); Mpp = Mnp = Mpn = Mnn = 0; 1.274 + CImg_3x3(I,T); Ipp = Inp = Icc = Ipn = Inn = 0; 1.275 + while (ntmask.max()>0) { 1.276 + cimg_for3x3(tmask,x,y,0,0,M) if (Mcc && (!Mpc || !Mnc || !Mcp || !Mcn)) { 1.277 + const float 1.278 + ccp = Mcp?0.0f:1.0f, cpc = Mpc?0.0f:1.0f, 1.279 + cnc = Mnc?0.0f:1.0f, ccn = Mcn?0.0f:1.0f, 1.280 + csum = ccp + cpc + cnc + ccn; 1.281 + cimg_forV(img,k) { 1.282 + cimg_get3x3(img,x,y,0,k,I); 1.283 + img(x,y,k) = (T)((ccp*Icp + cpc*Ipc + cnc*Inc + ccn*Icn)/csum); 1.284 + } 1.285 + ntmask(x,y) = 0; 1.286 + } 1.287 + tmask = ntmask; 1.288 + } 1.289 + } break; 1.290 + } 1.291 + } 1.292 + 1.293 + // Specific parameters for image resizing 1.294 + //---------------------------------------- 1.295 + if (resize_mode) { 1.296 + cimg_help("\n + Resizing mode parameters\n ------------------------"); 1.297 + const char *geom0 = cimg_option("-g0",(char*)0,"Input image geometry"); 1.298 + const char *geom = cimg_option("-g",(char*)0,"Output image geometry"); 1.299 + const bool anchor = cimg_option("-anchor",true,"Anchor original pixels (keep their original values)"); 1.300 + const unsigned int init = cimg_option("-init",3,"Initial estimate (1=block, 3=linear, 4=Moving average, 5=bicubic)"); 1.301 + amplitude = cimg_option("-dt",20.0f,"Regularization strength per iteration (>=0)"); 1.302 + sharpness = cimg_option("-p",0.2f,"Contour preservation (>=0)"); 1.303 + anisotropy = cimg_option("-a",0.9f,"Smoothing anisotropy (0<=a<=1)"); 1.304 + alpha = cimg_option("-alpha",0.1f,"Noise scale (>=0)"); 1.305 + sigma = cimg_option("-sigma",1.5f,"Geometry regularity (>=0)"); 1.306 + gauss_prec = cimg_option("-prec",2.0f,"Computation precision (>0)"); 1.307 + dl = cimg_option("-dl",0.8f,"Spatial integration step (0<=dl<=1)"); 1.308 + da = cimg_option("-da",30.0f,"Angular integration step (0<=da<=90)"); 1.309 + interpolation = cimg_option("-interp",0,"Interpolation type (0=Nearest-neighbor, 1=Linear, 2=Runge-Kutta)"); 1.310 + 1.311 + gprintf(stderr,"- Image Resizing mode\n"); 1.312 + if (!geom && !geom0) { 1.313 + std::fprintf(stderr,"%s : You need to specify an output geometry or an input geometry (option -g or -g0).\n\n", 1.314 + cimg::basename(argv[0])); 1.315 + std::exit(0); 1.316 + } 1.317 + if (!cimg::strcmp("-resize",resize_mode)) { 1.318 + std::fprintf(stderr,"%s : You must specify a valid input image filename after the '-resize' flag.\n\n", 1.319 + cimg::basename(argv[0])); 1.320 + std::exit(0); 1.321 + } 1.322 + gprintf(stderr,"- Load input image '%s'...",cimg::basename(resize_mode)); 1.323 + img.load(resize_mode); 1.324 + gprintf(stderr,"\r- Input image : '%s' (size %dx%d, value range [%g,%g])\n", 1.325 + cimg::basename(resize_mode),img.dimx(),img.dimy(),(double)img.min(),(double)img.max()); 1.326 + if (noise_g || noise_u || noise_s) { 1.327 + img0 = img; 1.328 + img.noise(noise_g,0).noise(noise_u,1).noise(noise_s,2); 1.329 + gprintf(stderr,"\r- Noisy image : value range [%g,%g], PSNR Noisy / Original : %g\n", 1.330 + (double)img.min(),(double)img.max(),img.PSNR(img0)); 1.331 + } 1.332 + int w, h; 1.333 + if (geom0) { 1.334 + int w0, h0; 1.335 + get_geom(geom0,w0,h0); 1.336 + w0 = w0>0?w0:-w0*img.dimx()/100; 1.337 + h0 = h0>0?h0:-h0*img.dimy()/100; 1.338 + gprintf(stderr,"- Reducing geometry to %dx%d using %s interpolation.\n",w0,h0, 1.339 + init==1?"bloc":(init==3?"linear":(init==5?"bicubic":"moving average"))); 1.340 + img0.assign(img); 1.341 + w = img.dimx(); 1.342 + h = img.dimy(); 1.343 + img.resize(w0,h0,-100,-100,5); 1.344 + } 1.345 + if (geom) { 1.346 + get_geom(geom,w,h); 1.347 + w = w>0?w:-w*img.dimx()/100; 1.348 + h = h>0?h:-h*img.dimy()/100; 1.349 + } 1.350 + mask.assign(img.dimx(),img.dimy(),1,1,255); 1.351 + if (!anchor) mask.resize(w,h,1,1,1); else mask = !mask.resize(w,h,1,1,4); 1.352 + img.resize(w,h,1,-100,init); 1.353 + if (img0) { gprintf(stderr,"\r- PSNR Original / Thumbnail : %g\n",img.PSNR(img0)); } 1.354 + } 1.355 + 1.356 + // Specific parameters for image cleaning 1.357 + //---------------------------------------- 1.358 + if (clean_mode) { 1.359 + cimg_help("\n + Cleaning mode parameters\n ------------------------"); 1.360 + patch_size = cimg_option("-p",4,"Patch size (>0)"); 1.361 + sigma_s = cimg_option("-ss",15.0f,"Spatial sigma (>0)"); 1.362 + sigma_p = cimg_option("-sp",10.0f,"Patch sigma (>0)"); 1.363 + lookup_size = cimg_option("-r",7,"Size of the lookup region (>0)"); 1.364 + 1.365 + gprintf(stderr,"- Image Cleaning mode\n"); 1.366 + if (!cimg::strcmp("-clean",clean_mode)) { 1.367 + std::fprintf(stderr,"%s : You must specify a valid input image filename after the '-clean' flag.\n\n", 1.368 + cimg::basename(argv[0])); 1.369 + std::exit(0); 1.370 + } 1.371 + gprintf(stderr,"- Load input image '%s'...",cimg::basename(clean_mode)); 1.372 + img.load(clean_mode); 1.373 + gprintf(stderr,"\r- Input image : '%s' (size %dx%d, value range [%g,%g])\n", 1.374 + cimg::basename(clean_mode),img.dimx(),img.dimy(),(double)img.min(),(double)img.max()); 1.375 + if (noise_g || noise_u || noise_s) { 1.376 + img0 = img; 1.377 + img.noise(noise_g,0).noise(noise_u,1).noise(noise_s,2); 1.378 + gprintf(stderr,"\r- Noisy image : value range [%g,%g], PSNR Noisy / Original : %g\n", 1.379 + (double)img.min(),(double)img.max(),img.PSNR(img0)); 1.380 + } 1.381 + } 1.382 + 1.383 + // Load reference image if any specified 1.384 + //-------------------------------------- 1.385 + if (reference_image) { 1.386 + gprintf(stderr,"- Load reference image '%s'...",cimg::basename(reference_image)); 1.387 + imgr.load(reference_image); 1.388 + gprintf(stderr,"\r- Reference image : '%s' (size %dx%d, value range [%g,%g])", 1.389 + cimg::basename(reference_image),imgr.dimx(),imgr.dimy(),(double)imgr.min(),(double)imgr.max()); 1.390 + if (img0) { imgr.resize(img0); gprintf(stderr,", PSNR Reference / Original : %g dB\n",imgr.PSNR(img0)); } 1.391 + else { imgr.resize(img); gprintf(stderr,"\n"); } 1.392 + } 1.393 + 1.394 + // Init images and display 1.395 + //------------------------- 1.396 + CImg<T> dest(img); 1.397 + unsigned int crange_beg = 0, crange_end = dest.dimv()-1U; 1.398 + if (color_base) { 1.399 + switch (nb_bits) { 1.400 + case 8: dest.RGBtoYCbCr(); break; 1.401 + case 16: (dest/=256).RGBtoYCbCr(); break; 1.402 + default: std::fprintf(stderr,"\n%s : YCbCr color base is not authorized for 32bits float-valued images.\n\n", 1.403 + cimg::basename(argv[0])); std::exit(0); 1.404 + } 1.405 + } 1.406 + if (channel_range) std::sscanf(channel_range,"%u%*c%u",&crange_beg,&crange_end); 1.407 + gprintf(stderr,"- Color base : %s, Channels range : %u-%u\n",color_base?"YCbCr":"RGB",crange_beg,crange_end); 1.408 + if (!visu && !append_result) img.assign(); 1.409 + if (visu) { 1.410 + const int sx = 2*CImgDisplay::screen_dimx()/3, sy = 2*CImgDisplay::screen_dimy()/3; 1.411 + int nwidth = dest.dimx(), nheight = dest.dimy(); 1.412 + if (nwidth>sx) { nheight = nheight*sx/nwidth; nwidth = sx; } 1.413 + if (nheight>sy) { nwidth = nwidth*sy/nheight; nheight = sy; } 1.414 + disp.assign(nwidth,nheight,"GREYCstoration"); 1.415 + if (color_base) { 1.416 + if (nb_bits==16) (dest.get_YCbCrtoRGB()*=256).display(disp); 1.417 + else dest.get_YCbCrtoRGB().display(disp); 1.418 + } 1.419 + else dest.display(disp); 1.420 + } 1.421 + const float gfact = (value_factor>0)?value_factor:((sizeof(T)==2)?1.0f/256:1.0f); 1.422 + 1.423 + //--------------------------------- 1.424 + // Begin GREYCstoration iterations 1.425 + //--------------------------------- 1.426 + bool stop_all = false; 1.427 + for (unsigned int iter=0; iter<nb_iterations && !stop_all; iter++) { 1.428 + bool stop_iteration = false; 1.429 + 1.430 + // Run one iteration of the GREYCstoration filter 1.431 + //------------------------------------------------ 1.432 + CImg<T> dest_range = dest.get_shared_channels(crange_beg,crange_end); 1.433 + if (restore_mode) 1.434 + dest_range.greycstoration_run(amplitude,sharpness,anisotropy,alpha,sigma,gfact,dl,da,gauss_prec, 1.435 + interpolation,fast_approx,tile_size,tile_border,nb_threads); 1.436 + if (clean_mode) 1.437 + dest_range.greycstoration_patch_run(patch_size,sigma_s,sigma_p,lookup_size, 1.438 + tile_size,tile_border,nb_threads,fast_approx); 1.439 + if (inpaint_mode || resize_mode) 1.440 + dest_range.greycstoration_run(mask,amplitude,sharpness,anisotropy,alpha,sigma,gfact,dl,da,gauss_prec, 1.441 + interpolation,fast_approx,tile_size,tile_border,nb_threads); 1.442 + do { 1.443 + const unsigned int progress = (unsigned int)dest_range.greycstoration_progress(); 1.444 + gprintf(stderr,"\r- Processing : Iteration %u/%u (%u%%)\t\t",1+iter,nb_iterations,progress); 1.445 + if (disp) { 1.446 + if (disp.is_resized) disp.resize(); 1.447 + disp.set_title("Processing : Iteration %u/%u (%u%%)",1+iter,nb_iterations,progress); 1.448 + if (disp.is_closed || disp.is_keyQ || disp.is_keyESC) { 1.449 + dest_range.greycstoration_stop(); 1.450 + stop_iteration = true; 1.451 + iter = nb_iterations-1; 1.452 + } 1.453 + } 1.454 + cimg::wait(200); 1.455 + } while (dest_range.greycstoration_is_running()); 1.456 + if (!stop_iteration && sdt>0) dest_range.sharpen(sdt,sp,alpha/3,sigma/3); 1.457 + dest_range.cut(cimg::type<T>::min(),cimg::type<T>::max()); 1.458 + 1.459 + // Prepare for next iteration 1.460 + //--------------------------- 1.461 + CImg<T> tmp_rgb = color_base?(nb_bits==16?dest.get_YCbCrtoRGB()*=256:dest.get_YCbCrtoRGB()):CImg<T>(), 1.462 + &dest_rgb = color_base?tmp_rgb:dest; 1.463 + if (disp && visu) dest_rgb.display(disp); 1.464 + if (file_o && saving_step && !(iter%saving_step)) dest_rgb.save(file_o,iter); 1.465 + 1.466 + // Display result and allows user interaction if needed. 1.467 + //------------------------------------------------------- 1.468 + if (iter==nb_iterations-1) { 1.469 + gprintf(stderr,"\r- Processing : Done ! \n"); 1.470 + if (img0) { gprintf(stderr,"- PSNR Restored / Original : %g dB\n",dest_rgb.PSNR(img0)); } 1.471 + if (disp) { 1.472 + static bool first_time = true; 1.473 + if (first_time) { 1.474 + first_time = false; 1.475 + gprintf(stderr, 1.476 + "- GREYCstoration interface :\n" 1.477 + " > You can now zoom to a particular rectangular region,\n" 1.478 + " or press one of the following key on the display window :\n" 1.479 + " SPACE : Swap views.\n" 1.480 + " S : Save a snapshot of the current image.\n" 1.481 + " I : Run another iteration.\n" 1.482 + " Q : Quit GREYCstoration.\n"); 1.483 + } 1.484 + 1.485 + CImgList<T> visu; 1.486 + visu.insert(img0,~0,true).insert(img,~0,true).insert(dest_rgb,~0,true).insert(imgr,~0U,true); 1.487 + const char *titles[4] = { "original", "noisy", "restored", "reference"}; 1.488 + unsigned int visupos = 2; 1.489 + CImgDisplay dispz; 1.490 + CImg<T> zoom; 1.491 + int snb = 0; 1.492 + bool stop_interact = false; 1.493 + while (!stop_interact) { 1.494 + disp.show().set_title("GREYCstoration (%s)",titles[visupos]); 1.495 + const CImg<int> s = visu(visupos).get_select(disp,2); 1.496 + if (disp.is_closed) stop_interact = true; 1.497 + switch (disp.key) { 1.498 + case cimg::keySPACE: do { visupos = (visupos+1)%visu.size; } while (!visu(visupos)); break; 1.499 + case cimg::keyBACKSPACE: do { visupos = (visupos-1+visu.size)%visu.size; } while (!visu(visupos)); break; 1.500 + case cimg::keyQ: stop_interact = stop_all = true; break; 1.501 + case cimg::keyI: 1.502 + stop_interact = true; 1.503 + gprintf(stderr,"- Perform iteration %u...\n",++nb_iterations); 1.504 + dest_rgb.display(disp); 1.505 + break; 1.506 + case cimg::keyS: 1.507 + if (!snb) { 1.508 + if (!append_result) dest_rgb.save(file_o?file_o:"GREYCstoration.bmp"); 1.509 + else CImgList<T>(img,dest_rgb).get_append('x').save(file_o?file_o:"GREYCstoration.bmp"); 1.510 + } 1.511 + if (zoom) zoom.save(file_o?file_o:"GREYCstoration.bmp",snb); 1.512 + gprintf(stderr,"- Snapshot %u : '%s' saved\n",snb++,file_o?file_o:"GREYCstoration.bmp"); 1.513 + break; 1.514 + } 1.515 + disp.key = 0; 1.516 + if (disp.is_resized) disp.resize().display(visu(visupos)); 1.517 + if (dispz && dispz.is_resized) dispz.resize().display(zoom); 1.518 + if (dispz && dispz.is_closed) dispz.assign(); 1.519 + 1.520 + if (s[0]>=0 && s[1]>=0 && s[3]>=0 && s[4]>=0) { 1.521 + const int x0 = s[0], y0 = s[1], x1 = s[3], y1 = s[4]; 1.522 + if (cimg::abs(x0-x1)>4 && cimg::abs(y0-y1)>4) { 1.523 + CImgList<T> tmp(img.get_crop(x0,y0,x1,y1), dest_rgb.get_crop(x0,y0,x1,y1)); 1.524 + if (img0) tmp.insert(img0.get_crop(x0,y0,x1,y1),0); 1.525 + if (imgr) tmp.insert(imgr.get_crop(x0,y0,x1,y1)); 1.526 + zoom = tmp.get_append('x','c'); 1.527 + if (!dispz) { 1.528 + const int sx = 5*CImgDisplay::screen_dimx()/6, sy = 5*CImgDisplay::screen_dimy()/6; 1.529 + int nwidth = zoom.dimx(), nheight = zoom.dimy(); 1.530 + if (nwidth>nheight) { nheight = nheight*sx/nwidth; nwidth = sx; } 1.531 + else { nwidth = nwidth*sy/nheight; nheight = sy; } 1.532 + dispz.assign(zoom.get_resize(nwidth,nheight)); 1.533 + dispz.set_title("GREYCstoration (zoom) : - %s %s %s %s", 1.534 + img0?"original -":"", 1.535 + img?"noisy -":"", 1.536 + dest?"restored -":"", 1.537 + imgr?"reference -":""); 1.538 + } else dispz.resize(dispz.dimx(),dispz.dimx()*zoom.dimy()/zoom.dimx(),false); 1.539 + dispz.display(zoom).show(); 1.540 + } 1.541 + } 1.542 + } 1.543 + } 1.544 + } 1.545 + } 1.546 + 1.547 + // Save result and exit 1.548 + //---------------------- 1.549 + if (file_o) { 1.550 + CImg<T> tmp_rgb = color_base?(nb_bits==16?dest.get_YCbCrtoRGB()*=256:dest.get_YCbCrtoRGB()):CImg<T>(), 1.551 + &dest_rgb = color_base?tmp_rgb:dest; 1.552 + if (jpg_quality) { 1.553 + gprintf(stderr,"\n- Saving output image '%s' (JPEG quality = %u%%)\n",file_o,jpg_quality); 1.554 + if (!append_result) dest_rgb.save_jpeg(file_o,jpg_quality); 1.555 + else CImgList<T>(img,dest_rgb).get_append('x').save_jpeg(file_o,jpg_quality); 1.556 + } else { 1.557 + gprintf(stderr,"\n- Saving output image '%s'\n",file_o); 1.558 + if (!append_result) dest_rgb.save(file_o); 1.559 + else CImgList<T>(img,dest_rgb).get_append('x').save(file_o); 1.560 + } 1.561 + } 1.562 + gprintf(stderr,"\n- Quit\n\n"); 1.563 +} 1.564 + 1.565 + 1.566 +/*----------------- 1.567 + Main procedure 1.568 + ----------------*/ 1.569 +int main(int argc,char **argv) { 1.570 + const unsigned int color_base = cimg_option("-cbase",0,0); 1.571 + switch (cimg_option("-bits",8,0)) { 1.572 + case 32: { float pixel_type = 0; greycstoration(argc,argv,pixel_type); } break; 1.573 + case 16: { 1.574 + if (!color_base) { float pixel_type = 0; greycstoration(argc,argv,pixel_type); } 1.575 + else { unsigned short pixel_type = 0; greycstoration(argc,argv,pixel_type); } 1.576 + } break; 1.577 + default: { unsigned char pixel_type = 0; greycstoration(argc,argv,pixel_type); } break; 1.578 + } 1.579 + return 0; 1.580 +}