2017-01-17 5 views
1

Wie kann ich einen nicht rechteckigen Bereich von Bild beschneiden?OpenCV - Cropping nicht rechteckigen Bereich von Bild C++

Stellen Ich habe vier Punkte und ich möchte es beschneiden, diese Form wäre nicht ein Dreieck irgendwie sein!

Zum Beispiel habe ich folgendes Bild:

enter image description here

und ich möchte dies aus Bild zuzuschneiden:

enter image description here

Wie kann ich das tun? Grüße ..

+0

Wie Sie auf die Region entscheiden wollen, zu beschneiden? Willst du die Ernte, die du gezeigt hast, immer blind machen? Oder willst du die ganze Zeit eine Raute? Im Allgemeinen können Sie die bitwise_and -Funktion von OpenCV verwenden, um einen Teil des Bildes zu maskieren, aber das Erzeugen der Maske erfordert mehr Details. –

+0

die Region wäre keine Konstante meine ich es in irgendeiner Form sein würde, aber immer hat es vier Ecken –

Antwort

5

Das Verfahren für ein beliebiges Viereck Zuschneiden (oder ein Polygon für diese Angelegenheit) Teil eines Bildes wird uns als summierten:

  • Erzeugen Sie eine „Maske“. Die Maske ist schwarz, wo Sie das Bild behalten möchten, und weiß, wo Sie nicht wollen, es zu halten
  • Berechne die „bitwise_and“ zwischen dem Eingangsbild und dem Masken

Also, Sie können davon ausgehen müssen, ein Bild. In diesem Zusammenhang verwende ich zur Vereinfachung eine Bildgröße von 30 x 30, die Sie je nach Anwendungsfall ändern können.

cv::Mat source_image = cv::imread("filename.txt"); 

Und Sie haben vier Punkte, die Sie als die Ecken verwenden möchten:

cv::Point corners[1][4]; 
corners[0][0] = Point(10, 10); 
corners[0][1] = Point(20, 20); 
corners[0][2] = Point(30, 10); 
corners[0][3] = Point(20, 10); 
const Point* corner_list[1] = { corners[0] }; 

können Sie die Funktion verwenden cv::fillPoly auf einer Maske diese Form zu zeichnen:

int num_points = 4; 
int num_polygons = 1; 
int line_type = 8; 
cv::Mat mask(30,30,CV_8UC3, cv::Scalar(0,0,0)); 
cv::fillPoly(mask, corner_list, &num_points, num_polygons, cv::Scalar(255, 255, 255), line_type); 

Dann einfach berechnen den bitwise_and des Bildes und Maske:

cv::Mat result; 
cv::bitwise_and(source_image, mask, result); 

result hat jetzt das beschnittene Bild in ihm. Wenn Sie die Kanten am Ende weiß statt schwarz wünschen könnte man stattdessen tun:

cv::Mat result_white(30,30,CV_8UC3, cv::Scalar(255,255,255)); 
cv::bitwise_and(source_image, mask, result_white, mask); 

In diesem Fall sind wir nur bitwise_and ‚s Maske Parameter verwenden, um den bitwise_and in der Maske zu tun. Weitere Informationen und Links zu allen genannten Funktionen finden Sie unter this tutorial.

+0

aktualisiert, danke. –

+0

I „keine passende Funktion‚fillPoly‘Fehler :(hab mir bitte helfen: https://stackoverflow.com/q/45441744/3162918 – bendaf

+1

Danke für den Hinweis, dass Fehler aus. Ich habe meine Antwort aktualisiert ich brauchte num_points passieren als Zeiger. –

1

können Sie cv verwenden :: Mat :: copyTo() wie folgt aus:

cv::Mat img = cv::imread("image.jpeg"); 
// note mask may be single channel, even if img is multichannel 
cv::Mat mask = cv::Mat::zeros(img.rows, img.cols, CV_8UC1); 
// fill mask with nonzero values, e.g. as Tim suggests 
// cv::fillPoly(...) 
cv::Mat result(img.size(), img.type(), cv::Scalar(255, 255, 255)); 
img.copyTo(result, mask);