0

Please anyone help me to resolve my issue. I am working on image processing based project and I stuck at a point. I got this image after some processing and for further processing i need to crop or detect only deer and remove other portion of image.

This is my Initial image:

enter image description here

And my result should be something like this:

enter image description here

It will be more better if I get only a single biggest blob in the image and save it as a image.

Divakar
  • 218,885
  • 19
  • 262
  • 358
Gujjar
  • 367
  • 1
  • 5
  • 24

3 Answers3

6

It looks like the deer in your image is pretty much connected and closed. What we can do is use regionprops to find all of the bounding boxes in your image. Once we do this, we can find the bounding box that gives the largest area, which will presumably be your deer. Once we find this bounding box, we can crop your image and focus on the deer entirely. As such, assuming your image is stored in im, do this:

im = im2bw(im); %// Just in case...
bound = regionprops(im, 'BoundingBox', 'Area'); 

%// Obtaining Bounding Box co-ordinates
bboxes = reshape([bound.BoundingBox], 4, []).';

%// Obtain the areas within each bounding box
areas = [bound.Area].';

%// Figure out which bounding box has the maximum area
[~,maxInd] = max(areas);

%// Obtain this bounding box
%// Ensure all floating point is removed
finalBB = floor(bboxes(maxInd,:));

%// Crop the image
out = im(finalBB(2):finalBB(2)+finalBB(4), finalBB(1):finalBB(1)+finalBB(3));

%// Show the images
figure;
subplot(1,2,1);
imshow(im);
subplot(1,2,2);
imshow(out);

Let's go through this code slowly. We first convert the image to binary just in case. Your image may be an RGB image with intensities of 0 or 255... I can't say for sure, so let's just do a binary conversion just in case. We then call regionprops with the BoundingBox property to find every bounding box of every unique object in the image. This bounding box is the minimum spanning bounding box to ensure that the object is contained within it. Each bounding box is a 4 element array that is structured like so:

[x y w h]

Each bounding box is delineated by its origin at the top left corner of the box, denoted as x and y, where x is the horizontal co-ordinate while y is the vertical co-ordinate. x increases positively from left to right, while y increases positively from top to bottom. w,h are the width and height of the bounding box. Because these points are in a structure, I extract them and place them into a single 1D vector, then reshape it so that it becomes a M x 4 matrix. Bear in mind that this is the only way that I know of that can extract values in arrays for each structuring element efficiently without any for loops. This will facilitate our searching to be quicker. I have also done the same for the Area property. For each bounding box we have in our image, we also have the attribute of the total area encapsulated within the bounding box.

Thanks to @Shai for the spot, we can't simply use the bounding box co-ordinates to determine whether or not something has the biggest area within it as we could have a thin diagonal line that could drive the bounding box co-ordinates to be higher. As such, we also need to rely on the total area that the object takes up within the bounding box as well. Simply put, it's just the sum of all of the pixels that are contained within the object.

Therefore, we search the entire area vector that we have created to see which has the maximum area. This corresponds to your deer. Once we find this location, extract the bounding box locations, then use this to crop the image. Bear in mind that the bounding box values may have floating point numbers. As the image co-ordinates are in integer based, we need to remove these floating point values before we decide to crop. I decided to use floor. I then write code that displays the original image, with the cropped result.

Bear in mind that this will only work if there is just one object in the image. If you want to find multiple objects, check bwboundaries in MATLAB. Otherwise, I believe this should get you started.

Just for completeness, we get the following result:

enter image description here

rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • 1
    one cavity: you choose the region based on its **BB** area rather than its **actual** area. Imagine a thin diagonal line - BB area very large while actual area very small... You might consider using `'Area'` property to select the region. – Shai Jun 19 '14 at 15:46
  • @Shai - Edit complete. Did not take much effort. Thank you for the spot. – rayryeng Jun 19 '14 at 15:50
  • Error using reshape Product of known dimensions, 4, not divisible into total number of elements, 1530. – Gujjar Jun 19 '14 at 15:52
  • @rayryeng can you please check for my origional image and then compile. I am using Matlab 2014a. – Gujjar Jun 19 '14 at 15:54
  • @AsifSharif This ran on my machine..... I never post code on here that isn't tested by myself. If it didn't run, I wouldn't have been able to produce the image you see in my post. I used the input image that you supplied in your original post. – rayryeng Jun 19 '14 at 16:46
1

While object detection is a very general CV task, you can start with something simple if the assumptions are strong enough and you can guarantee that the input images will contain a single prominent white blob well described by a bounding box.

One very simple idea is to subdivide the picture in 3x3=9 patches, calculate the statistics for each patch and compute some objective function. In the most simple case you just do a grid search over various partitions and select that with the highest objective metric. Here's an illustration:

enter image description here

If every line is a parameter x_1, x_2, y_1 and y_2, then you want to optimize

enter image description here

either by

The target function F can be define over statistics of the patches, e.g. like this

F(9 patches) {
  brightest_patch = max(patches)
  others          = patches \ brightest_patch
  score           = brightness(brightest_patch) - 1/8 * brightness(others)
  return score
}

or anything else that incorporates relevant statistics of the patches as well as their size. This also allows to incorporate a "prior knowledge": if you expect the blob to appear in the middle of the image, then you can define a "regularization" term that will penalize F if the parameters x_i and y_i deviate from the expected position too much.

Pavel
  • 7,436
  • 2
  • 29
  • 42
1

Thanks to all who answer and comment on my Question. With your help I got my exact solution. I am posting my final code and result for others.

img = im2bw(imread('deer.png'));
[L, num] = bwlabel(img, 4);

 %%//  Get biggest blob or object
count_pixels_per_obj = sum(bsxfun(@eq,L(:),1:num));
[~,ind] = max(count_pixels_per_obj);
biggest_blob = (L==ind);

%%// crop only deer
bound = regionprops(biggest_blob, 'BoundingBox');

%// Obtaining Bounding Box co-ordinates
bboxes = reshape([bound.BoundingBox], 4, []).';

%// Obtain this bounding box
%// Ensure all floating point is removed
finalBB = floor(bboxes);
out = biggest_blob(finalBB(2):finalBB(2)+finalBB(4),finalBB(1):finalBB(1)+finalBB(3));

%%// Show images
figure;
imshow(out);

enter image description here

Gujjar
  • 367
  • 1
  • 5
  • 24