'filtering unwanted contours - opencv with C++

I'm processing a video which I want to detect some objects.

first, I remove background, then make it gray and make a binary image using cv::threshold and after that cv::findcontours.

I want to remove too long and too short contours. I found a code for this reason in "Opencv 2 cookbook". But it has a run time error on 21st frame of my video.

// Eliminate too short or too long contours
    size_t cmin{ 15 }; // minimum contour length
    size_t cmax{ 120 }; // maximum contour length


    std::vector<std::vector<cv::Point> >::
        const_iterator itc = contours.begin();
    while (itc != contours.end()) {
        if (itc->size() < cmin || itc->size() > cmax)
            itc = contours.erase(itc);
        else
            ++itc;
    }

I searched and found another code and it has the same error on the same frame:

double min_area = 500; // area threshold
    double max_area = 1500; // area threshold
    for (int i = 0; i < contours.size(); i++) // iterate through each contour.
    {
        double area = contourArea(contours[i], false);  //  Find the area of contour
        if (area < min_area || area > max_area)
            contours.erase(contours.begin() + i);
    }

and I wrote a code to create a new vector and just copy the accepted contours in it. but it also has the same error on the same frame:

std::vector<std::vector<cv::Point> > goodcontours;
    size_t cmin{ 15 };
    size_t cmax{ 120 };
    double contourlength = 1;
    size_t contoursize = contours.size();
    for (int i = 0; i != contoursize;i++) {
        contourlength = cv::arcLength(contours[i], true);
        if (contourlength > cmin && contourlength < cmax)
            goodcontours.push_back(contours.at(i));
    }

I tried other videos and all of them has the same problem on a specific frame.

Before the error, I can still see the unwanted contours and it means they don't really eliminated.

the error just say:

Unhandled exception at 0x75017FB2 (ucrtbase.dll)

Do you have any suggestion for filtering the contours?

one of my video frames contours



Solution 1:[1]

here is my Find_Filter_Draw Contours function , sharing it might be helpful to someone

bool Find_Filter_Draw_Contours(){
   // Find Contours on our working image which is ... currentImage.
    cv::Mat hierarchy = cv::Mat();
    std::vector<std::vector<cv::Point> > contours;
    cv::Mat contourOutput = currentImage.clone();

    cv::findContours(contourOutput, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_NONE);
    hierarchy.release();

    // filter them based on Area.  good to remove small dots
    double minArea = 50; 
    double maxArea = 900000;

   std::vector<std::vector<cv::Point> > GoodContours;

  for (size_t idx = 0; idx < contours.size(); idx++) {
        double area = cv::contourArea(contours[idx]);
       // http://www.cplusplus.com/reference/limits/numeric_limits/
        if (area >= (minArea == -1 ? std::numeric_limits<double>::min() : minArea) && area <= (maxArea == -1 ? std::numeric_limits<double>::max() : maxArea)) {
              GoodContours.push_back(contours.at(idx));
        }
    }

    //Draw the contours
    cv::Mat contourImage(currentImage.size(), CV_8UC3, cv::Scalar(0,0,0));
    cv::Scalar colors[3];
    colors[0] = cv::Scalar(255, 0, 0);
    colors[1] = cv::Scalar(0, 255, 0);
    colors[2] = cv::Scalar(0, 0, 255);


      for (size_t idx = 0; idx < GoodContours.size(); idx++) {
          cv::drawContours(contourImage, GoodContours, idx, colors[idx % 3]);
      }

      cv::imshow("Input Image", currentImage);
      cv::imshow("Contours", contourImage);

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user889030