2

I have used canny edge detection and I have found the contours on an image I am trying to process. I want to find the five largest contours and then see whether or not there are contours within the five biggest contours in the image. Is this possible? I am new to OpenCV.

Boots2014
  • 55
  • 1
  • 2
  • 8
  • You want to find if there are contours _inside_ the 5 largest? – Miki Oct 28 '15 at 21:24
  • Yes. I have a picture of five bottles and I want to see whether the bottles have labels on them. The largest contours outline each bottle and if the bottle has a label there are additional contours inside it. Hope this makes sense. – Boots2014 Oct 28 '15 at 21:29
  • Well, yes, it makes sense. Can you show what you tried so far? – Miki Oct 28 '15 at 21:36
  • I'm away from my computer at the moment but my code was largely based on the source code from the open cv code here http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html I added a for loop in the function to find the largest contour. I'm not sure but I'm thinking I have to index the five largest contours somehow. – Boots2014 Oct 28 '15 at 23:25
  • Posted an answer. You can see how to find the `N` largest contours, and how to get inner contours for each one. – Miki Oct 28 '15 at 23:46
  • Wow thank you this is really helpful! – Boots2014 Oct 28 '15 at 23:48

1 Answers1

11

You can find the N largest contours checking their length. You should take care to pass to findContours the parameter CHAIN_APPROX_NONE for this to work properly.

You can then check inside each mask if there are other contours.

Image:

enter image description here

N = 5 largest contours, with inner contours for each one.

enter image description here

Code:

#include <opencv2\opencv.hpp>
#include <vector>
#include <numeric>
using namespace cv;
using namespace std;


int main()
{
    Mat3b img = imread("path_to_image");

    Mat1b gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);

    Mat1b edges;
    Canny(gray, edges, 200, 50);

    vector<vector<Point>> contours;
    findContours(edges.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

    vector<int> indices(contours.size());
    iota(indices.begin(), indices.end(), 0);

    sort(indices.begin(), indices.end(), [&contours](int lhs, int rhs) {
        return contours[lhs].size() > contours[rhs].size();
    });

    int N = 5; // set number of largest contours
    N = min(N, int(contours.size()));

    Mat3b res = img.clone();

    // Draw N largest contours
    for (int i = 0; i < N; ++i)
    {
        Scalar color(rand() & 255, rand() & 255, rand() & 255);
        Vec3b otherColor(color[2], color[0], color[1]);

        drawContours(res, contours, indices[i], color, CV_FILLED);

        // Create a mask for the contour
        Mat1b res_mask(img.rows, img.cols, uchar(0));
        drawContours(res_mask, contours, indices[i], Scalar(255), CV_FILLED);

        // AND with edges
        res_mask &= edges;

        // remove larger contours
        drawContours(res_mask, contours, indices[i], Scalar(0), 2);

        for (int r = 0; r < img.rows; ++r)
        {
            for (int c = 0; c < img.cols; ++c)
            {
                if (res_mask(r, c))
                {
                    res(r,c) = otherColor;
                }
            }
        }
    }

    imshow("Image", img);
    imshow("N largest contours", res);
    waitKey();

    return 0;
}
Miki
  • 40,887
  • 13
  • 123
  • 202