How to calculate the mean of all neighbouring elements in a matrix
59 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Hello, I have a m x n matrix and I want tot calculate the mean for every element and all its neighbouring values (horizontal, vertical, diagonal). Here I also want to consider the number of neighbours an element has dependent on its position. With matrix M = [3,4,8,6;1,6,9,0;2,5,7,1], M(1,1) should only have 3 neighbours, M(1,2) 5 neigbours and M(2,2) 8 neighbours.
How can I implement a function to calculate the mean of all neighbouring elements with using the matrix positions i,j which represents the rows and column values of the matrix. So M(i,j-1) should be the left element, M(i,j+1) the right element, M(i+1,j) the upper element, M(i-1) the lower element, M(i-1,j-1) the south-west element and so on.
The result should be saved in a new matrix. Should I use a nested for-loop to achieve this?
0 comentarios
Respuestas (2)
John D'Errico
el 16 de Ag. de 2022
Editada: John D'Errico
el 16 de Ag. de 2022
This is actually trivially easy to solve, using a nice trick that is well worth remembering. (Note that this is a great trick that has worked for me in multiple places. For example, you can use it to write a simple code for the game of life.) I'll use my own matrix for the example, so we can see how it works.
A = magic(7)
Now we wish to compute the mean of 3x3 blocks of the matrix. But near the edges, we have fewer neighbors. In a corner, even fewer neighbors yet. So what can we do? First, we will use convolution, but we do so in a tricky way. I'll do so here for the 2-dimensional problem, but higher dimensional problems would work just as nicely, because we can use convn.
K = ones(3,3); % the convolution kernel, indicating a 3x3 moving mean
Amean = conv2(A,K,'same')./conv2(ones(size(A)),K,'same')
Why did this work? Perhaps we need to look at the pieces. What did this do?
conv2(A,K,'same')
So that just adds up all of the elements in the vicinity of any original element in A.
conv2(ones(size(A)),K,'same')
Do you see how this works? It counted the number of terms in the sum. Essentially, it counts up the number of elements that were added to form the sum in the first call to conv2. And what is a mean, except the sum of a list of elements, divided by the number of elements in the list?
Now do you see how to make this work for a higher dimensional matrix? Easy, peasy.
A = randi(9,[4,4,4])
K = ones(3,3,3); % the convolution kernel, indicating a 3x3x3 moving mean
Amean = convn(A,K,'same')./convn(ones(size(A)),K,'same')
0 comentarios
Jan
el 19 de Mzo. de 2021
Editada: Jan
el 19 de Mzo. de 2021
What about:
M = [3,4,8,6; 1,6,9,0; 2,5,7,1];
Result = movmean(movmean(M, 3, 1), 3, 2);
Or:
n = 3; % Window size
[s1, s2] = size(M);
D = repmat(9, size(M));
D(1, 1) = 4;
D(1, s2) = 4;
D(s1, 1) = 4;
D(s1, s2) = 4;
D(1, 2:s2-1) = 6;
D(s1, 2:s2-1) = 6;
D(2:s1-1, 1) = 6;
D(2:s1-1, s2) = 6;
Result = conv2(M, ones(n), 'same') ./ D;
Or nicer:
Result = conv2(M, ones(n), 'same') ./ conv2(ones(size(M)), ones(n), 'same')
The approach with nested loops is ugly and slower.
4 comentarios
Márton Tamás Birosz
el 16 de Ag. de 2022
Hey, is it possible to use 'movmean' the same way for a 3D (nxnxn) matrix?
Ver también
Categorías
Más información sobre Matrix Indexing en Help Center y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!