Ask Your Question
0

How to specify mask for grabCut in C++

asked 2013-05-30 14:10:22 -0600

pixelsitter gravatar image

I'm just starting with opencv and can't find any samples. I would like to use GC_INIT_WITH_MASK, how do you specify the mask to grabCut if I have two rectangles: outer and inner.

cv::Rect outer = values cv::Rect inner = values for inner rectangle sits inside outer rectangle

cv::Mat mask = ??

Thanks in advance, Tom

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
5

answered 2013-05-30 15:24:07 -0600

Guanta gravatar image

What are your inner and outer-rectangles? One is your foreground and the other your background? What do you not understand from the docu (http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html?highlight=grabcut#grabcut) ?

There exist also an example: <your-opencv-folder>/samples/cpp/grabcut.cpp

Maybe another example helps, in which I assumed that the middle-portion of the image is definitely foreground and the first 5 rows of the image are definitely background:

cv::Mat1b markers(img.rows, img.cols);
// let's set all of them to possible background first
markers.setTo(cv::GC_PR_BGD);

// cut out a small area in the middle of the image
int m_rows = 0.1 * img.rows;
int m_cols = 0.1 * img.cols;
// of course here you could also use cv::Rect() instead of cv::Range to select 
// the region of interest
cv::Mat1b fg_seed = markers(cv::Range(img.rows/2 - m_rows/2, img.rows/2 + m_rows/2), 
                            cv::Range(img.cols/2 - m_cols/2, img.cols/2 + m_cols/2));
// mark it as foreground
fg_seed.setTo(cv::GC_FGD);

// select first 5 rows of the image as background
cv::Mat1b bg_seed = markers(cv::Range(0, 5),cv::Range::all());
bg_seed.setTo(cv::GC_BGD);

cv::Mat bgd, fgd;
int iterations = 1;
cv::grabCut(img, markers, cv::Rect(), bgd, fgd, iterations, cv::GC_INIT_WITH_MASK);

// let's get all foreground and possible foreground pixels
cv::Mat1b mask_fgpf = ( markers == cv::GC_FGD) | ( markers == cv::GC_PR_FGD);
// and copy all the foreground-pixels to a temporary image
cv::Mat3b tmp = cv::Mat3b::zeros(img.rows, img.cols);
img.copyTo(tmp, mask_fgpf);
// show it
cv::imshow("foreground", tmp);
cv::waitKey(0);

Please forgive me any errors in the code, I just wrote it from scratch.

edit flag offensive delete link more

Comments

This has help a great deal but fg_seed and bg_seed doesn't appear to get used anywhere. They get set from markers but markers itself doesn't get any settings.

pixelsitter gravatar imagepixelsitter ( 2013-05-30 17:03:20 -0600 )edit

It does! First markers-matrix is completely set to possible background (cv::GC_PR_BGD), then some regions of markers (namely fg_seed and bg_seed, which are just region of interests - the data is actually hold by markers) are set to foreground and background.

Guanta gravatar imageGuanta ( 2013-05-30 17:54:19 -0600 )edit

If I use your example as Range(0,5), the image is segmented properly but if I use the rectOuter I get a blank image: // image size is 968 x 800

Rect rectInner(397,657, 75, 78); Rect rectOuter(301,558,269,303);

cv::Mat1b fg_seed = markers(rectInner); fg_seed.setTo(cv::GC_FGD);

cv::Mat1b bg_seed = markers(cv::Range(rectOuter.x,rectOuter.x+rectOuter.width), cv::Range(rectOuter.y, rectOuter.y+rectOuter.height); bg_seed.setTo(cv::GC_BGD);

pixelsitter gravatar imagepixelsitter ( 2013-05-30 21:18:54 -0600 )edit

Since your bg_rect includes your fg_seed you have to change the order. First set bg_seed than fg_seed, otherwise your fg_seed will always be overwritten!

Guanta gravatar imageGuanta ( 2013-05-31 07:26:45 -0600 )edit

Very helpful! I have not seen a snippet online that did the grabcut as well! Good job!

the___doctor gravatar imagethe___doctor ( 2014-07-03 21:48:30 -0600 )edit

how to solve this problem in JavaCV? need urgent guys :|

swag gravatar imageswag ( 2014-08-21 08:02:09 -0600 )edit

Question Tools

Stats

Asked: 2013-05-30 14:10:22 -0600

Seen: 8,899 times

Last updated: May 30 '13