Borrar filtros
Borrar filtros

A faster replacement for 'imfindcircles'

30 visualizaciones (últimos 30 días)
Saeed Alborzi
Saeed Alborzi el 9 de Mzo. de 2023
Editada: Matt el 13 de Mzo. de 2023
Hi. Does anyone know a quicker way to detect circular objects in an image, instead of 'imfindcircles' ?
I'm working on a particle tracking code that is supposed to track the movement of some cm-sized circular particles in a video. The code first finds the particles using 'imfindcircles' and then tracks them over some successive frames using another tracking code, and then repeats this process multiple times for different trials. However, the number of particles (100), the number of frames in each trial (~300) and the total number of trials (up to 100) make 'imfindcircles' have to be repeated numerous times that it will take a day for such a run.
Does anyone have any suggestion to make this faster?? I checked the timing of the code and know for sure that 'imfindcircles' is taking most of the time...

Respuestas (2)

Matt
Matt el 9 de Mzo. de 2023
Hi
Do you need a radius estimation of your circles ? And do you need to test a list of radius or do they all have the same known radius ?
If the answer is no/same radius then you can use a simple convolution with a circular mask and look for maximum.
R = 5
img = imgaussfilt(rand(1024),R);
% a test image
x = -20:20;
y=x;
[X,Y]=meshgrid(x,y);
Radius = sqrt(X.^2+Y.^2);
mask = Radius<3;
threshold = 13;
% this is the main operation is the detection, faster then imfindcircles
% but not as robust/rich in information
processed = conv2(img,mask,"same");
BW = processed>threshold;
s = regionprops(BW,'centroid');
centers2 = [];
for ii=1:length(s)
centers2(ii,:)=s(ii).Centroid;
end
figure
subplot(1,2,1)
imagesc(img)
subplot(1,2,2)
scatter(centers2(:,1) , centers2(:,2))
  1 comentario
Saeed Alborzi
Saeed Alborzi el 9 de Mzo. de 2023
Editada: Saeed Alborzi el 9 de Mzo. de 2023
Thanks. I tried your masking section on my images but it doesn't work well. Also tried playing with your input parameter values but was not able to make it compatible (I see an entirely white BW at the end)...I myself do the masking with an auto-generated code from Color Thresholder based on the particle colors (have already experimentally made them different with every other color existing in the image). Attached a sample image...

Iniciar sesión para comentar.


Matt
Matt el 13 de Mzo. de 2023
Editada: Matt el 13 de Mzo. de 2023
Il almost works but not quite because you can integreate a lot of signal in between 2 or 3 particles
If you add another parameter like using the fact the the variance in a circle centered on a particle is low, and high when in between 2 particles it works well. And it is still really fast :
clear
img = imread('/home/.../1frame27.jpg');
I = rgb2gray(img);
figure
subplot(1,2,1)
imagesc(img)
subplot(1,2,2)
imagesc(I)
I = double(I);
% I image looks good
x = -23:23;
y=x;
[X,Y]=meshgrid(x,y);
Radius = sqrt(X.^2+Y.^2);
mask = Radius<18;
mask=mask./sum(mask,"all");
processed = conv2(I,mask,"same");
% figure
% imagesc(processed)
% we see here that the particles centers are intensity max in the processed
% image
threshold = 210;
BW = processed>threshold;
% imagesc(processed>threshold) % to help you find the threshold
s = regionprops(BW,'centroid');
centers2 = [];
for ii=1:length(s)
centers2(ii,:)=s(ii).Centroid;
end
figure
imagesc(img)
hold on
scatter(centers2(:,1) , centers2(:,2))
% can't find any good threshold !
% V2 - we can use the fact that variance is low in those bubbles
threshold = 150;
BW = processed>threshold;
processed_var = conv2(I.^2,mask,"same");
processed_var = processed_var-processed.^2;
% processed_var(i,j) is the variance of the N pixels in the circle defined
% by mask centered on (i,j)
processed = conv2(I,mask,"same");
processed_var = conv2(I.^2,mask,"same");
processed_var = processed_var-processed.^2;
SNR = processed./processed_var; % not really a SNR ...
BW2 = SNR>1;
s = regionprops(logical(BW2.*BW),'centroid');
centers2 = [];
for ii=1:length(s)
centers2(ii,:)=s(ii).Centroid;
end
figure
imagesc(img)
hold on
scatter(centers2(:,1) , centers2(:,2))
You can probably go even faster using a canny edge detector + a single convolution with a blurred ring to find the centers with probably a good accuracy.

Productos


Versión

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by