2014-01-26 85 views
-1

我使用一個beaglebone OpenCV的跟蹤水平和垂直的矩形轉乘。OpenCV的矩形高度和寬度保持

爲了確定矩形是否是水平或垂直的我使用從minAreaRect提取的高寬比。

但是我注意到有時候,如果我讓程序在同一個圖像上的一個循環上運行,相同的固定矩形交換的寬度和高度的值,它報告之前的寬度值作爲它的當前高度,類似於之前的身高值。

這使得該代碼不能令人滿意,因爲它不再能成功地使用高/寬比。

有人能請解釋一下是什麼引發了矩形的高度/寬度交換自身?

下面是一個示例輸出,注意迭代之間的高度和寬度

Hierarchy: 1 
Contour Size: 53 
Contour: 0 
    X: 350 
    Y: 196 
    Height: 236 
    Width: 26 
    Ratio (W/H): 0.110169 
    Ratio (H/W): 9.07692 
    Vert: 0 
    Horiz: 0 
Image proc. time: 1.9ms 
Contours: 1 
Hierarchy: 1 
Contour Size: 83 
Contour: 0 
    X: 244 
    Y: 300 
    Height: 26 
    Width: 236 
    Ratio (W/H): 9.07692 
    Ratio (H/W): 0.110169 
    Vert: 0 
    Horiz: 0 
Image proc. time: 2.2ms 
Contours: 1 
Hierarchy: 1 
Contour Size: 59 
Contour: 0 
    X: 350 
    Y: 196 
    Height: 236 
    Width: 26 
    Ratio (W/H): 0.110169 
    Ratio (H/W): 9.07692 
    Vert: 0 
    Horiz: 0 
Image proc. time: 2.4ms 

這裏是我用來生成此輸出

vector<Vec4i> hierarchy; 
Target targets; 


/// Show in a window 
namedWindow("Contours", WINDOW_AUTOSIZE); 


//Find rectangles 
findContours(thresholded, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); 

cout<<"Contours: "<<contours.size()<<endl; 
cout<<"Hierarchy: "<<hierarchy.size()<<endl; 


//run through all contours and remove small contours 
unsigned int contourMin = 25; 
for (vector<vector<Point> >::iterator it = contours.begin(); it!=contours.end();) 
{ 
    cout<<"Contour Size: "<<it->size()<<endl; 
    if (it->size()<contourMin) 
     it=contours.erase(it); 
    else 
     ++it; 
} 

//Vector for Min Area Boxes 
vector<RotatedRect> minRect(contours.size()); 

/// Draw contours 
Mat drawing = Mat::zeros(original.size(), CV_8UC3); 

NullTargets(targets); 

//run through large contours to see if they are our targerts 
if(!contours.empty() && !hierarchy.empty()) 
{ 



    for(unsigned int i = 0; i < contours.size(); i++) 
    { 
     //capture corners of copntour 
     minRect[i] = minAreaRect(Mat(contours[i])); 

     //if(hierarchy[i][100] != -1) 
     drawContours(drawing, contours, i, RED, 2, 8, hierarchy, 0, Point()); 



     //draw a minimum box around the target in green 
     Point2f rect_points[4]; 
     minRect[i].points(rect_points); 
     for (int j = 0; j < 4; j++) 
     line(drawing,rect_points[j],rect_points[(j+1)%4],GREEN,1,8); 

     //define minAreaBox 
     Rect box; 
     box.x = minRect[i].center.x - (minRect[i].size.width/2); 
     box.y = minRect[i].center.y - (minRect[i].size.height/2); 
     box.width = minRect[i].size.width; 
     box.height = minRect[i].size.height; 


     double WHRatio = box.width/((double)box.height); 
     double HWRatio = ((double)box.height)/box.width; 

     //check if contour is vert, we use HWRatio because it is greater that 0 for vert target 
     if ((HWRatio > MinVRatio) && (HWRatio < MaxVRatio)) 
     { 
      targets.VertGoal = true; 
      targets.VerticalTarget = box; 
      targets.VerticalAngle = minRect[i].angle; 
      targets.VerticalCenter = Point(box.x + box.width/2, box.y + box.height/2); 
      targets.Vertical_H_W_Ratio = HWRatio; 
      targets.Vertical_W_H_Ratio = WHRatio; 

     } 
     //check if contour is horiz, we use WHRatio because it is greater that 0 for vert target 
     else if ((WHRatio > MinHRatio) && (WHRatio < MaxHRatio)) 
     { 
      targets.HorizGoal = true; 
      targets.HorizontalTarget = box; 
      targets.HorizontalAngle = minRect[i].angle; 
      targets.HorizontalCenter = Point(box.x + box.width/2, box.y + box.height/2); 
      targets.Horizontal_H_W_Ratio = HWRatio; 
      targets.Horizontal_W_H_Ratio = WHRatio; 
     } 

     if(targets.HorizGoal && targets.VertGoal) 
      targets.HotGoal = true; 

     cout<<"Contour: "<<i<<endl; 
     cout<<"\tX: "<<box.x<<endl; 
     cout<<"\tY: "<<box.y<<endl; 
     cout<<"\tHeight: "<<box.height<<endl; 
     cout<<"\tWidth: "<<box.width<<endl; 
     cout<<"\tangle: "<<minRect[i].angle<<endl; 
     cout<<"\tRatio (W/H): "<<WHRatio<<endl; 
     cout<<"\tRatio (H/W): "<<HWRatio<<endl; 
     cout<<"\tVert: "<<targets.VertGoal<<endl; 
     cout<<"\tHoriz: "<<targets.HorizGoal<<endl; 
     cout<<"\tHot Goal: "<<targets.HotGoal<<endl; 
     //rectangle(drawing,box,YELLOW); 


     //ID the center in yellow 
     Point center(box.x + box.width/2, box.y + box.height/2); 
     line(drawing, center, center, YELLOW, 3); 
     line(drawing ,Point(320,240),Point(320,240),YELLOW,3); 

    } 

回答

3

當你與RotatedRect您使用的代碼應該記住,它沒有真正的寬度或高度,因爲如果將角度增加90度,它們可以交換。作爲使用「寬度」或RotatedRect的「高度」來初始化「盒子」的結果是有問題的,至少可以說。如果你想計算RotatedRect的比率,你應該考慮角度。或者,如果你不想使用角度使用矩形的,而不是RotatedRect從一開始(更換minAreaRect與boundingRect)。

在附註中,您不是通過數字頂點過濾多邊形,這通常是非常不可靠的數字。大的多邊形可能有很少的頂點,小的可能有很多頂點。自從您計算出它之後,您最好使用輪廓區域(來自contourArea函數)或其邊界框的區域。

相關問題