Find the average between each pair of points in a matrix

16 views (last 30 days)
Hello, I have a 61x61 random generated double matrix, I want to calculate the average between each point in a row of a column, and after going through all the rows in that column and calculating their corresponding averages, go to the next column.
If the average is >= 2 or <= -2 I would like to then set that data point to 1, otherwise set it to 0.
I managed to do this using for loops and if statements, but how would I do this using a vectorized approach?
I attatch what I have right now for reference.
Thanks.
Edit: Forgot to add, I would like to then, find the average between each point horizontally (what I stated above was vertically) so averaging between points in the 1st row and all columns, and then going to the 2nd row and so on. The average criteria is the same but if previously the data point is set to 1 and now it was calculated to be 0, keep it as 1, and if it was 0 and now was calculated as 1, then overwrite it to 1.
(I included two images to show what I mean by averaging horizontally and vertically.)

Accepted Answer

Joe Vinciguerra
Joe Vinciguerra on 11 Apr 2023
Edited: Joe Vinciguerra on 11 Apr 2023
I'm a little unclear on the specifics, but I think this is basically what you want:
z = randi([-5 5],61,61,'double')
zMeanV = movmean(z, [0 1], 1)
zMeanVH = movmean(zMeanV,[0 1], 2)
avgMap = or(zMeanVH >= 2, zMeanVH <= -2)
[edit]
After re-reading your post and looking closer at your code, it sounds like it should be more like this:
z = randi([-5 5],61,61,'double');
zMeanV = movmean(z, [0 1], 1);
zMeanV(end,:) = zMeanV(end-1,:);
avgMapV = or(zMeanV >= 2, zMeanV <= -2);
zMeanH = movmean(z,[0 1], 2);
zMeanH(:,end) = zMeanH(:, end-1);
avgMapH = or(zMeanH >= 2, zMeanH <= -2);
avgMap = or(avgMapV, avgMapH)
  7 Comments
JIAN-HONG YE ZHU
JIAN-HONG YE ZHU on 13 Apr 2023
Sorry for that silly mistake. The context to the 'random matrix' (which I used to ask the question) is that the actual matrix is intended to be filled with points in a position of a map, and the value of each point is the height of that point in the map.
By calculating the average between points, then I could see whether it is feasible or not for a vehicle to go from two certain points, so if the average surpasses certain value, it means a vehicle could not drive through it, or it's a cliff (-4 4...).
That being said, I realized if I want this I should instead calculate the gradient instead which would be more relevant to this.
Thank you very much for your help I appreciate it
Joe Vinciguerra
Joe Vinciguerra on 13 Apr 2023
A 2D gradient() of the entire array definately seems to make more sense for the application. Cheers!

Sign in to comment.

More Answers (1)

dpb
dpb on 11 Apr 2023
Edited: dpb on 11 Apr 2023
I'd do it as
z=randi([-5 5],8)
z = 8×8
-4 -1 0 5 -5 -4 0 5 -1 -2 5 -1 -5 0 2 -4 1 -1 -1 -5 -4 -3 -1 3 2 5 -4 4 4 -1 -1 -2 4 1 -3 4 -3 2 1 2 -4 -5 0 5 -4 5 -1 1 4 0 0 -1 5 5 -4 1 -1 5 -2 5 -4 -4 1 -2
za=filter2(ones(2)/4,z) % averaging 2D filter with same size as input (zero padded)
za = 8×8
-2.0000 0.5000 2.2500 -1.5000 -3.5000 -0.5000 0.7500 0.2500 -0.7500 0.2500 -0.5000 -3.7500 -3.0000 -0.5000 -0.0000 -0.2500 1.7500 -0.2500 -1.5000 -0.2500 -1.0000 -1.5000 -0.2500 0.2500 3.0000 -0.2500 0.2500 2.2500 0.5000 0.2500 -0.0000 -0.0000 -1.0000 -1.7500 1.5000 0.5000 0.0000 1.7500 0.7500 0.7500 -1.2500 -1.2500 1.0000 1.2500 2.7500 1.2500 -0.7500 0.5000 2.0000 0.7500 0.5000 1.2500 0.5000 -0.5000 -1.0000 -0.2500 1.0000 0.7500 0.7500 0.2500 -2.0000 -0.7500 -0.2500 -0.5000
zv=filter2(ones(2)/4,z,'valid') % keep only non-padded elements
zv = 7×7
-2.0000 0.5000 2.2500 -1.5000 -3.5000 -0.5000 0.7500 -0.7500 0.2500 -0.5000 -3.7500 -3.0000 -0.5000 -0.0000 1.7500 -0.2500 -1.5000 -0.2500 -1.0000 -1.5000 -0.2500 3.0000 -0.2500 0.2500 2.2500 0.5000 0.2500 -0.0000 -1.0000 -1.7500 1.5000 0.5000 0.0000 1.7500 0.7500 -1.2500 -1.2500 1.0000 1.2500 2.7500 1.2500 -0.7500 2.0000 0.7500 0.5000 1.2500 0.5000 -0.5000 -1.0000
Alternatively, you can choose 'valid' and get the averages only where there is no zero padding. This then returns a filtered array that is in your case over averaging over two elements, one less in each direction.
The description of the scaling is confusing, however, but by the first description, it would be
za=double(abs(za)>=2) % scales to 0, 1 based on average (throws away sign???)
za = 8×8
1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
  4 Comments
JIAN-HONG YE ZHU
JIAN-HONG YE ZHU on 12 Apr 2023
Thank you very much for your insight, I have one question, after reading through 2-D digital filter - MATLAB filter2 - MathWorks United Kingdom , 'filter2' has a syntax of Y = filter2(H,X), in this case, the matrix H is ones(2)/4. I do not understand how this matrix H is defined?
dpb
dpb on 12 Apr 2023
Edited: dpb on 12 Apr 2023
Ir's your 2x2 averaging kernel -- multiplies each set of four locations by 1/4 and adds which is the average over the four locations. As the doc also points out, filter is just conv (convolution) with the kernel rotated 90 degrees. Since yours is symmetric, it doesn't make any difference which.
You'll note that the first case, 'Same' is padded w/ zeros on bottom and right; those values are half of the average the the last two points. Sometimes (and what your code does if my glance-thru was correct) I'll multiply that last row/column by the ratio of the kernel size and the number of padded rows/columns(*). Here, of course, with a 2x2 kernel, it just has to pad the one row/column so the multiplier is 2/1-->2. You can see that result by inspection with the integer values it's easy to add and divide by four.
In the second example, 'Valid', the result is one row/column less than the original, but there's no padding and so the last row/column of the result are full 4-element averages.
Which to use and whether to reweight or not is all dependent upon what your needs are for the result; we can't know anything about that.
(*) If you do choose to normalize the last row/column, remember to only address the lower RH corner element once; otherwise you'll end up doing it twice!

Sign in to comment.

Products


Release

R2022b

Community Treasure Hunt

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

Start Hunting!