How to convolve two matrices with different sizes?

16 views (last 30 days)
I would like to filter a 2D image with a Gaussian by convolving them. The convolution must be done without using conv, conv2 ... functions.
The matrix image is not squared.
How could I implement this convolution?
Thanks in advanced
Help ASAP
  5 Comments
Andrea Herranz Bernardino
Thank you very much. Now I understand how the convolution works for 2D using the following code:
Nevertheless, could you be able to explain me what Rep is used for? It is not very clear for me :(
Tremendous thanks. You will save my life
The code is copied below:
function B = convolve(A, k);
[r c] = size(A);
[m n] = size(k);
h = rot90(k, 2);
center = floor((size(h)+1)/2);
left = center(2) - 1;
right = n - center(2);
top = center(1) - 1;
bottom = m - center(1);
Rep = zeros(r + top + bottom, c + left + right);
for x = 1 + top : r + top
for y = 1 + left : c + left
Rep(x,y) = A(x - top, y - left);
end
end
B = zeros(r , c);
for x = 1 : r
for y = 1 : c
for i = 1 : m
for j = 1 : n
q = x - 1;
w = y -1;
B(x, y) = B(x, y) + (Rep(i + q, j + w) * h(i, j));
end
end
end
end
Jonas
Jonas on 3 May 2021
Edited: Jonas on 3 May 2021
Rep is you original image which is padded with 0 on all four sides of the image. it is padded about half height of k at bottom and top and about half width of k at the left and right. this is necessary because when you convolve, your signals become bigger compared to the original. it just like in 1d convolution if you convolve e.g. [1 2 3 4] with [3 8 5] the resulting signal will have length 6 which is longer than both input signals.

Sign in to comment.

Answers (1)

DGM
DGM on 3 May 2021
There's no reason to be looping over the kernel like that. Let's say you wanted to replicate the behavior of conv2:
inpict = im2double(rgb2gray(imread('peppers.png')));
fk=fkgen('gaussian',20); % filter kernel
example=conv2(inpict,fk); % example to test against
% get sizes
s0 = [size(inpict,1) size(inpict,2)];
sfk = [size(fk,1) size(fk,2)];
s = s0 + 2*(sfk-1);
% pad the array with zeros
padded = zeros(s);
padded(sfk(1):(end-sfk(1)+1),sfk(2):(end-sfk(2)+1)) = inpict;
% flip the kernel (this is convolution, not correlation)
fk = rot90(fk,2);
fk = fk(:);
% preallocate full-size output
% by default, conv2 does the same
outpict = zeros(sfk(1)+s0(1)-1,s0(2)+sfk(2)-1);
for m = 1:s(1)-sfk(1)+1
for n = 1:s(2)-sfk(2)+1
sample = padded(m:m+sfk(1)-1,n:n+sfk(2)-1);
outpict(m,n) = sample(:)'*fk;
end
end
% measure error between our method and conv2
immse(example,outpict)
If instead you wanted to work a bit more like imfilter(), there are some considerations
  • By default, imfilter() zero-pads, but this causes vingetting. It's often desirable to use edge replication instead. You could use padarray() to do either.
  • By default, imfilter() uses correlation, so the filter isn't rotated. For symmetric filters, there isn't a difference, but it's something to keep in mind if compatibility matters.
  • By default, imfilter() returns the central area equal to the original image geometry. You'd just have to change the range of indices your filter slides over to change the output array. Otherwise you can just convolve the whole thing and crop off the excess.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!