OpenCV只围绕大轮廓绘制矩形?

时间:2017-09-04 22:50:49

标签: c++ opencv image-processing image-recognition opencv-contour

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

我试图检测和计算视频中的车辆,所以如果你看下面我的代码,我会在阈值和扩张后找到图像的轮廓,然后我用drawContours和矩形画一个盒子围绕检测到的轮廓。

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

现在,如果你看一下我附上的图片,你会发现在较大的矩形内画有矩形,我不想这样做。 enter image description here。这些矩形的面积小于40,000但是由于某种原因它们被绘制。

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

感谢。

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);
}

1 个答案:

答案 0 :(得分:5)

您需要将xy坐标相乘以获得矩形区域,您应该将widthheight相乘。

//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
}