Grabcut mask values
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];
}
Please gives opencv version and platform. Gives source too.
Updated the question with more information.
I think you miss something in grabcut algorithm. At the beginning all pixels in mask are GC_BGD. Then you select a rectangle. Inside this rect there is an object . All pixels in rectangle are GC_PR_FGD. Then you run grabcut grabcut is looking for background pixel in rect using stat (and neighborhood constraints) of pixels marked GC_BGD.
When pixel in mask are GC_BGD or GC_FGD pixels state will never changed
You can improve speed of your program : first loop in c++
I'm sure I miss a lot here, there are some things I cannot understand in the Python example (grabcut.py).
First, the mask seems to be initialized to zeros (BG), but the comment says PR_BG:
Then, on each iteration, the bgdmodel and fgdmodel are cleared. Why?
Thanks for the help!
constant are defined here
I don't know python but 0=GC_PR_BGD so there is typo erreur
About bgdmodel and fgdmodel in python example : i don't know python. But it is not logical to erase bgdmodel and fgdmodel before a new iteration. But here it is not exactly a new iteration because mask changed. Model must be calculated with new initial condition.