1.1 diff -r 5edfbd3e7a46 -r 1204ebf9340d PTdecode/CImg-1.3.0/examples/wavelet_atrous.cpp 1.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 +++ b/PTdecode/CImg-1.3.0/examples/wavelet_atrous.cpp Mon Aug 03 14:09:20 2009 +0100 1.4 @@ -0,0 +1,234 @@ 1.5 +/* 1.6 + # 1.7 + # File : wavelet_atrous.cpp 1.8 + # ( C++ source file ) 1.9 + # 1.10 + # Description : Performs a 2D or 3D 'a trous' wavelet transform 1.11 + # (using a cubic spline) on an image or a video sequence. 1.12 + # This file is a part of the CImg Library project. 1.13 + # ( http://cimg.sourceforge.net ) 1.14 + # 1.15 + # Author : Renaud Peteri 1.16 + # ( Renaud.Peteri(at)mines-paris.org ) 1.17 + # 1.18 + # Institution : CWI, Amsterdam 1.19 + # 1.20 + # Date : February 2005 1.21 + # 1.22 + # References : Starck, J.-L., Murtagh, F. and Bijaoui, A., 1.23 + # Image Processing and Data Analysis: The Multiscale Approach, 1.24 + # Cambridge University Press, 1998. 1.25 + # (Hardback and softback, ISBN 0-521-59084-1 and 0-521-59914-8.) 1.26 + # 1.27 + # License : CeCILL v2.0 1.28 + # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html ) 1.29 + # 1.30 + # This software is governed by the CeCILL license under French law and 1.31 + # abiding by the rules of distribution of free software. You can use, 1.32 + # modify and/ or redistribute the software under the terms of the CeCILL 1.33 + # license as circulated by CEA, CNRS and INRIA at the following URL 1.34 + # "http://www.cecill.info". 1.35 + # 1.36 + # As a counterpart to the access to the source code and rights to copy, 1.37 + # modify and redistribute granted by the license, users are provided only 1.38 + # with a limited warranty and the software's author, the holder of the 1.39 + # economic rights, and the successive licensors have only limited 1.40 + # liability. 1.41 + # 1.42 + # In this respect, the user's attention is drawn to the risks associated 1.43 + # with loading, using, modifying and/or developing or reproducing the 1.44 + # software by the user in light of its specific status of free software, 1.45 + # that may mean that it is complicated to manipulate, and that also 1.46 + # therefore means that it is reserved for developers and experienced 1.47 + # professionals having in-depth computer knowledge. Users are therefore 1.48 + # encouraged to load and test the software's suitability as regards their 1.49 + # requirements in conditions enabling the security of their systems and/or 1.50 + # data to be ensured and, more generally, to use and operate it in the 1.51 + # same conditions as regards security. 1.52 + # 1.53 + # The fact that you are presently reading this means that you have had 1.54 + # knowledge of the CeCILL license and that you accept its terms. 1.55 + # 1.56 +*/ 1.57 + 1.58 +#include "CImg.h" 1.59 +using namespace cimg_library; 1.60 + 1.61 +// The lines below are necessary when using a non-standard compiler as visualcpp6. 1.62 +#ifdef cimg_use_visualcpp6 1.63 +#define std 1.64 +#endif 1.65 +#ifdef min 1.66 +#undef min 1.67 +#undef max 1.68 +#endif 1.69 + 1.70 +#ifndef cimg_imagepath 1.71 +#define cimg_imagepath "img/" 1.72 +#endif 1.73 + 1.74 +CImg<float> mask_x(const unsigned char scale) { 1.75 + unsigned char d1 = (unsigned char)std::pow(2.0,(double)(scale-1)); 1.76 + unsigned char d2 = (unsigned char)std::pow(2.0,(double)(scale)); 1.77 + unsigned char cx = (unsigned char)std::pow(2.0,(double)(scale)); 1.78 + unsigned char res = (unsigned char)std::pow(2.0,(double)scale); 1.79 + CImg<float> m(2*res +1,1,1);m.fill(0); 1.80 + m(cx) = 6.0; 1.81 + m(cx-d1) = m(cx+d1) =4.0; 1.82 + m(cx-d2) = m(cx+d2) =1.0; 1.83 + m /= 16.0; 1.84 + return m; 1.85 +} 1.86 + 1.87 +CImg<float> mask_y(const unsigned char scale) { 1.88 + unsigned char d1 = (unsigned char)std::pow(2.0,(double)(scale-1)); 1.89 + unsigned char d2 = (unsigned char)std::pow(2.0,(double)(scale)); 1.90 + unsigned char cy = (unsigned char)std::pow(2.0,(double)(scale)); 1.91 + unsigned char res = (unsigned char)std::pow(2.0,(double)scale); 1.92 + CImg<float> m(1,2*res +1);m.fill(0); 1.93 + m(0,cy) = 6.0; 1.94 + m(0,cy-d1) = m(0,cy+d1) =4.0; 1.95 + m(0,cy-d2) = m(0,cy+d2) =1.0; 1.96 + m /= 16.0; 1.97 + return m; 1.98 +} 1.99 + 1.100 +CImg<float> mask_t(const unsigned char scale) { 1.101 + unsigned char d1 = (unsigned char)std::pow(2.0,(double)(scale-1)); 1.102 + unsigned char d2 = (unsigned char)std::pow(2.0,(double)(scale)); 1.103 + unsigned char ct = (unsigned char)std::pow(2.0,(double)(scale)); 1.104 + unsigned char res = (unsigned char)std::pow(2.0,(double)scale); 1.105 + CImg<float> m(1,1,2*res +1);m.fill(0); 1.106 + m(0,0,ct) = 6.0; 1.107 + m(0,0,ct-d1) = m(0,0,ct+d1) =4.0; 1.108 + m(0,0,ct-d2) = m(0,0,ct+d2) =1.0; 1.109 + m /= 16.0; 1.110 + return m; 1.111 +} 1.112 + 1.113 +/*------------------ 1.114 + Main procedure 1.115 + ----------------*/ 1.116 +int main(int argc,char **argv) { 1.117 + 1.118 + cimg_usage("Perform an 'a trous' wavelet transform (using a cubic spline) on an image or on a video sequence.\n" 1.119 + "This wavelet transform is undecimated and produces 2 images/videos at each scale. For an example of\n" 1.120 + "decomposition on a video, try -i img/trees.inr (sequence from the MIT).\n" 1.121 + "\t(Type -h for help)"); 1.122 + 1.123 + // Read command line parameters 1.124 + const char 1.125 + *name_i = cimg_option("-i",cimg_imagepath "lena.pgm","Input image or video"), 1.126 + *name_o = cimg_option("-o","","Name of the multiscale analysis output"), 1.127 + *axe_dec = cimg_option("-axe",(char*)NULL,"Perform the multiscale decomposition in just one direction ('x', 'y' or 't')"); 1.128 + const unsigned int 1.129 + s = cimg_option("-s",3,"Scale of decomposition"); 1.130 + 1.131 + const bool help = cimg_option("-h",false,"Display Help"); 1.132 + if(help) exit(0); 1.133 + 1.134 + // Initialize Image Data 1.135 + std::fprintf(stderr," - Load image sequence '%s'...\n",cimg::basename(name_i)); 1.136 + const CImg<float> texture_in(name_i); 1.137 + CImg<float> mask_conv_x, mask_conv_y, mask_conv_t; 1.138 + CImgList<float> res(s, texture_in.dimx(),texture_in.dimy(),texture_in.dimz()); 1.139 + CImgList<float> wav(s,texture_in.dimx(), texture_in.dimy(), texture_in.dimz()); 1.140 + cimglist_for(res,l) { res(l).fill(0.0); wav(l).fill(0.0);} 1.141 + unsigned int i; 1.142 + 1.143 + if (!axe_dec){ 1.144 + // Perform the multiscale decomposition in all directions 1.145 + for(i=0;i<s;i++){ 1.146 + std::fprintf(stderr," - Performing scale %u ...\n",i+1); 1.147 + if(i==0){ res(i) = texture_in;} else { res(i) = res(i-1);} 1.148 + mask_conv_x = mask_x(i+1); 1.149 + res(i) = res(i).get_convolve(mask_conv_x); 1.150 + mask_conv_y = mask_y(i+1); 1.151 + res(i) = res(i).get_convolve(mask_conv_y); 1.152 + mask_conv_t = mask_t(i+1); 1.153 + res(i) = res(i).get_convolve(mask_conv_t); 1.154 + if(i==0){wav(i) = texture_in - res(i);} // res(0) and wav(0) are the 1st scale of decompostion 1.155 + else {wav(i) = res(i-1) - res(i);} 1.156 + } } 1.157 + 1.158 + if (axe_dec) { 1.159 + // Perform the multiscale decomposition in just one direction 1.160 + char c; 1.161 + c = cimg::uncase(axe_dec[0]); 1.162 + fprintf(stderr," - Decompose the image along axe '%c'\n",c); fflush(stdout); 1.163 + 1.164 + switch(c) { 1.165 + case 'x': { 1.166 + for(i=0;i<s;i++) { 1.167 + std::fprintf(stderr," - Performing scale %u ...\n",i+1); 1.168 + if(i==0){ res(i) = texture_in;} else { res(i) = res(i-1);} 1.169 + mask_conv_x = mask_x(i+1); 1.170 + res(i) = res(i).get_convolve(mask_conv_x); 1.171 + if(i==0){wav(i) = texture_in - res(i);} 1.172 + else {wav(i) = res(i-1) - res(i);}}} 1.173 + break; 1.174 + 1.175 + case 'y': { 1.176 + for(i=0;i<s;i++) { 1.177 + std::fprintf(stderr," - Performing scale %u ...\n",i+1); 1.178 + if(i==0){ res(i) = texture_in;} else { res(i) = res(i-1);} 1.179 + mask_conv_y = mask_y(i+1); 1.180 + res(i) = res(i).get_convolve(mask_conv_y); 1.181 + if(i==0){wav(i) = texture_in - res(i);} 1.182 + else {wav(i) = res(i-1) - res(i);}}} 1.183 + break; 1.184 + 1.185 + case 't': { 1.186 + for(i=0;i<s;i++) { 1.187 + std::fprintf(stderr," - Performing scale %u ...\n",i+1); 1.188 + if(i==0){ res(i) = texture_in;} else { res(i) = res(i-1);} 1.189 + mask_conv_t = mask_t(i+1); 1.190 + res(i) = res(i).get_convolve(mask_conv_t); 1.191 + if(i==0){wav(i) = texture_in - res(i);} 1.192 + else {wav(i) = res(i-1) - res(i);}}} 1.193 + break; 1.194 + 1.195 + default: throw CImgException("Error, unknow decompostion axe '%c', try 'x', 'y' or 't'",c); 1.196 + } 1.197 + fputc('\n',stderr); 1.198 + } 1.199 + 1.200 + if (*name_o){ 1.201 + // Save the Multi-Scale Analysis 1.202 + std::fprintf(stderr," - Saving of all output sequences : %s in the msa/ directory... \n",cimg::basename(name_o)); 1.203 + int count = 1; // res0 = original image 1.204 + char filename[256] = "", filename_wav[256] = ""; 1.205 + char STmp[3] = ""; 1.206 + system("mkdir msa"); 1.207 + for(i=0;i<s;i++){ 1.208 + strcpy( filename, "msa/res" ); 1.209 + strcpy( filename_wav, "msa/wav" ); 1.210 + if( count < 10 ) 1.211 + { strcat( filename, "0" );strcat( filename_wav, "0" );} 1.212 + sprintf( STmp, "%d_", count ); 1.213 + strcat( filename, STmp ); strcat( filename_wav, STmp ); 1.214 + strcat( filename,name_o);strcat( filename_wav,name_o); 1.215 + res(i).save(filename); 1.216 + wav(i).save(filename_wav); 1.217 + count++; 1.218 + } 1.219 + } 1.220 + 1.221 + // Result visualization 1.222 + const float value = 255; 1.223 + for(i=0;i<s;i++) { 1.224 + res[i].normalize(0,255).draw_text(2,2,"Scale %d",&value,0,1,11,i); 1.225 + wav[i].normalize(0,255).draw_text(2,2,"Scale %d",&value,0,1,11,i); 1.226 + } 1.227 + 1.228 + CImgDisplay disp(res,"Approximations levels by increasing scale",0); 1.229 + CImgDisplay disp2(wav,"Wavelet coefficients by increasing scale",0); 1.230 + while ( !disp.is_closed && !disp.is_keyQ && !disp.is_keyESC && 1.231 + !disp2.is_closed && !disp2.is_keyQ && !disp2.is_keyESC ) { 1.232 + if (disp.is_resized) disp.resize().display(res); 1.233 + if (disp2.is_resized) disp2.resize().display(wav); 1.234 + CImgDisplay::wait(disp,disp2); 1.235 + } 1.236 + 1.237 + return 0; 1.238 +}