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