Matrix addition and means

I am trying to take a matrix of any size , whether it has one row or 9, and write a function file that add the each element by its immediate neighbor then average it and replace. So if
a=[1,2,0,1]
the function would produce
ans =
1.5 1 1 .5
here is what I have so far, but for some reason it wont add the edges.
function [ b] = Avg_Num(a )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
[r,c]=size(a);
if (r*c) == 1
b=a;
elseif r ==1
b(1,1)=(a(1,1)+a(1,2))/2;
for j= 2:(c-1)
b(1,j)=(a(1,j)+a(1,j-1)+a(1,j+1))/3;
b(1,max(j)+1)=(a(1,max(j))+a(1,max(j)+1))/2;
end
elseif r >1
b(1,1)=(a(1,1)+a(1,2)+a(2,2)+a(2,1))/4;
b(1,c)=(a(1,c)+a(1,c-1)+a(2,c)+a(2,c-1))/4;
b(r,1)=(a(r,1)+a(r-1,1)+a(r,2)+a(r-1,2))/4;
b(r,c)=(a(r,c)+a(r-1,c)+a(r-1,c-1)+a(r,c-1))/4;
for i=2 :(r-1)
for j=2:(c-1)
b(i,j)=(a(i,j)+a(i+1,j)+a(i-1,j)+a(i,j+1)+a(i,j-1)+a(i-1,j-1)+a(i-1,j+1)+a(i+1,j-1)+a(i+1,j+1))/9;
end
end
end
end
any ideas

1 Comment

How did you get the result from a=[1,2,0,1] ?

Sign in to comment.

Answers (1)

Image Analyst
Image Analyst on 11 Apr 2014
Edited: Image Analyst on 11 Apr 2014
Wow. How would you like to do all that in a single line? If so, how about using convolution:
% First with a 1D "a"
a=[1,2,0,1];
output = conv2(a, [1, 1]/2, 'same')
% Now with a 2D "a" - use a 3 by 3 array to do the scanning.
windowSize = 3
a = magic(windowSize); % Sample data
output = conv2(a, [windowSize, windowSize]/windowSize^2, 'same')

12 Comments

Thats amazing, whats windowSize, I can find it in the help documents in MATLAB.
oh, wait your just naming the matrix right, but whats with the 'same',
Window size is how big you want the window to be. Like 9. It's usually an odd number because you want the output element to be at the center of the window. But it doesn't have to be, you'll just have a half-element shift otherwise.
'same' means that the window travels over the entire array and quits if the scanning widow is not centered over the last element. For example, what if the array was 10 wide and your window was 7 wide. When the center element of the window (#4) is over the last element of your array (#10), it quits. If you use 'valid, it quits when the scanning window's outer edge hits the outer edge of the array its scanning. If it's full, it will go until there are no more overlapping elements. For example the last over lap at 10, when the scanning kernel goes from element 10 to 16, but only the elements at 10 are overlapped. The elements under the kernel that are not part of the original array are assumed to be zero when it does the multiply and add. You need to know how you want to handle it when you have these situations, called "edge effects" or "boundary effects".
As awesome as that is, it is not producing what i need. if
a=[1,1 ,1 ,1 ,1; 1,2,3,1,1; 1,3,6,1,1 8,1,6,2,2; 3,5,7,2,2; 4,9,2,2,2]
b= 1.25,1.5,1.5, 1.33,1;1.5,2.11,2.11,1.777,1.....
so the function is that each element adding it to its immediate neighbor and then averaging it
What is your desired b? Are you doing 4 connected or 8 connected neighbors? In other word, North, south, east and west? Or do you want to include neighbors on the diagonals (NW, NE, SE, SW)? Try this:
a=[1,1 ,1 ,1 ,1;
1,2,3,1,1;
1,3,6,1,1;
8,1,6,2,2;
3,5,7,2,2;
4,9,2,2,2]
% Now with a 2D "a" - use a 3 by 3 array to do the scanning.
windowSize = 3
% 4 connected neighbors.
kernel = [0 1 0; 1 1 1; 0 1 0] / 5; % four connected
output4 = conv2(a, kernel, 'same')
% 8-connected
kernel = [1 1 1; 1 1 1; 1 1 1] / 9; % eight connected
output8 = conv2(a, kernel, 'same')
right it needs to connect all neighbors , north , south, east, west, northeast, southeast, southwest, and northwest
so add the neighbors, avg, then place. a= [1,1,1; 1,2,3; 1,3,6] b= [1.25, 1.5, 1.75; 1.5, 2.111,2.667; 1,75, 2,6667, 3.5]
Yes, that's the 8 connected scenario. If you want different boundary conditions, experiment with 'same', 'valid', and 'full' - they give different size matrices. If you want the "window" to shrink when it gets to the edge, then you need to do things differently than conv2() which has a fixed size window. For example if you're on the last pixel and you want to average just the N,S,NW,W, and SW pixels (a 3 by 2 window) then let me know. It's a little trickier but is possible using sum() twice, so hopefully you don't want to do that. Actually what is your "use case" for this anyway?
thats why I wrote that long function file, but it missed the some numbers and just gives me zero, whic I cant figure out why.
Then do it this way:
a= [1,1,1;
1,2,3;
1,3,6]
output=[1.25 1.50 1.75
1.5 2.11 2.6667
1.75 2.6667 3.5]
sum_Of_a = conv2(a, ones(3), 'same')
count_in_window = conv2(ones(size(a)), ones(3), 'same')
theMean = sum_Of_a ./ count_in_window % Same as "output"
thats amazing, and it works on any size vector. my hat goes off to you.
Thanks for your help
You're welcome. Can you mark the answer as "Accepted" then?

Sign in to comment.

Categories

Asked:

on 11 Apr 2014

Commented:

on 12 Apr 2014

Community Treasure Hunt

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

Start Hunting!