In order to compute the linear convolution using DFT, you need to post-pad both signals with zeros, otherwise the result would be the circular convolution. You don't have to manually pad a signal though,
fft2
can do it for you if you add additional parameters to the function call, like so:fft2(X, M, N)
This pads (or truncates) signal
X
to create an M-by-N signal before doing the transform.
Pad each signal in each dimension to a length that equals the sum of the lengths of both signals, that is:M = size(im, 1) + size(mask, 1); N = size(im, 2) + size(mask, 2);
Just for good practice, instead of:
b = 1 / 16 * [1 1 1 1; 1 1 1 1; 1 1 1 1; 1 1 1 1];
you can write:
b = ones(4) / 16;
Anyway, here's the fixed code (I've generated a random image just for the sake of the example):
im = fix(255 * rand(500)); % # Generate a random image
mask = ones(4) / 16; % # Mask
% # Circular convolution
resConv = conv2(im, mask);
% # Discrete Fourier transform
M = size(im, 1) + size(mask, 1);
N = size(im, 2) + size(mask, 2);
resIFFT = ifft2(fft2(im, M, N) .* fft2(mask, M, N));
resIFFT = resIFFT(1:end-1, 1:end-1); % # Adjust dimensions
% # Check the difference
max(abs(resConv(:) - resIFFT(:)))
The result you should get is supposed to be zero:
ans =
8.5265e-014
Close enough.