OpenCV只围绕大轮廓绘制矩形? [英] OpenCV draw rectangles around only large contours?

查看:202
本文介绍了OpenCV只围绕大轮廓绘制矩形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

第一次发帖,希望我以正确的方式放置代码。

first time posting, hope I put the code in the right way.

我正在尝试检测和计算视频中的车辆,因此如果您查看下面的代码,我会在阈值处理和扩张后找到图像的轮廓,并且然后我使用drawContours和矩形在检测到的轮廓周围绘制一个框。

I'm trying to detect and count vehicles in a video, and so if you look at my code below I find the contours of the image after thresholding and dilating, and then I use drawContours and rectangle to draw a box around the detected contours.

我试图在drawContours / rectangle if语句中放置一个过滤器,说明是否有区域矩形不大于40,000,然后不要绘制它。

I tried to put a filter on the drawContours/rectangle if statement by saying if the area of the rectangle isn't bigger than 40,000, then don't draw it.

现在,如果你看看我附上的图片,你会发现有矩形是在较大的矩形内绘制,我不想这样做。 在此输入图片说明。这些矩形的面积小于40,000但是由于某种原因它们被绘制。

Now if you look at the picture I attached, you'll see that there are rectangles that are drawn inside the larger rectangles, which I am not trying to do. enter image description here. These rectangles has an area less than 40,000 but they are being drawn for some reason.

我打算使用矩形来计算图像上的汽车,但如果这不是最好的方法,我会接受建议。

I was going to use the rectangles to count the cars on the image, but if that's not the best way to do it I'm open to suggestions.

谢谢。

using namespace cv;
using namespace std;

int main()
{
    VideoCapture TestVideo;                 //Declare video capture
    Mat frame;                              //declare Mat as frame to grab

    TestVideo.open("FroggerHighway.mp4");           //open the test video from the project directory

    if (!TestVideo.isOpened())              //If its not open declare the error
        {
            cout << "Video did not open." << endl;
            waitKey(0);
        }

    if (TestVideo.get(CV_CAP_PROP_FRAME_COUNT) < 1)     //If the frame count is less than 1, basically an error checker
        {
            cout << "Video file must have at least one frame." << endl;
            waitKey(0);
        }

    TestVideo.read(frame);                              //read the first frame
    Mat frameGray = Mat::zeros(frame.size(), CV_8UC1);  //Convert frame source to gray
    cvtColor(frame, frameGray, CV_BGR2GRAY); 

    Mat frame2 = Mat::zeros(frameGray.size(), frameGray.type());    //Intermediate frame
    Mat framediff;                                                  //Frame differencing
    Mat thresh;
    Mat element;                                                    //Element used for morphOps (dilation)
    Mat dil;    

    while (TestVideo.isOpened() & waitKey(30) != 27)                //while the video is open, show the frame, press escape to end video
        {
        absdiff(frameGray, frame2, framediff);                      //take absolute difference of both frames
        threshold(framediff, thresh, 22, 255, CV_THRESH_BINARY);    //If absdiff is greater than 22, turn it white. 

        namedWindow("Gray", CV_WINDOW_NORMAL);                      //Display gray video
        imshow("Gray", frameGray);

        namedWindow("FrameDiff", CV_WINDOW_NORMAL);                 //Show frame difference before threshold/dilation
        imshow("FrameDiff", framediff);

        namedWindow("Threshold", CV_WINDOW_NORMAL);                 //Show thresholded video
        imshow("Threshold", thresh);

        element = getStructuringElement(MORPH_CROSS,                //morphOps dilation
            Size(2 * 5 + 1, 2 * 5 + 1),
            Point(5, 5));
        dilate(thresh, dil, element, Point(-1, -1), 1, 1, 1);

        namedWindow("Dilation", CV_WINDOW_NORMAL);                  //Show dilated video. 
        imshow("Dilation", dil);

        //Apply findCountours function to draw countours and count the objects.
        vector<vector<Point> > contours;        //Not sure what this does but it works
        findContours(dil, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);    //(outout image, hierarchy, and 2 ways to calculate it)
        vector<vector<Point> > contours_poly(contours.size());      //Also not sure what this does
        vector<Rect> boundRect(contours.size());            //This is used to approximate a polygon to fit the contours it calculated I think

        Mat output = Mat::zeros(dil.rows, dil.cols, CV_8UC3);   
        int counter = 0;                                    //Used to count # of rectangle drawn

        for (int i = 0; i < contours.size(); i++)
        {
            approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);  //Approximates a polygon to fit the contours calculated ?
            boundRect[i] = boundingRect(Mat(contours_poly[i]));    //for each approximation, a bounding rectangle is sorted around the contour ?

            if ((boundRect[i].x * boundRect[i].y) > 40000)          //If the bounding rectangle has an area less than 40,000 then just ignore it completely
            {
                counter = counter + 1;
                drawContours(output, contours, i, Scalar(255, 255, 255), -3);   //(input, countors, contour to be drawn, color of it, thickness (negative fills image));
                rectangle(output, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 0, 255), 2, 8, 0); //Draws the actual rectangle around the contours
            }
        }

        cout << "Rectangles Drawn: " << counter << endl;

        namedWindow("Output", CV_WINDOW_NORMAL);
        imshow("Output", output);

            if (((TestVideo.get(CV_CAP_PROP_POS_FRAMES) + 1) < TestVideo.get(CV_CAP_PROP_FRAME_COUNT)) & (waitKey(30) != 27))   //Move the frame count up 1, show the frame
            {
                TestVideo.read(frame);
                frameGray.copyTo(frame2);                   //MUST USE copyTo, or clone! Can't do frame2 = frameGray*
                cvtColor(frame, frameGray, CV_BGR2GRAY);
            }
            else
            {
                cout << "End of Video" << endl;
                waitKey(0);
                break;
            }

            waitKey(30);        //wait 30ms between showing each frame
        }

    return (0);
}


推荐答案

你正在乘以 x y 获取矩形区域的坐标,你应该乘以宽度 height

You're multiplying the x and y coordinates to get the area of rectangle, you should be multiplying the width and height.

//If the bounding rectangle has an area less than 40,000 then just ignore it completely
if ((boundRect[i].width * boundRect[i].height) > 40000)          
{
// code here
}

这篇关于OpenCV只围绕大轮廓绘制矩形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆