Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extracting Background Image Using GrabCut

Tags:

c++

opencv

I've an image (.jpg image), and I want to extract the background from the original image. I've googled a lot but have only found tutorials of extracting foreground image.

I've taken the code from another stackoverflow question. The code is working fine for me, and I've successfully extracted the foreground (as per my requirements). Now I want to completely remove this foreground from the original image. I want it to be something like this:-

Background = Original Image - Foreground

The empty space can be filled with black or white color. How can I achieve this?

I've tried using this technique:-

Mat background = image2 - foreground;

but it gives a complete black image.

Code:-

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( )
{
// Open another image
Mat image;
image= cv::imread("images/abc.jpg");

Mat image2 = image.clone();

// define bounding rectangle
cv::Rect rectangle(40,90,image.cols-80,image.rows-170);

cv::Mat result; // segmentation result (4 possible values)
cv::Mat bgModel,fgModel; // the models (internally used)

// GrabCut segmentation
cv::grabCut(image,    // input image
            result,   // segmentation result
            rectangle,// rectangle containing foreground
            bgModel,fgModel, // models
            1,        // number of iterations
            cv::GC_INIT_WITH_RECT); // use rectangle
cout << "oks pa dito" <<endl;
// Get the pixels marked as likely foreground
cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
// Generate output image
cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255));
//cv::Mat background(image.size(),CV_8UC3,cv::Scalar(255,255,255));
image.copyTo(foreground,result); // bg pixels not copied

// draw rectangle on original image
cv::rectangle(image, rectangle, cv::Scalar(255,255,255),1);

imwrite("img_1.jpg",image);

imwrite("Foreground.jpg",foreground);
Mat background = image2 - foreground;
imwrite("Background.jpg",background);

return 0;
}

Note: I'm an opencv beginner and don't have much knowledge of it right now. I shall be very thankful to you if you can either post the complete code (as required by me) or just post the lines of code and tell me where these lines of code be placed. Thanks.

P.S. This is my second question at StackOverflow.com. apologies ... if not following any convention.

like image 468
Omar Tariq Avatar asked Jul 17 '13 11:07

Omar Tariq


People also ask

How does GrabCut work?

GrabCut is an image segmentation method based on graph cuts. Starting with a user-specified bounding box around the object to be segmented, the algorithm estimates the color distribution of the target object and that of the background using a Gaussian mixture model.

How do I use GrabCut in OpenCV?

The GrabCut algorithm is implemented in OpenCV via the cv2. grabCut function and can be initialized via either: A bounding box that specifies the location of the object you want to segment in the input image. A mask that approximates the pixel-wise location of the object in the image.

How do you separate background from foreground OpenCV?

BackgroundSubtractorMOG2() is used to remove the background from video frames. When it comes to images you can use the GrabCut Algorithm . The OpenCV documentation contains a tutorial including the relevant Python code.

What is foreground extraction?

The idea here is to find the foreground, and remove the background. Foreground extract is any technique which allows an image's foreground to be extracted for further processing like object recognition, tracking etc. The algorithm used for foreground extraction here is GrabCut Algorithm.


1 Answers

Instead of copying all the pixels that are foreground, it copies all pixels which are not foreground. You can do this by using ~, which negates the mask:

image.copyTo(background,~result);
like image 186
sietschie Avatar answered Sep 19 '22 19:09

sietschie