turingcomplete
turingcomplete

Reputation: 2188

3x3 Average filter in matlab

I've written code to smooth an image using a 3x3 averaging filter, however the output is strange, it is almost all black. Here's my code.

function [filtered_img] = average_filter(noisy_img)
    [m,n] = size(noisy_img);
    filtered_img = zeros(m,n);
    for i = 1:m-2
        for j = 1:n-2
            sum = 0;
            for k = i:i+2
                for l = j:j+2
                    sum = sum+noisy_img(k,l);
                end
            end
            filtered_img(i+1,j+1) = sum/9.0;
        end
    end
end

I call the function as follows:

img=imread('img.bmp');
filtered = average_filter(img);
imshow(uint8(filtered));

I can't see anything wrong in the code logic so far, I'd appreciate it if someone can spot the problem.

Upvotes: 3

Views: 32152

Answers (6)

Zizy Archer
Zizy Archer

Reputation: 1390

Tangentially to the question:

Especially for 5x5 or larger window you can consider averaging first in one direction and then in the other and you save some operations. So, point at 3 would be (P1+P2+P3+P4+P5). Point at 4 would be (P2+P3+P4+P5+P6). Divided by 5 in the end. So, point at 4 could be calculated as P3new + P6 - P2. Etc for point 5 and so on. Repeat the same procedure in other direction. Make sure to divide first, then sum.

I would need to time this, but I believe it could work a bit faster for larger windows. It is sequential per line which might not seem the best, but you have many lines where you can work in parallel, so it shouldn't be a problem.

This first divide, then sum also prevents saturation if you have integers, so you might use the approach even in 3x3 case, as it is less wrong (though slower) to divide twice by 3 than once by 9. But note that you will always underestimate final value with that, so you might as well add a bit of bias (say all values +1 between the steps).

Upvotes: 0

alam
alam

Reputation: 1

Implement neighborhood operation of sum of product operation between an image and a filter of size 3x3, the filter should be averaging filter. Then use the same function/code to compute Laplacian(2nd order derivative, prewitt and sobel operation(first order derivatives). Use a simple 10*10 matrix to perform these operations need matlab code

Upvotes: 0

savith Satheesh
savith Satheesh

Reputation: 1

img=imread('camraman.tif');
nsy-img=imnoise(img,'salt&pepper',0.2);
imshow('nsy-img');
h=ones(3,3)/9;
avg=conv2(img,h,'same');
imshow(Unit8(avg));

Upvotes: -1

Rasman
Rasman

Reputation: 5359

Assuming you're working with grayscal images, you should replace the inner two for loops with :

filtered_img(i+1,j+1) = mean2(noisy_img(i:i+2,j:j+2));

Does it change anything?

EDIT: don't forget to reconvert it to uint8!!

filtered_img = uint8(filtered_img);

Edit 2: the reason why it's not working in your code is because sum is saturating at 255, the upper limit of uint8. mean seems to prevent that from happening

Upvotes: 10

Serg
Serg

Reputation: 14098

img = imread('img.bmp');
filtered = imfilter(double(img), ones(3) / 9, 'replicate');
imshow(uint8(filtered));

Upvotes: 2

bla
bla

Reputation: 26069

another option:

 f = @(x) mean(x(:));
 filtered_img = nlfilter(noisy_img,[3 3],f);

Upvotes: 2

Related Questions