How Do I Create a Mean Filtered Image using For Loops?

3 views (last 30 days)
My code is the one above. I am having trouble figuring out what I am doing wrong in particular. It just outputs the same image it received.
Now, some things to explain. I was specifically told not to worry about edge elements that can not be covered by the whole mean filter; hence the modulus if-statements to specify the for-loop range. So, my code was meant to just pick the middle value, starting at [row 2, column 2], and then replace the surrounding [3 x 3] elements (inclusive) in the tempArray with the generated mean value.
Am I over-simplifying how to find the mean? Is the reason that it is not carrying over because it is a for loop, and therefore not in the same scope? What am I doing wrong? How would I fix these issues?
  2 Comments
Matt J
Matt J on 21 Oct 2023
We can't copy/paste your code (because it's an image).
Aiden
Aiden on 21 Oct 2023
I am sorry about that! In the future, I will attach a file of my code as well for questions.
I was simply panicking because this is a part of a project that I need to get through, and I forgot to consider how difficult it would be to re-type.

Sign in to comment.

Accepted Answer

Voss
Voss on 21 Oct 2023
[gRow, gCol, ~] = size(grayImg);
gRow and gCol are non-negative scalar integers.
if mod(gRow, 3) < 3
mod(_,3) of something will be 0, 1, or 2, i.e., always less than 3, so this if condition is always true.
Later you use length(gRow) and length(gCol) to define your for loops. Both lengths are 1 since gRow and gCol are scalars.
So this:
for r = 2:3:(length(gRow) - cRow)
for c = 2:3:(length(gCol) - cCol)
is the same as this:
for r = 2:3:(1 - cRow)
for c = 2:3:(1 - cCol)
Given that cRow can be 0, 1, or 2, then 1-cRow will be 1, 0, or -1 (same for cCol), so those vectors that start with 2 are always empty
2:3:1
ans = 1×0 empty double row vector
2:3:0
ans = 1×0 empty double row vector
2:3:-1
ans = 1×0 empty double row vector
so your for loops never iterate. That's the reason why you always get the same image back.
For the code inside the loops, it can written more simply as:
mn = mean(greyImg(r-1:r+1,c-1:c+1),'all');
tempArray(r-1:r+1,c-1:c+1) = mn;
That is, you don't have to reference each element individually, and you don't need to use deal to assign the result. More succintly would be to get rid of the temporary variable mn and say:
tempArray(r-1:r+1,c-1:c+1) = mean(greyImg(r-1:r+1,c-1:c+1),'all');
  2 Comments
Aiden
Aiden on 21 Oct 2023
Thank you, I did not know if I could use row-column indexing this way and did not know how to try.
Also, your explanation of what I did wrong was fantastic and told me exactly what I needed to know. The simplification of code was also quite helpful and you are very appreciated.

Sign in to comment.

More Answers (2)

DGM
DGM on 21 Oct 2023
Edited: DGM on 21 Oct 2023
There are a bunch of examples of basic sliding window (and probably blockwise) filters on the forum. I don't have my bookmarks with me, so:
In practice, you'd use imfilter() or blockproc() depending on your intent, but I assume this is homework and you're supposed to avoid those.
For this case, here's a start
% single channel, uint8
grayImg = imread('cameraman.tif');
[gRow,gCol,~] = size(grayImg);
tempArray = grayImg;
% these are some problems:
% mod(x,n) is always <n, so these if-statements don't do anything
% if mod(gRow,3) < 3
% cRow = mod(gRow,3);
% else
% cRow = 0;
% end
%
% if mod(gCol,3) < 3
% cCol = mod(gCol,3);
% else
% cCol = 0;
% end
%
% gRow,gCol are scalar, so its length is always 1
% consequently, the loop doesn't increment as expected
%for r = 2:3:(length(gRow) - cRow)
% for c = 2:3:(length(gCol) - cCol)
% this is a blockwise filter
for r = 2:3:floor(gRow/3)*3 - 1
for c = 2:3:floor(gCol/3)*3 - 1
% good gravy, i'm not retyping all that
mn = sum(grayImg(r-1:r+1,c-1:c+1),'all')/9;
% i think this is what you meant to do?
tempArray(r-1:r+1,c-1:c+1) = mn;
end
end
imshow(tempArray,'border','tight')
% maybe you wanted a regular sliding-window filter instead?
for r = 2:gRow-1
for c = 2:gCol-1
% good gravy, i'm not retyping all that.
mn = sum(grayImg(r-1:r+1,c-1:c+1),'all')/9;
% i think this is what you meant to do?
tempArray(r-1:r+1,c-1:c+1) = mn;
end
end
imshow(tempArray,'border','tight')
  4 Comments
Aiden
Aiden on 21 Oct 2023
Really? It won't let me, it just says "Accept Answer" and then the option to do so on every other question dissappeared once I clicked one.
Aiden
Aiden on 21 Oct 2023
I see, never mind. I upvoted you, enjoy your day!

Sign in to comment.


Matt J
Matt J on 21 Oct 2023
Edited: Matt J on 21 Oct 2023
grayImg=reshape(1:49,7,7)
grayImg = 7×7
1 8 15 22 29 36 43 2 9 16 23 30 37 44 3 10 17 24 31 38 45 4 11 18 25 32 39 46 5 12 19 26 33 40 47 6 13 20 27 34 41 48 7 14 21 28 35 42 49
[m,n]=size(grayImg);
dm=repmat(3,1,ceil(m/3)); dm(end)=dm(end)-(sum(dm)-m);
dn=repmat(3,1,ceil(n/3)); dn(end)=dn(end)-(sum(dn)-n);
Blocks=mat2cell(grayImg,dm,dn);
for i=1:numel(Blocks)
if numel(Blocks{i})==9
Blocks{i}(:)=mean(Blocks{i}(:));
end
end
meanFltImg=cell2mat(Blocks)
meanFltImg = 7×7
9 9 9 30 30 30 43 9 9 9 30 30 30 44 9 9 9 30 30 30 45 12 12 12 33 33 33 46 12 12 12 33 33 33 47 12 12 12 33 33 33 48 7 14 21 28 35 42 49

Products


Release

R2023b

Community Treasure Hunt

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

Start Hunting!