I have a pixel matrix containing some points and a lot of zero elements. From those non-zero points, I want to discard those that have a stronger point in range N withing the matrix. The range is an euclidean distance between the pixels.
input = [0.0 0.0 0.0 0.9 0.0 0.0
0.0 0.0 0.2 0.0 0.0 0.5
0.0 0.0 0.7 0.0 0.0 0.0
0.0 0.4 0.1 0.0 0.0 0.0];
output = [0.0 0.0 0.0 0.9 0.0 0.0 % 0.7 is the largest number in range
0.0 0.0 0.0 0.0 0.0 0.5 % 0.2 got removed; was next to 0.9 and 0.7
0.0 0.0 0.7 0.0 0.0 0.0 % 0.7 is the largest number in range
0.0 0.0 0.0 0.0 0.0 0.0]; % 0.1 and 0.4 both got removed; were next to 0.7
Update: This is what I've came up so far. It iterates over all non-zero pixels and compares the current pixel to the largest of the neighborhood. However, the neighborhood contains to many pixels. Rather than selecting the area through index offsets, I need to select a circular area somehow. Moreover, I'd be grateful if there is a shorter way, maybe replacing the loops with built-in Matlab functions like conv2
or imfilter
.
% Discard points near stronger points
points = find(Image > 0);
radius = args.Results.min_dist;
for i = 1:size(points)
[index_y, index_x] = ind2sub(size(Image), points(i));
% Find neighborhood
from_x = max(index_x-radius, 1);
from_y = max(index_y-radius, 1);
to_x = min(index_x+radius, size(Image, 2));
to_y = min(index_y+radius, size(Image, 1));
neighbors = Image(from_y:to_y, from_x:to_x);
% Discard if there is a stronger neighbor
largest = max(max(neighbors));
if Image(index_y, index_x) < largest
Image(index_y, index_x) = 0;
end
end
If you had the image processing toolbox installed (or one of the free alternatives mentioned in Try Hard's answer), you could make this happen quite easily:
The function imdilate
is basically a sliding max filter. So what we do is, for each pixel we look for the maximum in the neighborhood specified by your radius R
. Then we compare the actual value with the found maximum and if it is smaller, we set the value to zero.
function A = zeroOutWeakElements(A, R)
[X,Y] = ndgrid(-ceil(R):ceil(R));
neighborhood = (X.^2 + Y.^2)<=R^2;
A(imdilate(A,neighborhood)>A) = 0;
For large full matrices and small distances this would also be significantly faster than the currently accepted solution. The benefit will wear off with sparse matrices and large radii, but I guess you should test with actual data to be sure what's best.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With