in lear_gist-1.2/gist.c [286:415]
/*static*/ void prefilt(image_t *src, int fc)
{
fftw_lock();
int i, j;
/* Log */
for(j = 0; j < src->height; j++)
{
for(i = 0; i < src->width; i++) {
src->data[j*src->stride+i] = log(src->data[j*src->stride+i]+1.0f);
}
}
image_t *img_pad = image_add_padding(src, 5);
/* Get sizes */
int width = img_pad->width;
int height = img_pad->height;
int stride = img_pad->stride;
/* Alloc memory */
float *fx = (float *) fftwf_malloc(width*height*sizeof(float));
float *fy = (float *) fftwf_malloc(width*height*sizeof(float));
float *gfc = (float *) fftwf_malloc(width*height*sizeof(float));
fftwf_complex *in1 = (fftwf_complex *) fftwf_malloc(width*height*sizeof(fftwf_complex));
fftwf_complex *in2 = (fftwf_complex *) fftwf_malloc(width*height*sizeof(fftwf_complex));
fftwf_complex *out = (fftwf_complex *) fftwf_malloc(width*height*sizeof(fftwf_complex));
/* Build whitening filter */
float s1 = fc/sqrt(log(2));
for(j = 0; j < height; j++)
{
for(i = 0; i < width; i++)
{
in1[j*width + i][0] = img_pad->data[j*stride+i];
in1[j*width + i][1] = 0.0f;
fx[j*width + i] = (float) i - width/2.0f;
fy[j*width + i] = (float) j - height/2.0f;
gfc[j*width + i] = exp(-(fx[j*width + i]*fx[j*width + i] + fy[j*width + i]*fy[j*width + i]) / (s1*s1));
}
}
fftshift(gfc, width, height);
/* FFT */
fftwf_plan fft1 = fftwf_plan_dft_2d(width, height, in1, out, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_unlock();
fftwf_execute(fft1);
fftw_lock();
/* Apply whitening filter */
for(j = 0; j < height; j++)
{
for(i = 0; i < width; i++)
{
out[j*width+i][0] *= gfc[j*width + i];
out[j*width+i][1] *= gfc[j*width + i];
}
}
/* IFFT */
fftwf_plan ifft1 = fftwf_plan_dft_2d(width, height, out, in2, FFTW_BACKWARD, FFTW_ESTIMATE);
fftw_unlock();
fftwf_execute(ifft1);
fftw_lock();
/* Local contrast normalisation */
for(j = 0; j < height; j++)
{
for(i = 0; i < width; i++)
{
img_pad->data[j*stride + i] -= in2[j*width+i][0] / (width*height);
in1[j*width + i][0] = img_pad->data[j*stride + i] * img_pad->data[j*stride + i];
in1[j*width + i][1] = 0.0f;
}
}
/* FFT */
fftwf_plan fft2 = fftwf_plan_dft_2d(width, height, in1, out, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_unlock();
fftwf_execute(fft2);
fftw_lock();
/* Apply contrast normalisation filter */
for(j = 0; j < height; j++)
{
for(i = 0; i < width; i++)
{
out[j*width+i][0] *= gfc[j*width + i];
out[j*width+i][1] *= gfc[j*width + i];
}
}
/* IFFT */
fftwf_plan ifft2 = fftwf_plan_dft_2d(width, height, out, in2, FFTW_BACKWARD, FFTW_ESTIMATE);
fftw_unlock();
fftwf_execute(ifft2);
fftw_lock();
/* Get result from contrast normalisation filter */
for(j = 0; j < height; j++)
{
for(i = 0; i < width; i++) {
img_pad->data[j*stride+i] = img_pad->data[j*stride + i] / (0.2f+sqrt(sqrt(in2[j*width+i][0]*in2[j*width+i][0]+in2[j*width+i][1]*in2[j*width+i][1]) / (width*height)));
}
}
image_rem_padding(src, img_pad, 5);
/* Free */
fftwf_destroy_plan(fft1);
fftwf_destroy_plan(fft2);
fftwf_destroy_plan(ifft1);
fftwf_destroy_plan(ifft2);
image_delete(img_pad);
fftwf_free(in1);
fftwf_free(in2);
fftwf_free(out);
fftwf_free(fx);
fftwf_free(fy);
fftwf_free(gfc);
fftw_unlock();
}