How to remove this NON RED AND NON CIRCLE objects from this image? And make reds white and rest is black

Viewed 263

enter image description here I need red circles white, and the rest as black. Exactly like binary image. I could filter out only red color, then do stuff but how to include only circles? I tried many things but it just doesn't work. I guess because of deprecated functions of MATLAB. Because many of these topics are so old atleast 10 years old. I tried these:

https://nl.mathworks.com/help/images/ref/bwareaopen.html

https://nl.mathworks.com/matlabcentral/answers/19507-remove-non-circle-objects-from-image

I only came so close with this code, but it still leaves squares and hexagons around. I want them gone but don't know how. I tried increasing minExtend, or decreasing, but it doesn't do it.

I=imread('circlesColored.png');
% Get the image as a b&w indexed (non-rgb) image
R=I(:,:,1);
R=(R>35&R<255);
imshow(R);
bwareaopen(I, 50);
 BW = gray2ind(R, 2);
%Calculate its connected regions
L = bwlabel(BW); % Not using bwconncomps() for older version users
stats = regionprops(L,'Extent','Area');
%Find the ones that are like a circle
minExtent = 0.75;
keepMask = [stats.Extent]>minExtent;
%Extract the image of circles only and display
BWcircles = ismember(L, find(keepMask));
BWnonCircles = BW & ~BWcircles;
%Show the circles
figure, imshow(BWcircles)
2 Answers

As of R2019a, a 'Circularity' property is added to regionprops. I modified your code to get that:

close all; clc; clear variables;
I=imread('2JxCA.png');
% Get the image as a b&w indexed (non-rgb) image
R=I(:,:,1);
R=(R>35&R<255);
imshow(R);
%Calculate its connected regions
L = bwlabel(R); % Not using bwconncomps() for older version users
stats = regionprops(L,'Circularity'); 
%Find the ones that are like a circle
keepMask = [stats.Circularity]>.99;
%Extract the image of circles only and display
BWcircles = ismember(L, find(keepMask));
BWnonCircles = R & ~BWcircles;
%Show the circles
figure, imshow(BWcircles)

enter image description here

But don't worry if you are using older versions. Docs actually described how it is calculated:

'Circularity'
Roundness of objects, returned as a struct with field Circularity. The struct contains the circularity value for each object in the input image. The circularity value is computed as (4*Area*pi)/(Perimeter^2). For a perfect circle, the circularity value is 1. The input must be a label matrix or binary image with contiguous regions. If the image contains discontiguous regions, regionprops returns unexpected results.

Note

Circularity is not recommended for very small objects such as a 3-by-3 square. For such cases, the results might exceed the circularity value for a perfect circle.

So, if you are running the code in versions older than R2019a, replace the lines in which stats and keepMask are assigned with the following lines:

stats = regionprops(L,'Area', 'Perimeter'); 
%Find the ones that are like a circle
Circularity = (4*[stats(:).Area]*pi)./([stats(:).Perimeter].^2);
keepMask = Circularity>.99;

here's a slightly different approach:

% remove non-red
thr=100;
I_only_red= I(:,:,1)>thr & I(:,:,2)<thr & I(:,:,3)<thr ;

%remove non circles: we first find the circles in the image
[centers, radii, metric] = imfindcircles(I_only_red,[40 120]);

% and make a mask according to their centers and radii:
[x y]=meshgrid(1:size(I,2),1:size(I,1));
mask=zeros(size(I_only_red));

for n=1:numel(radii)
    mask = mask | (x-centers(n,1)).^2+(y-centers(n,2)).^2<=radii(n).^2;
end

let's plot:

subplot(3,1,1); imagesc(I);
subplot(3,1,2); imagesc(I_only_red);
                viscircles(centers , radii ,'EdgeColor','b');

subplot(3,1,3); imagesc(I_only_red.*mask);

enter image description here

Related