1

première fois, j'espère que j'ai mis le code dans le bon sens. J'essaie de détecter et de compter les véhicules dans une vidéo, et donc si vous regardez mon code ci-dessous, je trouve les contours de l'image après seuillage et dilatation, puis j'utilise drawContours et rectangle pour dessiner une boîte autour les contours détectés.OpenCV dessine des rectangles autour de grands contours seulement?

J'ai essayé de placer un filtre sur l'instruction drawContours/rectangle if en disant si la surface du rectangle n'est pas supérieure à 40 000, alors ne le dessinez pas.

Maintenant, si vous regardez l'image que j'ai jointe, vous verrez qu'il y a des rectangles qui sont dessinés à l'intérieur des rectangles plus grands, ce que je n'essaie pas de faire. enter image description here. Ces rectangles ont une superficie inférieure à 40 000 mais ils sont dessinés pour une raison quelconque. J'allais utiliser les rectangles pour compter les voitures sur l'image, mais si ce n'est pas la meilleure façon de le faire, je suis ouvert aux suggestions.

Merci.

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

Pourriez-vous s'il vous plaît formater votre code afin qu'il puisse être lu sans problème? – DarkCygnus

Répondre

5

Vous multiplions les coordonnées x et y pour obtenir la zone du rectangle, vous devez être multiplier le width et 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 
} 
+0

Merci beaucoup! Toujours quelque chose de simple. Il met maintenant 1 rectangle autour de 1 blob de taille de voiture à la fois. –

+1

N'oubliez pas d'accepter la réponse si elle a bien répondu à votre question –