// Frequency-space gaussian deconvolution is pretty simple (outside of the fourier transforms) // Output = fft(filter) * fft(image) / (fft(filter)^2 + weight*fft(gradient filters)^2) Image FFTDeconvolve::apply(Window im, Window filter, float weight) { assert(im.frames == 1, "-fftdeconvolve can only handle single-frame images\n"); assert(filter.frames == 1, "-fftdeconvolve can only handle single-frame filters\n"); assert(filter.channels == 1, "-fftdeconvolve can only handle single-channel filters\n"); // sum of second derivatives filter Image fft_g(im.width, im.height, 1, 2); fft_g(0, 0)[0] = weight; fft_g(im.width-1, 0)[0] = -weight*0.25; fft_g(0, im.height-1,0)[0] = -weight*0.25; fft_g(1, 0)[0] = -weight*0.25; fft_g(0, 1)[0] = -weight*0.25; FFT::apply(fft_g); Image fft_im = RealComplex::apply(im); FFT::apply(fft_im); Image fft_filter(im.width, im.height, 1, 2); for (int y = 0; y < filter.height; y++) { int fy = y - filter.height/2; if (fy < 0) fy += fft_filter.height; for (int x = 0; x < filter.width; x++) { for (int c = 0; c < filter.channels; c++) { int fx = x - filter.width/2; if (fx < 0) fx += fft_filter.width; fft_filter(fx, fy)[2*c] = filter(x, y)[c]; } } } FFT::apply(fft_filter); ComplexMultiply::apply(fft_im, fft_filter, true); ComplexMultiply::apply(fft_filter, fft_filter, true); Add::apply(fft_filter, fft_g); ComplexDivide::apply(fft_im, fft_filter, false); IFFT::apply(fft_im); return ComplexReal::apply(fft_im); }
static void process (Mat const &src, Mat &dst) { fft_filter (src, frequency_filter, NULL, &dst); }