How can I create and apply a Gaussian filter in MATLAB without using fspecial, imfilter, or conv2?

I have the following code in MATLAB:

I=imread(image);
h=fspecial('gaussian',si,sigma);
I=im2double(I);
I=imfilter(I,h,'conv');
figure,imagesc(I),impixelinfo,title('Original Image after Convolving with gaussian'),colormap('gray');

      

How can I define and apply a Gaussian filter to an image without imfilter

, fspecial

and conv2

?

+3


source to share


1 answer


It's a shame that you cannot use some of the built-in methods from the Image Processing Toolbox to help you accomplish this task. However, we can still do what you ask, although it will be a little more difficult. I'm still going to use some of the features from IPT to help us do what you ask. Also, I'm going to assume that your image is shades of gray . I'll leave it to you if you want to do this for color images.




Create gaussian mask

What you can do is create a 2D spatial coordinate grid using a meshgrid

size equal to the mass of the Gaussian filter you are creating. I guess it's N

weird to make my life easier. This will allow the spatial coordinates to be symmetrical across the entire mask.

If you remember, 2D Gauss can be defined as:

The scaling factor before the exponent is primarily concerned with ensuring that the area under the gaussian is 1. We will deal with this normalization in a different way, where we generate gaussian coefficients without a scaling factor, and then simply sum all the coefficients in the mask and divide each element by this amount to provide a unit area.

Assuming you want to create a filter N x N

and with a given standard deviation sigma

, the code would look something like this: h

representing your Gaussian filter.

%// Generate horizontal and vertical co-ordinates, where
%// the origin is in the middle
ind = -floor(N/2) : floor(N/2);
[X Y] = meshgrid(ind, ind);

%// Create Gaussian Mask
h = exp(-(X.^2 + Y.^2) / (2*sigma*sigma));

%// Normalize so that total area (sum of all weights) is 1
h = h / sum(h(:));

      

If you test this with fspecial

, for odd values, N

you will see that the masks are the same.




Filter Image

Image Filtering Basics For every pixel in your input image, you take a pixel neighborhood that surrounds that pixel, which is the same size as your Gaussian mask. You are performing a stepwise multiplication on this area of โ€‹โ€‹pixels with a gaussian mask and sum all the elements together. The resulting sum is that the output pixel will be at the corresponding spatial location in the output image. I am going to use im2col

that will use pixel neighborhoods and turn them into columns. im2col

will take each of these columns and create a matrix where each column represents one pixel region.

What we can do next is take a gaussian mask and convert to a column vector. We'll then take that column vector and replicate that across as many columns as we get from the result im2col

to create ... let's call this Gaussian matrix for lack of a better term. With this Gaussian matrix, we will do the elementwise multiplication with this matrix and with the output im2col

. Once we have done that, we can sum all the rows for each column. The best way to do this stepwise multiplication is through bsxfun

, and I'll show you how to use it shortly.

This will result in your filtered image, but it will be one vector. You will need to rearrange this vector back to matrix form with col2im

in order to get the filtered image. However, a small problem with this approach is that it does not filter pixels where the spatial mask goes beyond the image dimensions. So, in fact, you need to fill the border of your image with zeros so that we can correctly execute our filter. We can do this with padarray

.

So our code will look something like this, navigating to your variables above:

N = 5; %// Define size of Gaussian mask
sigma = 2; %// Define sigma here

%// Generate Gaussian mask
ind = -floor(N/2) : floor(N/2);
[X Y] = meshgrid(ind, ind);
h = exp(-(X.^2 + Y.^2) / (2*sigma*sigma));
h = h / sum(h(:));

%// Convert filter into a column vector
h = h(:);

%// Filter our image
I = imread(image);
I = im2double(I);
I_pad = padarray(I, [floor(N/2) floor(N/2)]);
C = im2col(I_pad, [N N], 'sliding');
C_filter = sum(bsxfun(@times, C, h), 1);
out = col2im(C_filter, [N N], size(I_pad), 'sliding');

      




out

contains the filtered image after applying a Gaussian masking mask to your input image I

. As an example, let's say N = 9, sigma = 4

. Let's also use cameraman.tif

that is an image of that part of the MATLAB system path. Using the above parameters as well as the image, this is the input and output image we get:

enter image description here

enter image description here

+21


source







All Articles