1

初めての投稿、私は正しい方法でコードを入れて願っています。OpenCVは大きな輪郭の周りに長方形を描画しますか?

私はビデオ中の乗り物を検出してカウントしようとしています。下のコードを見ると、しきい値と膨張の後にイメージの輪郭が見つかり、drawContoursとrectangleを使用して検出された輪郭。

私は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つの長方形を配置します。 –

+1

質問に回答したことを忘れないでください –

関連する問題