MATLAB Answers

0

Custom Image Spatial Filtering Code using loops not giving the same result as using the built in imtransform() function

Asked by Joshua Kearney on 12 Jun 2018
Latest activity Edited by Anton Semechko on 12 Jun 2018
Hi, I'm working on trying to create a custom code to apply spatial filtering without Matlab functions for school. So I created a custom convolution function to be applied to an image and a kernel but the resultant image looks different for both of these images and I'm hitting a wall with why. My custom code is more blurred and I think my convolution function is incorrect but to me, it looks like I'm applying the equation correctly.
Any help would be appreciated. Thanks.
clear all; close all; clc;
% Read images 1 and 2
im = imread('img1.png');
A = rgb2gray(im);
% Read Kernels
Kernel_1 = (1/9)*ones(3);
Kernel_2 = (1/49)*ones(7);
Kernel = Kernel_2; % Set current kernel
img_out = convolution(A,Kernel); %Perform convolution on image and selected kernel
img_out_filter = imfilter(A,Kernel,'same','conv');
%%Display output images
subplot(1,3,1); imshow(A); title('Original')
subplot(1,3,2); imshow(img_out,[]); title('Custom Created Function')
subplot(1,3,3); imshow(img_out_filter); title('Matlab imfilter Function')
%%Rotate input matrix
function rot_mat = rot(mat,theta)
theta = -25 *2*pi/360;
R = [cos(theta) sin(theta) 0;
-sin(theta) cos(theta) 0;
0 0 1];
rot_mat = mat*R;
end
%%Perform convolution on image and kernel
function B = convolution(A, k)
[ky, kx] = size(k); % Read kernel size
im_pad = padarray(A, [kx ky]); % Pad original image
[y, x] = size(im_pad); % Read image size
B = zeros(x,y); % Create empty matrix to store output image
kr = rot90(k); % Rotates kernel 180 deg for convolution
kr = rot90(kr);
for i=(1+ky):(y-ky) % index through each image row
for j=(1+kx):(x-kx) % index through each image pixel
neigh = im_pad(i-floor(ky/2):i+floor(ky/2), j-floor(kx/2):j+floor(kx/2)); % Create local neighborhood of image
accumulator = 0;
for u=1:ky % index through each kernel row
for v=1:kx % index through each kernel element
if(i>ky && i<y-ky && j>kx && j<y-kx)
temp = neigh(u,v)*kr(u,v);
accumulator = accumulator + temp;
end
end
end
B(i,j) = accumulator; %Set value of pixel in new image with convolution operation resultant
end
end
B=B(1+ky:y-ky,1+kx:x-kx); % Remove image padding
end

  0 Comments

Sign in to comment.

1 Answer

Answer by Anton Semechko on 12 Jun 2018
Edited by Anton Semechko on 12 Jun 2018
 Accepted Answer

Actually, both your 'convolution' function and built-in 'imfilter' function produce very similar results. The discrepancy you were observing was due to the fact that you forgot to cast A (the image) into double format before filtering. Here is the corrected part of your code.
% Read images 1 and 2
im = imread('img1.png');
A = rgb2gray(im);
A = double(A);
% Read Kernels
Kernel_1 = (1/9)*ones(3);
Kernel_2 = (1/49)*ones(7);
Kernel = Kernel_2; % Set current kernel
img_out = convolution(A,Kernel); %Perform convolution on image and selected kernel
img_out_filter = imfilter(A,Kernel,'same','conv');
%%Display output images
figure('color','w')
subplot(1,3,1); imshow(A,[]); title('Original')
subplot(1,3,2); imshow(img_out,[]); title('Custom Created Function')
subplot(1,3,3); imshow(img_out_filter,[]); title('Matlab imfilter Function')

  3 Comments

Thanks, that makes sense. Casting it with double made it work great! Cheers.
Glad I could help. You did a good job with your implementation of 2D convolution.
Also note that there is not need to reflect the filtering kernel if its radially symmetric, like it is in your case.

Sign in to comment.