OpenCV矩形高度和宽度保持交换

时间:2014-01-26 05:13:43

标签: c++ opencv beagleboard

我在beaglebone上使用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);

    }

1 个答案:

答案 0 :(得分:3)

当您使用RotatedRect时,您应该记住它没有真正的宽度或高度,因为如果您向角度添加90度,它们可以交换。因此,使用RotatedRect的“width”或“height”来初始化“box”是至少可以说是有问题的。如果要从RotatedRect计算比率,则应考虑角度。或者,如果您不想从头开始使用角度使用Rect而不是RotatedRect(将minAreaRect替换为boundingRect)。

在旁注中,您不是按照数字顶点过滤多边形,这通常是非常不可靠的数字。大多边形可能只有很少的顶点而小的多边形可能有很多。最好使用轮廓区域(来自contourArea函数)或边界框区域,因为无论如何都要计算它。