2013-02-06 242 views
3

我正在使用C++環境中的OpenCV開發軟件。 其目標是檢測拳擊手套並圍繞手套輪廓繪製邊框。OpenCV邊界框

我遇到的問題是邊界框不止一次被淹沒,實際上多個框被繪製。過去幾天我試圖做的是以某種方式消除繪製的盒子的數量,並且只畫出一個大的邊框。

我正在尋找一些技術來填充整個對象,我相信這對於這種情況非常有幫助。

下面我貼我用來實現圖像中顯示的結果代碼:

vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
vector<Vec3f> vecCircles;    
vector<Vec3f>::iterator itrCircles; 

while(1) 
{ 
    Mat frame; 
    cap >> frame; // get a new frame from camera 
    ///////////////////// 
    Mat imgHSV; 
    cvtColor(frame, imgHSV, CV_BGR2HSV); 
    //////////////////// 
    Mat blur_out; 
    GaussianBlur(imgHSV, blur_out, Size(1,1),2.0,2.0); 
    //////////////////// 
    Mat range_out; 
    inRange(blur_out, Scalar(100, 100, 100), Scalar(120, 255, 255), range_out); 
    //////////////////// 
    findContours(range_out, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 

    /// Approximate contours to polygons + get bounding rects and circles 
    vector<vector<Point> > contours_poly(contours.size()); 
    vector<Rect> boundRect(contours.size()); 
    vector<Point2f>center(contours.size()); 
    vector<float>radius(contours.size()); 

    for(int i = 0; i < contours.size(); i++) 
    { 
     approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); 
     boundRect[i] = boundingRect(Mat(contours_poly[i])); 
    } 

    /// Draw polygonal contour + bonding rects 
    Mat drawing = Mat::zeros(range_out.size(), CV_8UC3); 
    for(int i = 0; i< contours.size(); i++) 
    { 
     Scalar color = Scalar(255,0,255); 
     drawContours(drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point()); 
     rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);   
    } 

enter image description here

如果任何人都可以提出一些提示或提供在哪裏可以找到答案,一些信息源爲我的問題。

編輯(快速更新):

我設法逐步提高輸出圖像安靜點時安靜高興的結果。關鍵是使用侵蝕&擴張以及在我的findContours()功能。我將CV_RETR_TREE更改爲CV_RETR_EXTERNAL。還有一些其他的小事情我解決,但結果是好的:

enter image description here

不知道如果我應該寫這這裏,或打開新的線程....但現在我需要一些幫助,成分標籤和提取中心點和麪積等參數。 :)

+1

隨意了投票,幫助你的答案。 – karlphillip

回答

5

您目前在每個輪廓周圍繪製邊框,並且findContour將在每個連接的白色或黑色組件周圍找到輪廓,其中圖片中有很多部分。

所以我要做的第一件事就是在閾值圖像上過濾所有那些帶有形態操作的噪音:做一些opening and closing,這兩個都是dilation and erosion的組合。

在你的情況下,像cvDilate(2次); cvErode(4次); cvDilate(2次)

這應該將所有的白色斑點合併爲一個光滑的斑點,但中間的黑洞將保留。 您可以按尺寸找到合適的尺寸,但使用CV_RETR_EXTERNAL而不是CV_RETR_TREE調用findContours會更容易,那麼它將只返回最外層的輪廓。

+0

當你說cvDilate(2次)時,你的建議是這樣的; cvErode(4次); cvDilate(2次)在代碼中,它看起來像這樣...?:Mat dilate; \t Mat元素(7,7,CV_8U,Scalar(1)); (range_out,dilate,element,Point(-1,-1),2); cv :: dilate \t墊子腐蝕; \t Mat element2(7,7,CV_8U,Scalar(1)); \t cv :: erode(dilate,erode,element2,Point(-1,-1),4); \t Mat dilate2; \t Mat element3(7,7,CV_8U,Scalar(1)); \t cv :: dilate(range_out,dilate2,element3,Point(-1,-1),2); – Tomazi

1

在找到輪廓之前,您應該應用形態濾鏡,如erodedilate。之後,您可以通過計算其邊界框size或邊界框的高度和邊界來查找輪廓並忽略小輪廓。最後,您可以使用hierarchy排除位於其他輪廓內的那些輪廓。

0

正如b_m所提到的,您需要應用形態學操作。然後,我會做一些事情,如找到圖像中最大的輪廓,並只圍繞該輪廓繪製邊界框。我創建了以下功能爲我的項目,我想會幫助你,如果以正確的方式

CvSeq* findLargestContour(CvSeq* contours){ 

    CvSeq* current_contour = contours; 
    double largestArea = 0; 
    CvSeq* largest_contour = NULL; 

    // check we at least have some contours 

    if (contours == NULL){return NULL;} 

    while (current_contour != NULL){ 

     double area = fabs(cvContourArea(current_contour)); 

     if(area > largestArea){ 
      largestArea = area; 
      largest_contour = current_contour; 
     } 

     current_contour = current_contour->h_next; 
    } 

    // return pointer to largest 

    return largest_contour; 

}