The documentation for GrabCut says this about the mask parameter:
@param mask Input/output 8-bit single-channel mask. The mask is initialized by the function when
mode is set to GC_INIT_WITH_RECT. Its elements may have one of the cv::GrabCutClasses.
The first time I invoke grabCut it runs successfully and the mask is initialised. But the second time I do it, using the mask and mode == GC_INIT_WITH_MASK, I get the following error:
OpenCV Error: Bad argument (mask element value must be equal GC_BGD or GC_FGD or GC_PR_BGD or GC_PR_FGD) in checkMask, file /Volumes/build-storage/build/master_iOS-mac/opencv/modules/imgproc/src/grabcut.cpp, line 337
The values in the mask matrix are either 0 or 255, when I was expecting 0-3. Does this make sense? I am doing anything wrong?
Update: I am using version 3.2.0 for the iPhone. The crash does not happen if I replace pixels with 255 with 1 (GC_FGD), but then all I get is a completely transparent image.
Here is my main code block, in Objective C. Some ivar and properties (i.e., _mask and self.mask are the same thing.
- (UIImage *)processImage {
if (!self.firstRun) {
for( int y = 0; y < _mask.rows; y++ ) {
for( int x = 0; x < _mask.cols; x++ ) {
uchar val = _mask.at<uchar>(y,x);
if (val == 255) {
_mask.at<uchar>(y,x) = GC_FGD;
}
}
}
for (NSValue *r in self.foregroundPoints) {
rectangle(_mask, cvRectFromCGRect(r.CGRectValue), GC_FGD);
}
for (NSValue *r in self.backgroundPoints) {
rectangle(_mask, cvRectFromCGRect(r.CGRectValue), GC_BGD);
}
}
grabCut(_inputImageMat,
_mask,
cvRectFromCGRect(_rect),
_bgModel,
_fgModel,
1, // number of iterations
_firstRun ? cv::GC_INIT_WITH_RECT : cv::GC_INIT_WITH_MASK);
self.firstRun = false;
Mat image = self.inputImageMat.clone();
// Get the pixels marked as likely foreground
cv::compare(self.mask, cv::GC_PR_FGD, self.mask, cv::CMP_EQ);
// Generate output image
cv::Mat foreground(image.size(), CV_8UC3, cv::Scalar(255, 0, 255));
image.copyTo(foreground, self.mask); // bg pixels not copied
// image has magenta on transparent sections. replace before using
return [UIImage imageWithCVMat:foreground];
}