2013-07-17 52 views
7

我有一个图像(.jpg图像),我想从原始图像中提取背景。我搜索了很多,但只找到了提取前景图片的教程。使用GrabCut提取背景图像

我已经从另一个stackoverflow question采取了代码。代码对我来说工作正常,并且我已经成功地提取了前景(按照我的要求)。现在我想从原始图像中彻底删除这个前景。我希望它是这样的: -

背景=原始图像 - 前景

空的空间可填充为黑色或白色。我怎样才能做到这一点?

我已经使用这种技术尝试: -

Mat background = image2 - foreground; 

,但它给出了一个完整的黑色图像。

代码: -

#include <opencv2/opencv.hpp> 
#include <iostream> 

using namespace cv; 
using namespace std; 

int main() 
{ 
// Open another image 
Mat image; 
image= cv::imread("images/abc.jpg"); 

Mat image2 = image.clone(); 

// define bounding rectangle 
cv::Rect rectangle(40,90,image.cols-80,image.rows-170); 

cv::Mat result; // segmentation result (4 possible values) 
cv::Mat bgModel,fgModel; // the models (internally used) 

// GrabCut segmentation 
cv::grabCut(image, // input image 
      result, // segmentation result 
      rectangle,// rectangle containing foreground 
      bgModel,fgModel, // models 
      1,  // number of iterations 
      cv::GC_INIT_WITH_RECT); // use rectangle 
cout << "oks pa dito" <<endl; 
// 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)); 
//cv::Mat background(image.size(),CV_8UC3,cv::Scalar(255,255,255)); 
image.copyTo(foreground,result); // bg pixels not copied 

// draw rectangle on original image 
cv::rectangle(image, rectangle, cv::Scalar(255,255,255),1); 

imwrite("img_1.jpg",image); 

imwrite("Foreground.jpg",foreground); 
Mat background = image2 - foreground; 
imwrite("Background.jpg",background); 

return 0; 
} 

注:我是一个初学者的OpenCV并没有它的很多知识现在。如果您可以发布完整的代码(根据我的要求)或者只是发布代码行并告诉我这些代码行的位置,我会非常感谢您。谢谢。

P.S.这是我在StackOverflow.com上的第二个问题。道歉...如果不遵循任何惯例。

回答

12

不是复制所有前景像素,而是复制所有不是前景的像素。您可以通过使用~,这否定了做面膜的:

image.copyTo(background,~result); 
+0

你钉了它。谢谢:-) –

3

,如果你有什么//Get the pixels marked as likely background

// Get the pixels marked as likely background 
cv::compare(result,cv::GC_PR_BGD,result,cv::CMP_EQ); 

编辑:上面的代码缺少GC_BGD像素。尽管更有效的答案给出,让我们完成我们开始:

// Get the pixels marked as background 
cv::compare(result,cv::GC_BGD,result_a,cv::CMP_EQ); 
// Get the pixels marked as likely background 
cv::compare(result,cv::GC_PR_BGD,result_b,cv::CMP_EQ); 
// Final results 
result=result_a+result_b; 
+0

是的,它删除了前景,但它也将图像裁剪为我指定的矩形。谢谢回答。 –

+0

问题是,有些像素被标记为'GC_PR_BGD'(可能是背景),另一些像'GC_BGD',这意味着它们肯定是背景,因为它们已经作为算法的输入。 – sietschie

+0

是的。我们需要保持这两个意思,也许再多一行代码。 – William

0

只是一个小小的建议,@William's 答案可以更简洁的写成:

result = result & 1; 

,以获得二进制掩码。

0

也许另一个例子有帮助,我认为图像的中间部分绝对是前景。 因此请尝试此链接。 enter link description here