1

首次发帖,希望我把代码放在正确的位置。OpenCV仅在大轮廓周围绘制矩形?

我试图检测和统计视频中的车辆,所以如果你看看我的代码,我会在阈值和扩大后找到图像的轮廓,然后使用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); 
} 
+0

请问格式化您的代码,以便它可以被读取没有问题? – DarkCygnus

回答

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 
} 
+0

非常感谢!总是很简单。现在它每次将1个矩形围绕1个汽车大小的blob放置。 –

+1

如果已成功解答您的问题,请不要忘记接受答案 –