Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00025 #include <stdlib.h>
00026 #include <math.h>
00027 #include <float.h>
00028
00029 #include <fftw3.h>
00030
00031 #include "retinex_pde_lib.h"
00032
00033
00034 #ifndef M_PI
00035
00036 #define M_PI 3.14159265358979323846
00037 #endif
00038
00039
00040
00041
00042
00043
00044
00071 static float *discrete_laplacian_threshold(float *data_out,
00072 const float *data_in,
00073 size_t nx, size_t ny, float t)
00074 {
00075 size_t i, j;
00076 float *ptr_out;
00077 float diff;
00078
00079 const float *ptr_in, *ptr_in_xm1, *ptr_in_xp1, *ptr_in_ym1, *ptr_in_yp1;
00080
00081
00082 if (NULL == data_in || NULL == data_out) {
00083 fprintf(stderr, "a pointer is NULL and should not be so\n");
00084 abort();
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094 ptr_in = data_in;
00095 ptr_in_xm1 = data_in - 1;
00096 ptr_in_xp1 = data_in + 1;
00097 ptr_in_ym1 = data_in - nx;
00098 ptr_in_yp1 = data_in + nx;
00099 ptr_out = data_out;
00100
00101 for (j = 0; j < ny; j++) {
00102 for (i = 0; i < nx; i++) {
00103 *ptr_out = 0.;
00104
00105 if (0 < i) {
00106 diff = *ptr_in - *ptr_in_xm1;
00107 if (fabs(diff) > t)
00108 *ptr_out += diff;
00109 }
00110 if (nx - 1 > i) {
00111 diff = *ptr_in - *ptr_in_xp1;
00112 if (fabs(diff) > t)
00113 *ptr_out += diff;
00114 }
00115
00116 if (0 < j) {
00117 diff = *ptr_in - *ptr_in_ym1;
00118 if (fabs(diff) > t)
00119 *ptr_out += diff;
00120 }
00121 if ( ny - 1 > j) {
00122 diff = *ptr_in - *ptr_in_yp1;
00123 if (fabs(diff) > t)
00124 *ptr_out += diff;
00125 }
00126 ptr_in++;
00127 ptr_in_xm1++;
00128 ptr_in_xp1++;
00129 ptr_in_ym1++;
00130 ptr_in_yp1++;
00131 ptr_out++;
00132 }
00133 }
00134
00135 return data_out;
00136 }
00137
00147 static double *cos_table(size_t size)
00148 {
00149 double *table = NULL;
00150 double *ptr_table;
00151 size_t i;
00152
00153
00154 if (NULL == (table = (double *) malloc(sizeof(double) * size))) {
00155 fprintf(stderr, "allocation error\n");
00156 abort();
00157 }
00158
00159
00160
00161
00162
00163 ptr_table = table;
00164 for (i = 0; i < size; i++)
00165 *ptr_table++ = cos((M_PI * i) / size);
00166
00167 return table;
00168 }
00169
00190 static float *retinex_poisson_dct(float *data, size_t nx, size_t ny, double m)
00191 {
00192 float *ptr_data;
00193 double *cosi = NULL, *cosj = NULL;
00194 double *ptr_cosi, *ptr_cosj;
00195 size_t i, j;
00196 double m2;
00197
00198
00199
00200
00201
00202
00203 cosi = cos_table(nx);
00204 cosj = cos_table(ny);
00205
00206
00207
00208
00209
00210
00211 m2 = m / 2.;
00212 ptr_data = data;
00213 ptr_cosi = cosi;
00214 ptr_cosj = cosj;
00215
00216
00217
00218
00219
00220 *ptr_data++ = 0.;
00221 ptr_cosi++;
00222
00223 for (i = 1; i < nx; i++)
00224 *ptr_data++ *= m2 / (2. - *ptr_cosi++ - *ptr_cosj);
00225 ptr_cosj++;
00226 ptr_cosi = cosi;
00227
00228 for (j = 1; j < ny; j++) {
00229 for (i = 0; i < nx; i++)
00230 *ptr_data++ *= m2 / (2. - *ptr_cosi++ - *ptr_cosj);
00231 ptr_cosj++;
00232 ptr_cosi = cosi;
00233 }
00234
00235 free(cosi);
00236 free(cosj);
00237 return data;
00238 }
00239
00240
00241
00242
00243
00268 float *retinex_pde(float *data, size_t nx, size_t ny, float t)
00269 {
00270 fftwf_plan dct_fw, dct_bw;
00271 float *data_fft, *data_tmp;
00272
00273
00274
00275
00276
00277
00278 if (NULL == data) {
00279 fprintf(stderr, "a pointer is NULL and should not be so\n");
00280 abort();
00281 }
00282
00283
00284 #ifdef FFTW_NTHREADS
00285 if (0 == fftwf_init_threads()) {
00286 fprintf(stderr, "fftw initialisation error\n");
00287 abort();
00288 }
00289 fftwf_plan_with_nthreads(FFTW_NTHREADS);
00290 #endif
00291
00292
00293 if (NULL == (data_fft = (float *) malloc(sizeof(float) * nx * ny))
00294 || NULL == (data_tmp = (float *) malloc(sizeof(float) * nx * ny))) {
00295 fprintf(stderr, "allocation error\n");
00296 abort();
00297 }
00298
00299
00300
00301
00302
00303
00304 (void) discrete_laplacian_threshold(data_tmp, data, nx, ny, t);
00305
00306 dct_fw = fftwf_plan_r2r_2d((int) ny, (int) nx,
00307 data_tmp, data_fft,
00308 FFTW_REDFT10, FFTW_REDFT10,
00309 FFTW_ESTIMATE | FFTW_DESTROY_INPUT);
00310 fftwf_execute(dct_fw);
00311 free(data_tmp);
00312
00313
00314
00315 (void) retinex_poisson_dct(data_fft, nx, ny, 1. / (double) (nx * ny));
00316
00317
00318 dct_bw = fftwf_plan_r2r_2d((int) ny, (int) nx,
00319 data_fft, data,
00320 FFTW_REDFT01, FFTW_REDFT01,
00321 FFTW_ESTIMATE | FFTW_DESTROY_INPUT);
00322 fftwf_execute(dct_bw);
00323
00324
00325 fftwf_destroy_plan(dct_fw);
00326 fftwf_destroy_plan(dct_bw);
00327 fftwf_free(data_fft);
00328 fftwf_cleanup();
00329 #ifdef FFTW_NTHREADS
00330 fftwf_cleanup_threads();
00331 #endif
00332 return data;
00333 }