2013-07-17 12 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の私の2番目の質問です。慣例に従わなければ謝罪します。

答えて

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

真。私たちは両方を保つ必要があります。これはおそらくもう1つのコード行を意味します。 – William

0

だけの小さな提案、@William's 答えは、より簡潔に書くことができます。

result = result & 1; 

バイナリマスクを得るために。

0

画像の中央部分が前景であると仮定した別の例が役立つかもしれません。 このリンクを試してください。 enter link description here