im = imread('lenna.png');
imshow(im);
m = [2 1 0; 1 0 -1; 0 -1 -2] % a diagonal edge detection mask
im = rgb2gray(im);
im = im2double(im);
General convolution algorithm
The standard way to do a convolution in most languages, using nested loops. This is very slow in Matlab, largely because of array bounds checking.
Note that the +nmr +nmc in the index calculation for im are there only because the output array starts at (1,1). They would be omitted in a language that supported general array bounds.
[nxr, nxc] = size(im); % nxr: number of im rows, etc.
[nmr, nmc] = size(m);
nyr = nxr - nmr + 1; % get valid output region
nyc = nxc - nmc + 1;
y1 = zeros(nyr, nyc); % preallocate output array
tic
for yr = 1:nyr % loop over output elements
for yc = 1:nyc
sum = 0;
for mr = 1:nmr % loop over mask elements
for mc = 1:nmc
sum = sum + im(yr-mr+nmr, yc-mc+nmc) * m(mr, mc);
end
end
y1(yr, yc) = sum; % store result
end
end
toc
imshow(y1, []); % show final result
Better code in Matlab
A better way of doing it in Matlab, but without using a library function. This does all the multiplications for each mask element together, adding them together a whole array at a time. It's much faster in this language, and gives the same results, as you can see from the final line of the calculation.
This is the kind of method you might employ with parallel processing hardware, if it is available. The key to understanding this is to realise that xpart is a shifted copy of the original input, which is multiplied by one mask element and added in to the output. You need to understand how the : operator in Matlab lets you get a subarray.
[nxr, nxc] = size(im); % nxr: number of im rows, etc.
[nmr, nmc] = size(m);
nyr = nxr - nmr + 1; % get valid output region
nyc = nxc - nmc + 1;
y2 = zeros(nyr, nyc); % preallocate output array
tic
for mr = 1:nmr % loop over mask elements
for mc = 1:nmc
xpart = im(nmr-mr+1:nxr-mr+1, nmc-mc+1:nxc-mc+1);
y2 = y2 + xpart * m(mr, mc);
end
end
toc
% Compare final result
max_difference = max(max(abs(y2-y1)))
Using Matlab's built-in function
This is the standard Matlab function. Again, it returns the same answer. It's faster still. Note that tic and toc probably aren't giving very accurate reports now, as the time elapsed is very small, and they measure clock time rather than CPU time.
ticy3 = conv2(im, m, 'valid'); % Mask is SECOND argumenttocmax_difference = max(max(abs(y3-y1)))