2016-04-21 12 views
1

So können Sie mehrere Objekte aus einem Bild zuschneiden, indem Sie mit der Maus mithilfe von OpenCV eine Bindungsbox zeichnen. Bitte beachten Sie das Bild unten:Wie können Sie mehrere Objekte aus einem Bild zuschneiden, indem Sie Begrenzungsrahmen (oder Polygone) zeichnen?

enter image description here

Ich möchte die Coladosen Grenzen mit Mausklicks wählen und sie beschneiden.

Ich bin in der Lage zu einzelnes Polygon zu zeichnen, aber nicht ein Vielfaches:

Need Lösung, um mehrere Polygone auf Objekte auswählen zu zeichnen. hier ist der Code:

Leere mouseHandler (int Ereignis, int x, int y, int, void *) {

if (event == EVENT_LBUTTONDOWN && !drag) 
{ 
    if (flag1 == 0) 
    { 
     if (var == 0) 
      img1 = img0.clone(); 
     point = Point(x, y); 
     circle(img1, point, 2, Scalar(0, 0, 255), -1, 8, 0); 
     pts[var] = point; 
     var++; 
     drag = 1; 
     if (var>1) 
      line(img1, pts[var - 2], point, Scalar(0, 0, 255), 2, 8, 0); 

     imshow("Source", img1); 
    } 
} 

if (event == EVENT_LBUTTONUP && drag) 
{ 
    imshow("Source", img1); 

    drag = 0; 
} 
if (event == EVENT_RBUTTONDOWN) 
{ 
    flag1 = 1; 
    img1 = img0.clone(); 
    for (int i = var; i < numpts; i++) 
     pts[i] = point; 

    if (var != 0) 
    { 
     const Point* pts3[1] = { &pts[0] }; 
     polylines(img1, pts3, &numpts, 1, 1, Scalar(0, 0, 0), 2, 8, 0); 
    } 

    for (int i = 0; i<var; i++) 
    { 
     minx = min(minx, pts[i].x); 
     maxx = max(maxx, pts[i].x); 
     miny = min(miny, pts[i].y); 
     maxy = max(maxy, pts[i].y); 
    } 
    lenx = maxx - minx; 
    leny = maxy - miny; 

    imshow("Source", img1); 
} 

if (event == EVENT_RBUTTONUP) 
{ 
    flag = var; 

    final = Mat::zeros(img0.size(), CV_8UC3); 
    res1 = Mat::zeros(img0.size(), CV_8UC1); 
    const Point* pts4[1] = { &pts[0] }; 

    fillPoly(res1, pts4, &numpts, 1, Scalar(255, 255, 255), 8, 0); 
    bitwise_and(img0, img0, final, res1); 
    imshow("mask", res1); 
    imwrite("mask.png", res1); 

    imshow("Source", img1); 



} 
if (event == EVENT_MBUTTONDOWN) 
{ 
    for (int i = 0; i < numpts; i++) 
    { 
     pts[i].x = 0; 
     pts[i].y = 0; 
    } 
    var = 0; 
    flag1 = 0; 
    minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; 
    imshow("Source", img0); 
    drag = 0; 
} 

}

int main() {

Mat src = imread("abc.jpg"); 

minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; 

img0 = src; 

channel = img0.channels(); 

res1 = Mat::zeros(img0.size(), CV_8UC1); 
final = Mat::zeros(img0.size(), CV_8UC3); 
//////////// source image /////////////////// 

namedWindow("Source", 1); 
setMouseCallback("Source", mouseHandler, NULL); 
imshow("Source", img0); 
imshow("mask", res1); 
waitKey(0); 


img0.release(); 
img1.release(); 

}

+0

Mögliche Duplikat [Wie kann ich die Position und zeichnen Rechteck mit opencv bekommen?] (Http://stackoverflow.com/questions/31370459/how-can-i-get- die-position-and-draw-rectangle-using-opencv) – Miki

+0

Meine Antwort dort hat ein Arbeitsbeispiel zum Zeichnen (und Speichern) mehrerer Rechtecke auf einem Bild mit OpenCV. Mit diesen Rezepten können Sie das Originalbild mit 'Mat crop (image (rect)) einfach zuschneiden;' – Miki

+0

Danke Miki! Ich möchte es mit Polygon als Objekt implementieren, die nicht immer rechteckig sind. Ich kann ein Polygon zeichnen, aber keine Vielfachen zeichnen. Können Sie vorschlagen, wie Sie mehrere Polygone zeichnen? – OpenCVHelp

Antwort

1

Wenn Sie nur Rechtecke zeichnen möchten, können Sie die beziehen Code in this answer.


Wenn Sie Polygone zeichnen müssen, sehen Sie sich bitte den folgenden Code an. Sie können die Polygonscheitelpunkte mit linken Mausklicks zeichnen. Ein Doppelklick mit der linken Maustaste schließt das Polygon und startet ein neues.

Bitte beachten Sie, dass es hilfreich sein kann, eine Option zum Entfernen eines Scheitelpunkts hinzuzufügen, indem Sie beispielsweise den Scheitelpunkt löschen, der einem rechten Mausklick am nächsten liegt.

Der untere Teil zeigt Ihnen, wie Sie die beschnittenen Bilder speichern.

Code:

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

using namespace std; 
using namespace cv; 

vector<vector<Point>> polygons; 
bool bDraw; 
vector<Point> poly; 


Mat3b img; 
Mat3b layer; 
Mat3b working; 


void CallBackFunc(int event, int x, int y, int flags, void* userdata) 
{ 
    if (event == EVENT_LBUTTONDOWN) 
    { 
     //cout << "Left button of the mouse is clicked - position (" << x << ", " << y << ")" << endl; 

     // Refresh 
     working = layer.clone(); 

     if (!bDraw) 
     { 
      // Init your polygon 
      poly.clear(); 
      bDraw = true; 
     } 

     // Add Current Point 
     poly.push_back(Point(x, y)); 

     // Draw Poly 
     for (size_t i = 1; i < poly.size(); ++i) { 
      line(working, poly[i - 1], poly[i], Scalar(0, 255, 0)); 
     } 
     // Draw Points 
     for (size_t i = 0; i < poly.size(); ++i) { 
      circle(working, poly[i], 3, Scalar(0, 0, 255)); 
     } 

     // Update 
     imshow("My Window", working); 

    } 
    else if (event == EVENT_MOUSEMOVE) 
    { 
     //cout << "Mouse move over the window - position (" << x << ", " << y << ")" << endl; 

     // If drawing, update rect width and height 
     if (!bDraw) return; 

     // Refresh 
     working = layer.clone(); 

     // Draw Poly 
     for (size_t i = 1; i < poly.size(); ++i) { 
      line(working, poly[i - 1], poly[i], Scalar(0, 255, 0)); 
     } 
     // Draw Points 
     for (size_t i = 0; i < poly.size(); ++i) { 
      circle(working, poly[i], 3, Scalar(0, 0, 255)); 
     } 
     // Draw Current line 
     line(working, poly.back(), Point(x, y), Scalar(0, 255, 0)); 

     // Update 
     imshow("My Window", working); 
    } 
    else if (event == EVENT_LBUTTONDBLCLK) 
    { 
     //cout << "Left button double clicked" << endl; 

     // Refresh 
     working = layer.clone(); 

     // Add Current Point 
     poly.push_back(Point(x, y)); 

     // Save poly, draw it on layer 
     polygons.push_back(poly); 

     // Draw Poly 
     for (size_t i = 1; i < poly.size(); ++i) 
     { 
      line(working, poly[i - 1], poly[i], Scalar(0, 255, 255)); 
     } 
     // Draw closed poly 
     line(working, poly.back(), poly.front(), Scalar(0, 255, 255)); 

     // Draw Points 
     for (size_t i = 0; i < poly.size(); ++i) { 
      circle(working, poly[i], 3, Scalar(0, 0, 255)); 
     } 

     layer = working.clone(); 

     bDraw = false; 

     // Update 
     imshow("My Window", working); 
    } 
} 

int main(int argc, char** argv) 
{ 
    bool bDraw = false; 

    // Read image from file 
    img = imread("path_to_image"); 

    // initialize your temp images 
    layer = img.clone(); 
    working = img.clone(); 

    //if fail to read the image 
    if (img.empty()) 
    { 
     cout << "Error loading the image" << endl; 
     return -1; 
    } 

    //Create a window 
    namedWindow("My Window", 1); 

    //set the callback function for any mouse event 
    setMouseCallback("My Window", CallBackFunc, NULL); 

    //show the image 
    imshow("My Window", working); 

    // Wait until user press 'q' 
    while ((waitKey(1) & 0xFF) != 'q'); 

    // Create cropped images and show/save 
    for (size_t i = 0; i < polygons.size(); ++i) 
    { 
     Mat3b out(img.rows, img.cols, Vec3b(0, 0, 0)); 
     Mat1b mask(img.rows, img.cols, uchar(0)); 
     drawContours(mask, polygons, i, Scalar(255), CV_FILLED); 
     img.copyTo(out, mask); 

     Rect box = boundingRect(polygons[i]); 
     out = out(box).clone(); 

     imshow("Crop #" + to_string(i), out); 
     waitKey(1); 
     //imwrite("Crop #" + to_string(i), out); 
    } 

    waitKey(); 
    return 0; 
} 
+0

Vielen Dank @Miki! – OpenCVHelp