Finding Contours in OpenCV?

2019-01-17 05:07发布

问题:

When you retrieve contours from an image, you should get 2 contours per blob - one inner and one outer. Consider the circle below - since the circle is a line with a pixel width larger than one, you should be able to find two contours in the image - one from the inner part of the circle and one from the outer part.

Using OpenCV, I want to retrieve the INNER contours. However, when I use findContours (), I only seem to be getting the outer contours. How would I retrieve the inner contours of a blob using OpenCV?

I am using the C++ API, not C therefore only suggest functions that use the C++ API. (i.e. findContours () rather than cvFindContours ())

Thanks.

回答1:

I ran this code on your image and it returned an inner and outer contour.

#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

int main(int argc, const char * argv[]) {

    cv::Mat image= cv::imread("../../so8449378.jpg");
    if (!image.data) {
        std::cout << "Image file not found\n";
        return 1;
    }

    //Prepare the image for findContours
    cv::cvtColor(image, image, CV_BGR2GRAY);
    cv::threshold(image, image, 128, 255, CV_THRESH_BINARY);

    //Find the contours. Use the contourOutput Mat so the original image doesn't get overwritten
    std::vector<std::vector<cv::Point> > contours;
    cv::Mat contourOutput = image.clone();
    cv::findContours( contourOutput, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE );

    //Draw the contours
    cv::Mat contourImage(image.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 < contours.size(); idx++) {
        cv::drawContours(contourImage, contours, idx, colors[idx % 3]);
    }

    cv::imshow("Input Image", image);
    cvMoveWindow("Input Image", 0, 0);
    cv::imshow("Contours", contourImage);
    cvMoveWindow("Contours", 200, 0);
    cv::waitKey(0);

    return 0;
}

Here are the contours it found:



回答2:

I think what Farhad is asking is to crop the contour from the original image.

To do that you will need to find the contour as explained above, then use a mask to get the inside from the original, and then crop the result into an image with the same size as the contour.



回答3:

The findcontours function stores all the contours in different vectors, in the code given all contours are drawn, you just have draw the contour corresponding to the inner one, idx is the variable that states which contour is drawn.