Ask Your Question
5

How to set transparent background to grabcut output image in OpenCV (C++)?

asked 2014-07-17 10:11:02 -0600

nena gravatar image

updated 2020-11-28 06:09:58 -0600

Hi I'm using the grabcut algorithm to remove the background of an image, and currently I get these results: image description

What I want is that the background to be transparent instead of black. I tried the suggestions I found here: http://answers.opencv.org/question/24463/how-to-remove-black-background-from-grabcut-output/#24508

which led me to this result: image description

What I want is that my program doesn't depend on the colors of the image, since any color can be part of the foreground. As far as I understood, thresholding performs the image segmentation based on colors, so I can't use it.

I've read something about blob and edge detection but I didn't manage to implement it. So I need help. Thanks

edit retag flag offensive close merge delete

Comments

@nena can you share me the code for background subtraction which produce the output for the first image?

Aj-611 gravatar imageAj-611 ( 2016-02-16 02:05:05 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2014-07-18 03:46:31 -0600

Haris gravatar image

updated 2014-07-18 03:48:05 -0600

You need to do,

See below code,

Mat src=imread("a.png",1);
Mat dst;//(src.rows,src.cols,CV_8UC4);
Mat tmp,thr;

cvtColor(src,tmp,CV_BGR2GRAY);
threshold(tmp,thr,100,255,THRESH_BINARY);

 vector< vector <Point> > contours; // Vector for storing contour
     vector< Vec4i > hierarchy;
     int largest_contour_index=0;
     int largest_area=0;

Mat alpha(src.size(),CV_8UC1,Scalar(0));
findContours( tmp, contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
    for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
      {
       double a=contourArea( contours[i],false);  //  Find the area of contour
       if(a>largest_area){
       largest_area=a;
       largest_contour_index=i;                //Store the index of largest contour
       }
      }
drawContours( alpha,contours, largest_contour_index, Scalar(255),CV_FILLED, 8, hierarchy );

Mat rgb[3];
split(src,rgb);

Mat rgba[4]={rgb[0],rgb[1],rgb[2],alpha};
merge(rgba,4,dst);
imwrite("dst.png",dst);

Note:

To keep the edge smooth check out below links,

http://stackoverflow.com/questions/21795643/image-edge-smoothing-with-opencv

http://stackoverflow.com/questions/17161088/how-to-refine-or-blur-or-smooth-just-the-edges

image description

image description

edit flag offensive delete link more

Comments

I reused the same mask which I found using grabcut instead of looking for the contours, and then split the image. That worked perfectly well. Thank you so much!

nena gravatar imagenena ( 2014-07-24 05:17:19 -0600 )edit

Can you maybe suggest a way of improving the performance?

nena gravatar imagenena ( 2014-07-24 05:18:55 -0600 )edit

You mean process time?

Haris gravatar imageHaris ( 2014-07-24 05:48:37 -0600 )edit

Exactly. I am working on a user friendly app for removing the background and I want it to work very fast even for large resolution images, which is not the case now.

nena gravatar imagenena ( 2014-07-24 06:30:45 -0600 )edit
1

The processing time mainly depend on image size, to improve it you could do something like down-sample image, perform grabcut, create mask, up-sample the mask and finally segment the image using up sampled mask. You can see an implementation here.

Haris gravatar imageHaris ( 2014-07-25 00:47:35 -0600 )edit

Great idea, thank you!

nena gravatar imagenena ( 2014-07-25 04:37:25 -0600 )edit

You are welcome.

Haris gravatar imageHaris ( 2014-07-25 22:51:29 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2014-07-17 10:11:02 -0600

Seen: 15,288 times

Last updated: Jul 18 '14