代码之家  ›  专栏  ›  技术社区  ›  David Rose

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

  •  2
  • David Rose  · 技术社区  · 8 年前

    第一次张贴,希望我把代码在正确的方式。

    我试图检测和计算视频中的车辆,如果你看我下面的代码,我会在阈值和扩展后找到图像的轮廓,然后我使用drawContours和rectangle在检测到的轮廓周围绘制一个框。

    我试图在drawContours/rectangle if语句上设置一个过滤器,说如果矩形的面积不大于40000,那么就不要绘制它。

    enter image description here . 这些矩形的面积小于40000,但出于某种原因正在绘制它们。

    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 回复  |  直到 8 年前
        1
  •  5
  •   zindarod    8 年前

    你在乘以 x y width 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
    }