how can i detect round objects and remove other objects in an image using matlab?

IMAGES{i} = imread(sprintf(Fimage,i));
result = cell(1,N);
result{i} = rgb2gray(IMAGES{i});
BW = im2bw(result{i}, .4);
se = strel('disk',11);
erodedBW = imdilate(BW,se);
imagesc(erodedBW)
bw=bwareaopen(erodedBW,50000);
%imshow(bw)
%hold
[B,L] = bwboundaries(bw,'noholes');
for k = 1:length(B)
boundary = B{k};
xr(i,k)=round(mean((boundary(:,2))));
yr(i,k)=round(mean((boundary(:,1))));
imgindex(i)=i;
end
st=regionprops( ~bw,'area','centroid','PixelIdxList');

 Accepted Answer

It seemed to work for me:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
rgbImage = imread('005.png');
grayImage = rgb2gray(rgbImage);
subplot(2,2,1);
imshow(grayImage);
title('Original Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Threshold the image.
binaryImage = im2bw(grayImage, .4);
% Display the image.
subplot(2,2,2);
imshow(binaryImage)
title('Initial Binary Image', 'FontSize', fontSize);
% Dilate the image to enlarge the small blobs.
se = strel('disk',11);
binaryImage = imdilate(binaryImage,se);
subplot(2,2,3);
imshow(binaryImage)
title('Dilated Image', 'FontSize', fontSize);
% Label the blobs.
labeledImage = bwlabel(binaryImage);
measurements = regionprops(labeledImage,'Area','Perimeter');
% Do size filtering and roundness filtering.
% Get areas and perimeters of all the regions into single arrays.
allAreas = [measurements.Area]
allPerimeters = [measurements.Perimeter]
% Compute circularities.
circularities = allPerimeters.^2 ./ (4*pi*allAreas)
% Find objects that have "round" values of circularities.
maxAllowableArea = 50000;
keeperBlobs = circularities < 3 & allAreas < maxAllowableArea; % Whatever values you want.
% Get actual index numbers instead of a logical vector
% so we can use ismember to extract those blob numbers.
roundObjects = find(keeperBlobs);
% Compute new binary image with only the small, round objects in it.
binaryImage = ismember(labeledImage, roundObjects) > 0;
subplot(2,2,4);
imshow(binaryImage);
title('Final Image', 'FontSize', fontSize);
% Remeasure with this new segmentation.
% Label the blobs.
labeledImage = bwlabel(binaryImage);
measurements = regionprops(labeledImage,'Area','Perimeter', 'Centroid');
% Get areas and perimeters of all the regions into single arrays.
allAreas = [measurements.Area]
allPerimeters = [measurements.Perimeter]
allCentroids = [measurements.Centroid]
centroidX = allCentroids(1:2:end);
centroidY = allCentroids(2:2:end);
% Plot circles around them
hold on;
for k = 1 : length(centroidX);
plot(centroidX(k), centroidY(k), ...
'ro', 'MarkerSize', 20, 'LineWidth', 2);
end
What does "not working well" mean to you? What exactly do you want as an output of this routine? The size, location, what?????

14 Comments

that was really helpful, sorry for bothering you but can i only detect the "IR" i'm not sure if that's possible
I don't know which blob is the IR. Tell me.
kindly you'll see two images attached , one with an "on" IR LED light and the other one "off" the purpose of my project is to save the sequence of "on and off" as a matrix, when the light is off i don't want anything to be detected "full-black" image this codes detects the noise as well which is unwanted is that possible?
files/28143/040.png>>
It looks like the on and off states have different brightnesses so you should be able to find a threshold that distinguishes between the two.
Sir, the final image shows unwanted circular shape as attached below i only want the one next to the red arrow as shown
Sounds interesting , did you try to work with a specific pixels in the image as I understand your LED is around the center , so try to detect within the center area
Try the attached code. It works for both images you've supplied.
Actually you're best off just masking off the image to known regions. If your camera is aimed at pretty much the same place every time then you can just blacked out areas known to be tape or whatever and just let the black rectangles show through. Do that before you even do anything else.
thank you for your help , Im working on a video in order to detect the sequence of 8 images on and off and the IR blinks are really fast not to be noticed by humans eye(blinking IR by arduino) as the on light is =1 and the off =0 so im getting a matrix of ones and zeros
It will be a little tricky to get the frame rate right. If you're too slow then the LED might be on for some of the exposure time and off for some of the exposure time. If it's too fast, it will be on (most probably) during a whole frame time but you have to make sure there is enough light captured to produce a spot in the image. If the frame time is around the time of an "on" time of the LED, you might have the LED on in two subsequent frames, and will it have enough exposure in each frame to register? And if it does, do you say it was on for two frame times, or just one frame time. You'll have to look at the intensity and try to figure out how long it was on during that one frame exposure.
I did try to change the frame rate in matlab (30 frames per sec"default") but couldnt do that so after a lot of math i could do the blinks as the frames and i need a single blink for a single frame so for now i'll check the intensity and get back to you , thank you very much
Why not check if the light is on by attaching an Arduino to the LED leads rather than by using image analysis?
the main idea of the project is to know the sequence by using image analysis.

Sign in to comment.

More Answers (2)

Calculate the circularities and filter based on that.
labeledImage = bwlabel(~bw);
st=regionprops(labeledImage,'area','Perimeter');
% Get areas and perimeters of all the regions into single arrays.
allAreas = [st.Area];
allPerimeters = [st.Perimeter];
% Compute circularities.
circularities = allPerimeters.^2 ./ (4*pi*allAreas);
% Find objects that have "round" values of circularities.
roundObjects = find(circularities < 4); % Whatever value you want.
% Compute new binary image with only the round objects in it.
binaryImage = ismember(labeledImage, roundObjects) > 0;
imshow(binaryImage);

1 Comment

i want to detect only this ir LED and remove all other objects, its not working well!

Sign in to comment.

I adapted the code above. May not be too elegant but it worked for me (I am looking at mouse cells).
circ_thresh = 1.15; %default circularity of 1.2 is OK, 1.05 is very stringent
%try to exclude weird shapes based on circularity
mask_conn= bwconncomp(mask_bs,8); % you need this as input for function 'regionprops'
mask_RP=regionprops(mask_conn,'area','Perimeter','PixelIdxList');
allAreas = [mask_RP.Area];
allPerimeters = [mask_RP.Perimeter];
circularities = allPerimeters.^2 ./ (4*pi*allAreas);
roundObjectsIndex = find(circularities < circ_thresh); % Whatever value you want.
mask_bsTEMP = false(size(DAPI_flat, 1), size(DAPI_flat, 2)); % initialize the mask as black
mask_RP_sort = mask_RP(roundObjectsIndex,:);
for k = 1:numel(mask_RP_sort)
idx = mask_RP_sort(k).PixelIdxList;
mask_bsTEMP(idx) = true;
end
mask_bs5=mask_bsTEMP; %test circularity threshold circ_thresh
imshow(mask_bs5);

1 Comment

There is now a 'Circularity' option to ask regionprops() for so you don't have to compute it yourself, though it's the inverse of what we computed. It's
(4*Area*pi)./(Perimeter^2)

Sign in to comment.

Categories

Community Treasure Hunt

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

Start Hunting!