Taha Kamil
Taha Kamil

Reputation: 25

How to crop out a detected object (circle) from image and store it?

The code below classifies objects based on their roundness using bwboundaries.

It estimates each object's area and perimeter and uses these results to form a simple metric indicating the roundness of an object with the following metric:

metric = 4*pi*area/perimeter^2

This metric is equal to 1 only for a circle and it is less than one for any other shape. But with this code, I'm using a threshold of 0.80 so that only objects with a metric value greater than 0.80 will be classified as round.

My question is when a given object classified as a round, how can I crop it out from the original image img (not I nor bw) and save it as a new image?

I think using the label matrix and boundary matrix would be enough to do so, but still don't know how to manipulate them.

img=imread('cap.png');
I = rgb2gray(img);

% Step 2: Threshold the Image
bw1 = imbinarize(I);
bw = imcomplement(bw1);

% Step 3: Remove the Noise
bw = bwareaopen(bw,30);      % remove small objects
bw = imfill(bw,'holes');    


% Step 4: Find the Boundaries
[B,L] = bwboundaries(bw,'noholes');
imshow(label2rgb(L,@jet,[.5 .5 .5]))
hold on
for k = 1:length(B)
  boundary = B{k};
  plot(boundary(:,2),boundary(:,1),'w','LineWidth',2)
end



% Step 5: Determine which Objects are Round
stats = regionprops(L,'Area','Centroid');
threshold = 0.80;
% loop over the boundaries
for k = 1:length(B)

  % obtain (X,Y) boundary coordinates corresponding to label 'k'
  boundary = B{k};

  % compute a simple estimate of the object's perimeter
  delta_sq = diff(boundary).^2;    
  perimeter = sum(sqrt(sum(delta_sq,2)));

  % obtain the area calculation corresponding to label 'k'
  area = stats(k).Area;

  % compute the roundness metric
  metric = 4*pi*area/perimeter^2;

  % display the results
  metric_string = sprintf('%2.2f',metric);

  % Test if the current object classified as a round
  if metric > threshold
    % HERE, I want to crop the current object from the 'img' 
    % and save it as a new image 
  end

end

title(['Metrics closer to 1 indicate that ',...
       'the object is approximately round'])

Upvotes: 2

Views: 271

Answers (1)

rayryeng
rayryeng

Reputation: 104555

You can additionally add the BoundingBox attribute to regionprops which will effectively give you the limits of where the blob extends within a bounding box, and you can use those to crop your image and save it. It will have the form [x y width height] where x and y are the top left coordinates of the bounding box and width and height are of course the width and height. x would be the column coordinate and y would be the row coordinate. You can use imcrop to finally crop out the image.

img=imread('cap.png');
I = rgb2gray(img);

% Step 2: Threshold the Image
bw1 = imbinarize(I);
bw = imcomplement(bw1);

% Step 3: Remove the Noise
bw = bwareaopen(bw,30);      % remove small objects
bw = imfill(bw,'holes');    


% Step 4: Find the Boundaries
[B,L] = bwboundaries(bw,'noholes');
imshow(label2rgb(L,@jet,[.5 .5 .5]))
hold on
for k = 1:length(B)
  boundary = B{k};
  plot(boundary(:,2),boundary(:,1),'w','LineWidth',2)
end



% Step 5: Determine which Objects are Round
stats = regionprops(L,'Area','Centroid','BoundingBox'); % Change
threshold = 0.80;
% loop over the boundaries
for k = 1:length(B)

  % obtain (X,Y) boundary coordinates corresponding to label 'k'
  boundary = B{k};

  % compute a simple estimate of the object's perimeter
  delta_sq = diff(boundary).^2;    
  perimeter = sum(sqrt(sum(delta_sq,2)));

  % obtain the area calculation corresponding to label 'k'
  area = stats(k).Area;

  % compute the roundness metric
  metric = 4*pi*area/perimeter^2;

  % display the results
  metric_string = sprintf('%2.2f',metric);

  % Test if the current object classified as a round
  if metric > threshold
    % HERE, I want to crop the current object from the 'img' 
    % and save it as a new image 

    % New - crop image
    bb = stats(k).BoundingBox;
    img_crop = imcrop(img, bb);

    % New - Save the image
    imwrite(img_crop, sprintf('crop%d.png', k));
  end

end

title(['Metrics closer to 1 indicate that ',...
       'the object is approximately round'])

Note that I use imwrite to save the crop to file and it's named based on what blob ID you're looking at. Therefore, if there are multiple blobs or round objects that satisfy the criteria, you will be saving them all.

Upvotes: 2

Related Questions