2016-04-21 79 views
1

如何使用OpenCV使用鼠標繪製綁定框來從圖像中裁剪多個對象。請看下面的圖片:如何通過繪製邊界框(或多邊形)從圖像中裁剪多個對象?

enter image description here

我想用鼠標點擊來選擇可樂罐邊界和修剪它們。

需要的解決方案來繪製多個多邊形選擇對象:

我能畫一個多邊形,但不倍數。這裏是代碼:

空隙mouseHandler(INT事件,INT的x,INT Y,INT,無效*) {

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主() {

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

的可能重複[我怎樣才能得到這個職位,並使用OpenCV的繪製矩形?](http://stackoverflow.com/questions/31370459/how-can-i-get-這個位置和繪製矩形使用opencv) – Miki

+0

我的答案有一個工作示例如何繪製(和存儲)與OpenCV的圖像上的多個矩形。有了這些矩形,你可以很容易地用'Mat crop(image(rect))'裁剪原始圖像;' – Miki

+0

感謝Miki!我想使用多邊形來實現它,因爲對象不總是矩形的形狀..我可以繪製一個多邊形,但無法繪製倍數。你能建議如何繪製多個多邊形? – OpenCVHelp

回答

1

如果你只是想繪製矩形,你可以參考代碼在this answer


如果您需要繪製多邊形,請查看下面的代碼。您可以使用鼠標左鍵單擊繪製多邊形頂點。左鍵雙擊將關閉多邊形,並開始一個新的。

請注意,可能有助於添加一個選項來刪除頂點,例如通過刪除最接近右鍵單擊的頂點。

底部會告訴你如何保存裁剪圖像。

代碼:

#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

非常感謝@Miki! – OpenCVHelp