2013-07-17 89 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