Remove centroid locations of objects that are too close

Hi, I have a list of centroid locations of spots in an image (xf, yf). The spots are randomly distributed. I want to remove the centroid locations that are too close to each other, or say within a distance of d. I've got to the following but not sure what to do next. Also is there a better way to do this ratrher than use loops?
%using a loop
M=[];
for j=1:length(xf)
for i=1:length(xf)
dx=xf(j)-xf(i);
dy=yf(j)-yf(i);
dr=sqrt(power(dx,2)+power(dy,2));
M(j,1)=xf(j);
M(j,2)=yf(j);
M(j,3)=xf(i);
M(j,4)=yf(i);
M(j,5)=dr;
end
end

2 Comments

If two spots are less than d apart should both be removed? If not, by what criterion do you decide which spot remains?
To me it sounds like both are to be removed. This is easily done with pdist2.

Sign in to comment.

 Accepted Answer

A=[xf(:) yf(:)];
D=pdist2(A,A);
D(D==0)=inf; %retroactive EDIT
keep = all(D>d,1);
xf=xf(keep);
yf=yf(keep);

7 Comments

Thankyou Matt. Its almost there. Its not removing the 2nd centroid of the "close pair" of objects.
I've set the cut of distance to be 40.
A and D from your code gives this:
A =
15.88 18.43
33.48 14.99
53.49 37.71
D =
0 17.94 42.27
17.94 0 30.27
42.27 30.27 0
This is my Matrix where col 1,2 are centroids of each spot, col 3,4 are then centroid of all other spots, col 5 is the distance between all pairs of spots.:
M =
15.88 18.43 15.88 18.43 0
15.88 18.43 33.48 14.99 17.94
15.88 18.43 53.49 37.71 42.27
33.48 14.99 15.88 18.43 17.94
33.48 14.99 33.48 14.99 0
33.48 14.99 53.49 37.71 30.27
53.49 37.71 15.88 18.43 42.27
53.49 37.71 33.48 14.99 30.27
53.49 37.71 53.49 37.71 0
Make sure you are using my most updated version. Your D matrix should have NaNs along the diagonal. Not zeros.
I see now that D should have Infs along the diagonals, not NaNs, but even so with d=40, none of your objects are sufficiently remote, so all centroids get removed. With d=30, one blob remains.
A =[
15.88 18.43
33.48 14.99
53.49 37.71]; d=30;
D=pdist2(A,A);
D(D==0)=Inf
D = 3×3
Inf 17.9330 42.2638 17.9330 Inf 30.2754 42.2638 30.2754 Inf
keep = all(D>d,1)
keep = 1×3 logical array
0 0 1
A=A(keep,:)
A = 1×2
53.4900 37.7100
Perfect, thanks. Can you explain the bit about replacing the Nan with Inf, I don't follow this part.
Thanks
Jason
We don't want to consider the distance between an object and itself, so we need to set the diagonal of D to something that will automatically satisfy the distance cut-off criterion.
Of course, its clear now, thankyou
Just to add, when I had over 400 objects, akthough i do other operations, using the for loop took 110s.using the pdist2 approach took just under 2s. Remarkable!

Sign in to comment.

More Answers (1)

yes,sir,may be use pdist2, such as
xf = rand(1, 10);
yf = rand(1, 10);
%using a loop
M=[];
for j=1:length(xf)
for i=1:length(xf)
dx=xf(j)-xf(i);
dy=yf(j)-yf(i);
dr=sqrt(power(dx,2)+power(dy,2));
M(end+1,1)=xf(j);
M(end,2)=yf(j);
M(end,3)=xf(i);
M(end,4)=yf(i);
M(end,5)=dr;
end
end
% second method
A=[xf(:) yf(:)];
B=pdist2(A,A);
C=B';
C=C(:);
isequal(M(:,end),C)
ans = logical
1

Categories

Find more on Image Processing and Computer Vision in Help Center and File Exchange

Products

Release

R2022a

Asked:

on 8 Aug 2022

Commented:

on 9 Aug 2022

Community Treasure Hunt

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

Start Hunting!