Ask Your Question

Revision history [back]

A simple approach could be to judge the size by the number of points in the contour and simply remove all contours which are not one of the two biggest. Something like this (right after findContours):

// Before all this you must #include <algorithm> to have access to min_element() and max_element()

vector<vector<Point> > contours;
int contourIds[] = {0, 1}; // Holds the indexes of the two largest contours.
int contourSizes[] = {contours[0].size(), contours[1].size()}; // Holds the values of the two largest contours.
for(int i = 2; i < (int)contours.size(); i++) { // Find the largest contours, start scanning at contour 2, since 0 and 1 are out initial assumptions for the largest.
    int smallest = *std::min_element(contourSizes, contourSizes+2);
    if(contours[i].size() <= smallest) {
        continue; // This contour is smaller than the two stored contours, so we ignore it.
    }
    // Replace the smallest:
    int smallestId = contourSizes[0] != smallest; // Find if the smallest is contained in spot 0 or 1 in contourIds and contourSizes (using that false == 0 and true == 1)
    contourIds[smallestId] = i;
    contourSizes[smallestId] = contours[i].size();
}
// Erase the 3 intervals of smaller contours:
contours.erase(contours.begin(), contours.begin()+*std::min_element(contourIds, contourIds+2));
contours.erase(contours.begin()+*std::min_element(contourIds, contourIds+2)+1, contours.begin()+*std::max_element(contourIds, contourIds+2));
contours.erase(contours.begin()+*std::max_element(contourIds, contourIds+2)+1, contours.end());

I have not tested the above code, but I think it should more or less work.

A simple approach could be to judge the size by the number of points in the contour and simply remove all contours which are not one of the two biggest. Something like this (right after findContours):

// Before all this you must #include <algorithm> to have access to min_element() and max_element()

vector<vector<Point> > contours;
int contourIds[] = {0, 1}; // Holds the indexes of the two largest contours.
int contourSizes[] = {contours[0].size(), contours[1].size()}; // Holds the values of the two largest contours.
for(int i = 2; i < (int)contours.size(); i++) { // Find the largest contours, start scanning at contour 2, since 0 and 1 are out initial assumptions for the largest.
    int smallest = *std::min_element(contourSizes, contourSizes+2);
    if(contours[i].size() <= smallest) {
        continue; // This contour is smaller than the two stored contours, so we ignore it.
    }
    // Replace the smallest:
    int smallestId = contourSizes[0] != smallest; // Find if the smallest is contained in spot 0 or 1 in contourIds and contourSizes (using that false == 0 and true == 1)
    contourIds[smallestId] = i;
    contourSizes[smallestId] = contours[i].size();
}
// Erase the 3 intervals of smaller contours:
contours.erase(contours.begin(), contours.begin()+*std::min_element(contourIds, contourIds+2));
contours.erase(contours.begin()+*std::min_element(contourIds, contourIds+2)+1, contours.begin()+*std::max_element(contourIds, contourIds+2));
contours.erase(contours.begin()+*std::max_element(contourIds, contourIds+2)+1, contours.end());

I have not tested the above code, but I think it should more or less work.

A simple approach could be to judge the size by the number of points in the contour and simply remove all contours which are not one of the two biggest. Something like this (right after findContours):

// Before all this you must #include <algorithm> to have access to min_element() and max_element()

int contourIds[] = {0, 1}; // Holds the indexes of the two largest contours.
int contourSizes[] = {contours[0].size(), contours[1].size()}; // Holds the values of the two largest contours.
for(int i = 2; i < (int)contours.size(); i++) { // Find the largest contours, start scanning at contour 2, since 0 and 1 are out initial assumptions for the largest.
    int smallest = *std::min_element(contourSizes, contourSizes+2);
    if(contours[i].size() <= smallest) {
        continue; // This contour is smaller than the two stored contours, so we ignore it.
    }
    // Replace the smallest:
    int smallestId = contourSizes[0] != smallest; // Find if the smallest is contained in spot 0 or 1 in contourIds and contourSizes (using that false == 0 and true == 1)
    contourIds[smallestId] = i;
    contourSizes[smallestId] = contours[i].size();
}
// Erase the 3 intervals of smaller contours:
contours.erase(contours.begin(), contours.begin()+*std::min_element(contourIds, contourIds+2));
contours.erase(contours.begin()+*std::min_element(contourIds, contourIds+2)+1, contours.begin()+*std::max_element(contourIds, contourIds+2));
contours.erase(contours.begin()+*std::max_element(contourIds, contourIds+2)+1, contours.end());

I have not tested the above code, but I think it should more or less work.

If you want to use the actual areas you can calculate the area of the contours with contourArea and store the actual area instead of the vector size in contourSizes. The code above should still work in that case.