A faster replacement for 'imfindcircles'
29 views (last 30 days)
Show older comments
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...
0 Comments
Answers (2)
Matt
on 9 Mar 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))
Matt
on 13 Mar 2023
Edited: Matt
on 13 Mar 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.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!