OpenCV 4 Computer Vision Application Programming Cookbook(Fourth Edition)
上QQ阅读APP看书,第一时间看更新

How to do it...

The cv::grabCut function is easy to use. You just need to input an image and label some of its pixels as belonging to the background or to the foreground. Based on this partial labeling, the algorithm will then determine a foreground/background segmentation for the complete image, as shown in the following steps:

  1. One way to specify a partial foreground/background labeling for an input image is to define a rectangle inside which the foreground object is included:
// define bounding rectangle 
// the pixels outside this rectangle
// will be labeled as background
cv::Rect rectangle(5,70,260,120);

This defines the following area in the image:

All the pixels outside this rectangle will then be marked as background, in addition to the input image and its segmentation image.

  1. Calling the cv::grabCut function requires the definition of two matrices, which will contain the models built by the algorithm, as follows:
cv::Mat result; // segmentation (4 possible values)
// GrabCut segmentation
cv::grabCut(image, // input image
result, // segmentation result
rectangle,// rectangle containing foreground
bgModel, fgModel, // models
5, // number of iterations
cv::GC_INIT_WITH_RECT); // use rectangle

Note how we specified that we are using the bounding rectangle mode with the cv::GC_INIT_WITH_RECT flag as the last argument of the function (the next section, How it works..., will discuss the other available mode).

  1. The input/output segmentation image can have one of the following four values:
  • cv::GC_BGD: This is the value of the pixels that certainly belong to the background (for example, pixels outside the rectangle, in our example)
  • cv::GC_FGD: This is the value of the pixels that certainly belong to the foreground (there are none in our example)
  • cv::GC_PR_BGD: This is the value of the pixels that probably belong to the background
  • cv::GC_PR_FGD: This is the value of the pixels that probably belong to the foreground (that is, the initial value of the pixels inside the rectangle in our example)
  1. We get a binary image of the segmentation by extracting the pixels that have a value equal to cv::GC_PR_FGD. This is accomplished with the following code:
// 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));
image.copyTo(foreground,// bg pixels are notcopied
result);
  1. To extract all the foreground pixels, that is, with values equal to cv::GC_PR_FGD or cv::GC_FGD, it is possible to check the value of the first bit, as follows:
// checking first bit with bitwise-and 
result= result&1; // will be 1 if FG

This is possible because these constants are defined as the values 1 and 3, while the other two (cv::GC_BGD and cv::GC_PR_BGD) are defined as 0 and 2. In our example, the same result is obtained because the segmentation image does not contain the cv::GC_FGD pixels (only the cv::GC_BGD pixels have been included).

The following image is then obtained:

Now, let's go behind the scenes to understand the code better.