Find the average between each pair of points in a matrix
18 次查看(过去 30 天)
显示 更早的评论
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.)
0 个评论
采纳的回答
Joe Vinciguerra
2023-4-11
编辑:Joe Vinciguerra
2023-4-11
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 个评论
Joe Vinciguerra
2023-4-13
A 2D gradient() of the entire array definately seems to make more sense for the application. Cheers!
更多回答(1 个)
dpb
2023-4-11
编辑:dpb
2023-4-11
I'd do it as
z=randi([-5 5],8)
za=filter2(ones(2)/4,z) % averaging 2D filter with same size as input (zero padded)
zv=filter2(ones(2)/4,z,'valid') % keep only non-padded elements
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???)
4 个评论
dpb
2023-4-12
编辑:dpb
2023-4-12
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!
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Logical 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!