how to separate objects in image using matlab

 Accepted Answer

DGM
DGM on 21 Jun 2021
Edited: DGM on 21 Jun 2021
Consider:
inpict = imread('toolspic.png'); % cropped from thumbnail
bpict = rgb2gray(inpict)<220; % pick a threshold to isolate from BG
S = regionprops(bpict,'boundingbox','filledimage');
C = cell(numel(S),1);
for n = 1:numel(S)
% get mask of object only
mk = S(n).FilledImage;
% get corresponding rectangular area of original image
bb = floor(S(n).BoundingBox);
samp = inpict(bb(2):bb(2)+bb(4)-1,bb(1):bb(1)+bb(3)-1,:);
% remove adjacent object fragments from rectangular sample
samp(repmat(~mk,[1 1 size(inpict,3)])) = 255;
% store this image
C{n} = samp;
end
% just plot the images for viewing
for n = 1:numel(S)
subplot(3,4,n)
imshow(C{n},'border','tight')
end
Of course, there are other things to consider. This uses a very tight binary mask to extract the objects from the image. If the objects had soft edges, they would inherit hard edges from the mask. If the purpose is visual, then it may be desired to use a dilated mask and/or a softened (numeric) masking approach. Either would have further complications, particularly the need to deal with objects near the image boundaries.

5 Comments

Thank you sir this code is very good and powerful , sir i have question this image works 100 % true but there is many images are not compatible and works with this code ?
Thank you best regards
And also in some images i have this error (index in position 1 is invalid. array indices must be positive integers or logical values)
If I had to guess, I would suspect the problem is with objects that touch the image boundary.
You could try doing this after the first two lines:
inpict = padarray(inpict,[2 2],255,'both'); % pad image with bg color (white)
bpict = padarray(bpict,[2 2],0,'both'); % pad mask with bg color (black)
There are other ways to do the same thing, but this is simple enough.
If that doesn't help, consider attaching one of the problem images.
Thank you sir
This attached image has a problem
The issue was just with some speckles being picked up as objects. I guess I should've thought about that. Using bwareaopen on bpict will remove spots smaller than a given number of pixels.
bpict = bwareaopen(bpict,100);
Given that I'm using a masking approach with FilledImage, filling bpict itself shouldn't be necessary unless the interiors of certain objects are patterned in a way that makes it difficult to despeckle by connected group size. For sake of robustness, it might be a good thing to add prior to calling bwareaopen().
bpict = imfill(bpict,'holes');

Sign in to comment.

More Answers (2)

if your input image has white background you can easily generate a binare image after conversion to grayscale and using thresholding
grayIm=rgb2gray(im);
binIm=grayIm(grayIm<0.9);
on the binary image you can use bwconvhull with the 'objects' option or/and finally bwlabel(); this gives you the positions in which you can find different objects. you can then cut the objects out of the original image and save them as separate image
What I'd do is to binarize the image then call imfill() to fill holes in the objects.
grayImage = rgb2gray(rgbImage);
binaryImage = grayImage < 220;
binaryImage = imfill(binaryImage, 'holes');
Then call regionprops to get the bounding box of each image.
props = regionprops(binaryImage, 'BoundingBox');
Then I'd crop out each sub-image. Then I'd use a double for loop with isequal() to compare every image with every other image to see which subimage is unique.
numObjects = length(props)
alreadyUsed = false(numObjects); % Keep track if we've already seen this object or not.
for k1 = 1 : numObjects
image1 = imcrop(grayImage, props(k1).BoundingBox);
foundIt = false;
for k2 = 1 : numObjects
if k1 == k2
% Don't bother comparing object to itself.
continue;
end
image2 = imcrop(grayImage, props(k2).BoundingBox);
foundIt = false;
if isequal(image1, image2)
foundIt = true;
break; % Don't bother checking against the others, unless you want a count.
end
end
if ~foundIt
% We have not seen this object yet. So paste it onto our
% output canvass.
% Code for you to complete to paste image1 onto canvass
end
end
If it's unique, paste it onto your output canvass. If it's not unique and it's the second instance of the object, then don't paste it onto the output image. It should work as long as it's a computer graphics image and all objects are identical, i.e. no varying compression artifacts. If there are slight differences, then make sure they're the same size and use corrcoeff() to see how similar the images are.
Some demos are included which may be informative.

Asked:

on 21 Jun 2021

Commented:

DGM
on 23 Jun 2021

Community Treasure Hunt

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

Start Hunting!