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 comentarios

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.

Iniciar sesión para comentar.

 Respuesta aceptada

Matt J
Matt J el 9 de Ag. de 2022
Editada: Matt J el 9 de Ag. de 2022
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 comentarios

Jason
Jason el 9 de Ag. de 2022
Editada: Jason el 9 de Ag. de 2022
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!

Iniciar sesión para comentar.

Más respuestas (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

Categorías

Más información sobre Data Type Identification en Centro de ayuda y File Exchange.

Productos

Versión

R2022a

Etiquetas

Preguntada:

el 8 de Ag. de 2022

Comentada:

el 9 de Ag. de 2022

Community Treasure Hunt

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

Start Hunting!

Translated by