1

처음 게시 할 때 올바른 방법으로 코드를 삽입하시기 바랍니다.OpenCV는 큰 윤곽선 주위에 직사각형을 그립니까?

저는 비디오에서 차량을 감지하고 계산하려고합니다. 따라서 아래 코드를 보면 thresholding 및 dilating 후 이미지의 윤곽선을 찾은 다음 drawContours와 rectangle을 사용하여 주위에 상자를 그립니다 검출 된 윤곽.

사각형의 영역이 40,000보다 크지 않은 경우 drawContours/rectangle if 문에 필터를 넣으려고했다가 그려 보지 않았습니다.

이제 내가 첨부 한 그림을 보면 큰 직사각형 안에 그려지는 직사각형이 있음을 알 수 있습니다. 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

당신은 당신이 widthheight을 곱한 수, 사각형의 영역을 얻기 위해 xy 좌표를해야 곱한 것입니다.

//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 개의 크기의 블로 브 (blob) 주위에 1 개의 사각형을 넣습니다. –

+1

질문에 성공적으로 답변 한 경우 답변을 수락하는 것을 잊지 마십시오. –