MATLAB Answers

Matrix size is A(100*100). Weighted average of the 4 elements.

29 views (last 30 days)
Karthik Nagaraj
Karthik Nagaraj on 5 Dec 2018
Commented: Jan on 6 Dec 2018
How to store the result in a matrix which contains the average the 4 elements in the cluster A11, A12,A21,A22 and similarly A13,A14.A23,A24 and goes on? The resultant matrix should be 25*25

  5 Comments

Show 2 older comments
Jan
Jan on 6 Dec 2018
This image does not clarify, what you want to do. Please explain the detail of weighting the average.
Stephen Cobeldick
Stephen Cobeldick on 6 Dec 2018
"The resultant matrix should be 25*25"
Following your description the resulting matrix would actually be 50x50. Consider a simpler 10x10 matrix:
>> A = randi(9,10,10) % 10x10
A =
5 5 8 2 7 4 4 2 1 6
9 7 2 5 9 8 6 8 2 2
1 5 6 8 6 8 7 4 3 4
7 9 4 4 3 2 6 6 7 1
3 8 8 7 2 3 5 8 2 4
1 6 9 8 1 8 6 4 8 5
7 9 3 3 1 6 5 9 3 8
2 6 7 8 3 9 9 1 8 9
6 1 6 3 7 5 6 4 9 7
9 2 6 7 6 8 4 1 5 5
>> M = (A(1:2:end,1:2:end)+A(2:2:end,1:2:end)+A(1:2:end,2:2:end)+A(2:2:end,2:2:end))/4
M =
6.5000 4.2500 7.0000 5.0000 2.7500
5.5000 5.5000 4.7500 5.7500 3.7500
4.5000 8.0000 3.5000 5.7500 4.7500
6.0000 5.2500 4.7500 6.0000 7.0000
4.5000 5.5000 6.5000 3.7500 6.5000
>> size(M) % resulting matrix is 5x5
ans =
5 5
>> mean([5,5,9,7]) % check first block
ans = 6.5000
So far it is not clear where any weighting is involved. Please clarify how the weighting is defined and what it should be applied to.
Karthik Nagaraj
Karthik Nagaraj on 6 Dec 2018
Thanks a lot!
This gives the desired result!
Instead of 2x2 matrix, can you generalize the above solution for KXL matrix order, which is a submatrix whose averages are to be determined similarly.
I have reframed the question. Sorry for confusing 2x2 with 4x4. It is a 4 element sub matrix with 2x2 order and weighting is not actually involved.
In the case of 100*100 matrix; the subset of 2x2 window matrices reduce the 100x100 to 50x50 matrix (100/2=50). These 2x2 matrices are unique; i.e., I have to take the first two elements of the first row and same elements of the second row and average it. Similarly, for the next set I have to take third and fourth element of the first row and same elements of the second row and average it. This goes on until the 99th and 100th element of the first row and second row. All these averaged results are to be stored in the first row of a new matrix.
Likewise for the next set I have to take 3rd and 4th row and next 5th and 6th and so on upto 99th and 100th row. All these averaged results are to be stored in a new matrix whose dimensions are 25x25.
Note that the set of elements are nowhere repeated!
for loops with two variables and some more usual methods I have tried but of no use!
So I don't want to move the 2x2 window over by a pixel each time, I want to move it in "jumps" of 2x2 sub-matrix.
Please help me solving this.

Sign in to comment.

Accepted Answer

Jan
Jan on 6 Dec 2018
Edited: Jan on 6 Dec 2018
In the original question and the image you mentiones 2x2 submatrices. In the commend you talk of 4x4 submatrices. This is not clear in this sentence also:
These 4x4 matrices are unique; i.e., I have to take the first two elements of the first row and same elements of the second row and average it.
Here I used n=4, but perhaps you want n=2:
n = 4;
X = rand(100, 100);
Y = reshape(X, [n, 100/n, n, 100/n]);
Y = permute(Y, [2, 4, 1, 3]); % Move dims of length n together
Y = reshape(Y, [100/n, 100/n, n*n]); % Combine to subvectors of length n*n
Result = mean(Y, 3); % Mean over 3rd dimension

  5 Comments

Show 2 older comments
Jan
Jan on 6 Dec 2018
@Karthik: Please try to concentrate. The question if you mean 2x2 or 4x4 sub matrices is still not clear. See:
subset of 2x2 window matrices reduce the 100x100 to 25x25 matrix (100/4=25)
No, a 2x2 window of a 100x100 matrix creates 50x50 tiles, not 25x25.
The code I have posted runs without an error. If you get an error in reshape you do run a different code. If you do not post it, I cannot find the problem. Please try it again:
n = 2;
X = rand(100, 100);
Y = reshape(X, [n, 100/n, n, 100/n]);
Y = permute(Y, [2, 4, 1, 3]); % Move dims of length n together
Y = reshape(Y, [100/n, 100/n, n*n]); % Combine to subvectors of length n*n
Result = mean(Y, 3);
This can be expanded easily to the general case:
K = 2;
L = 4;
X = rand(100, 100);
Y = reshape(X, [K, 100/K, L, 100/L]);
Y = permute(Y, [2, 4, 1, 3]); % Move dims of length n together
Y = reshape(Y, [100/K, 100/L, K*L]); % Combine to subvectors of length n*n
Result = mean(Y, 3);
If the size of the matrix is not a multiple of the sub-matrix sizes, this must fail. In this FileExchange submission you find a fast C-Mex function to compute the results and the same function as M-file also, which crops the right and bottom columns and rows, if the size is not a multiple of K or L: https://www.mathworks.com/matlabcentral/fileexchange/24812-blockmean
You still did not explain the "weighting".
Karthik Nagaraj
Karthik Nagaraj on 6 Dec 2018
Mr Jan,
Thank you so much for your time and efforts. Finally your solution works as mentioned. I had not changed one variable in your code for the requirement of a problem, that was the reason for me not getting the solution.
I correct myself, its 50x50 tiles and I misinterpreted the term 'Weighting'.
Thanks again.
Thank you one and all for helping me out!
Jan
Jan on 6 Dec 2018
@Karthik: You are welcome. Helping to solve problems is the purpose of this forum :-)

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 5 Dec 2018
Try this:
kernel = ones(4)/16;
localMeans = conv2(A, kernel, 'same');

  4 Comments

Show 1 older comment
Image Analyst
Image Analyst on 5 Dec 2018
Only one 4x4 window will fit into a 4x4 array. If you slide it around, then some part will be off the array. So then you will have less than 16 elements in. So you have to decide what to do with the missing elements. conv() assumes they're zero. If you really need to have the window "shrink" when it gets close the the edge, you'll have to do conv2() twice. Once to sum up the values of the array, and once to count the number of elements at each position, and then you divide those two images. Let me know if you need this. Usually it's not needed since the array is much bigger than the filter window and what happens near the edges does not really matter that much.
Karthik Nagaraj
Karthik Nagaraj on 5 Dec 2018
Thanks again for responding!
I am finding it difficult to understand the conv() function role here.
In the case of 100*100 matrix; the subset of 4x4 window matrices reduce the 100x100 to 25x25 matrix (100/4=25). These 4x4 matrices are unique; i.e., I have to take the first two elements of the first row and same elements of the second row and average it. Similarly, for the next set I have to take third and fourth element of the first row and same elements of the second row and average it. This goes on until the 99th and 100th element of the first row and second row. All these averaged results are to be stored in the first row of a new matrix.
Likewise for the next set I have to take 3rd and 4th row and next 5th and 6th and so on upto 99th and 100th row. All these averaged results are to be stored in a new matrix whose dimensions are 25x25.
Note that the set of elements are nowhere repeated!
for loops with two variables and some more usual methods I have tried but of no use!
Please help me solving this.
Image Analyst
Image Analyst on 6 Dec 2018
So you don't want to move the 4x4 window over by a pixel each time, you want to move it in "jumps" of 4. That's quite a different thing. You can do it in jumps if you use blockproc(). Study the attached examples for a variety of ways to use it. Adapt as needed.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!