2013-07-17 14 views
7

Ich habe ein Bild (.jpg Bild), und ich möchte den Hintergrund aus dem Originalbild extrahieren. Ich habe viel gegooglet, aber habe nur Tutorials gefunden, um das Vordergrundbild zu extrahieren.Hintergrund mit GrabCut extrahieren

Ich habe den Code von einem anderen stackoverflow question genommen. Der Code funktioniert gut für mich, und ich habe erfolgreich den Vordergrund extrahiert (gemäß meinen Anforderungen). Jetzt möchte ich diesen Vordergrund vollständig aus dem Originalbild entfernen. Ich mag es so etwas sein: -

Hintergrund = Originalbild - Vordergrund

Der leere Raum kann mit schwarzer oder weißer Farbe gefüllt werden. Wie kann ich das erreichen?

Ich habe mit dieser Technik versucht: -

Mat background = image2 - foreground; 

aber es gibt ein komplettes schwarzes Bild.

Code: -

#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; 
} 

Hinweis: Ich bin ein opencv Anfänger und nicht viel Kenntnis davon haben jetzt. Ich werde Ihnen sehr dankbar sein, wenn Sie entweder den vollständigen Code (wie von mir gefordert) posten oder einfach die Codezeilen posten und mir sagen können, wo diese Codezeilen platziert werden. Vielen Dank.

P.S. Dies ist meine zweite Frage bei StackOverflow.com. Entschuldigung ... wenn keine Konvention eingehalten wird.

Antwort

12

Anstatt alle Pixel im Vordergrund zu kopieren, werden alle Pixel kopiert, die nicht Vordergrund sind. Sie können dies tun, indem ~ verwenden, die die Maske negiert:

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

Sie haben es genagelt. Danke :-) –

3

Was passiert, wenn Sie //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); 

bearbeiten: Der obige Code GC_BGD Pixel fehlt. Trotz eine effizientere Antwort gegeben wurde, wollen wir beenden, was wir angefangen haben:

// 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

Ja, es entfernt den Vordergrund, aber es schneidet auch das Bild auf das Rechteck, das ich angegeben habe. Danke für die Antwort. –

+0

Das Problem ist, dass einige Pixel als 'GC_PR_BGD' (wahrscheinlich Hintergrund) und einige als' GC_BGD' markiert sind, was bedeutet, dass sie sicher Hintergrund sind, da sie als Eingabe für den Algorithmus angegeben wurden. – sietschie

+0

Wahr. Wir müssen beide behalten, was vielleicht eine weitere Codezeile bedeutet. – William

0

Nur eine kleine Anregung, @William's Antwort prägnanter als geschrieben werden kann:

result = result & 1; 

, um die binäre Maske zu erhalten .

0

Vielleicht hilft ein anderes Beispiel, bei dem ich angenommen habe, dass der mittlere Teil des Bildes definitiv Vordergrund ist. Also versuchen Sie diesen Link. enter link description here