Search code examples
image-processingmatlabmatlab-cvst

Eliminating various backgrounds from image and segmenting object?


Let say I have this input image, with any number of boxes. I want to segment out these boxes, so I can eventually extract them out. input image:

The background could anything that is continuous, like a painted wall, wooden table, carpet. My idea was that the gradient would be the same throughout the background, and with a constant gradient. I could turn where the gradient is about the same, into zero's in the image.

Through edge detection, I would dilate and fill the regions where edges detected. Essentially my goal is to make a blob of the areas where the boxes are. Having the blobs, I would know the exact location of the boxes, thus being able to crop out the boxes from the input image. So in this case, I should be able to have four blobs, and then I would be able to crop out four images from the input image.

This is how far I got: segmented image:

query = imread('AllFour.jpg');
gray = rgb2gray(query);
[~, threshold] = edge(gray, 'sobel');
weightedFactor = 1.5;
BWs = edge(gray,'roberts');
%figure, imshow(BWs), title('binary gradient mask');

se90 = strel('disk', 30);
se0 = strel('square', 3);

BWsdil = imdilate(BWs, [se90]);
%figure, imshow(BWsdil), title('dilated gradient mask');

BWdfill = imfill(BWsdil, 'holes');
figure, imshow(BWdfill);
title('binary image with filled holes');

Solution

  • What a very interesting problem! Here's my solution in an attempt to solve this problem for you. This is assuming that the background has the same colour distribution throughout. First, transform your image from RGB to the HSV colour space with rgb2hsv. The HSV colour space is an ideal transform for analyzing colours. After this, I would look at the saturation and value planes. Saturation is concerned with how "pure" the colour is, while value is the intensity or brightness of the colour itself. If you take a look at the saturation and value planes for the image, this is what is shown:

    im = imread('https://i.sstatic.net/1SGVm.jpg');
    out = rgb2hsv(im);
    figure;
    subplot(2,1,1);
    imshow(out(:,:,2));
    subplot(2,1,2);
    imshow(out(:,:,3));
    

    This is what I get:

    enter image description here

    By taking a look at some locations in the gray background, it looks like the majority of the saturation are less than 0.2 as well as the elements in the value plane are greater than 0.3. As such, we want to find the opposite of those pixels to get our objects. As such, we find those pixels whose saturation is greater than 0.2 or those pixels with a value that is less than 0.3:

    seg = out(:,:,2) > 0.2 | out(:,:,3) < 0.3;
    

    This is what we get:

    enter image description here

    Almost there! There are some spurious single pixels, so I'm going to perform an opening with imopen with a line structuring element.

    After this, I'll perform a dilation with imdilate to close any gaps, then use imfill with the 'holes' option to fill in the gaps, then use erosion with imerode to shrink the shapes back to their original form. As such:

    se = strel('line', 3, 90);
    pre = imopen(seg, c);
    se = strel('square', 20);
    pre2 = imdilate(pre, se);
    pre3 = imfill(pre2, 'holes');
    final = imerode(pre3, se);
    figure;
    imshow(final);
    

    final contains the segmented image with the 4 candy boxes. This is what I get:

    enter image description here