2011-12-09 233 views
14

当你从图像中检索轮廓时,你应该得到2个轮廓 - 一个内部和一个外部。考虑下面的圆 - 由于圆是像素宽度大于1的线,因此您应该能够在图像中找到两个轮廓 - 一个来自圆圈内部,另一个来自外部。在OpenCV中寻找轮廓?

使用OpenCV的,我想要检索的内部轮廓。但是,当我使用findContours()时,我似乎只能获得外部轮廓。我将如何使用OpenCV检索blob的内部轮廓?

我现在用的是C++ API,而不是C因此只建议使用C++ API函数。 (即findContours()而不是cvFindContours())

感谢。

enter image description here

+0

你能告诉我们一些代码吗? – SSteve

+0

那么,我真的没有任何独特的代码。我只是从相机中取出一块垫子。我运行Canny边缘检测器,然后使用findContours()查找轮廓。所有找到的轮廓都存储在一个矢量>中。这基本上就是我所有的,所以在我发布实际代码时没什么意义 - 它只是寻找轮廓的传统过程。 – fdh

+0

虽然我的兴趣只是外部轮廓,但我已经用轮廓工作了一下。我试着用'drawContours()'来着色轮廓。其中有一种层次。我使用的'drawContours()'上的样本没有着色内部轮廓。我试图在这里得到的是,你可能需要使用'findContours()'中的层次数组对它们进行排序。 (我之所以没有发布答案,是因为我对这个层次的了解是有限的,我不想在这个问题上混淆你,我对这些做了一些测试,如果能够解释我的理解,你的要求。) – Sonaten

回答

19

我跑你的形象在这个代码,它返回一个内部和外部轮廓。

#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; 
} 

这里是它发现的轮廓:

findContour result image

+0

谢谢。你会碰巧知道如何专门访问内部轮廓吗?如在洞的边界? – fdh

+2

如果将模式设置为'CV_RETR_TREE'而不是'CV_RETR_LIST',则会得到轮廓树,因此内轮廓将位于外轮廓之下。它没有区分内外轮廓,所以如果圆内有一个圆,这两个轮廓都会低于外圆的内轮廓。 [OpenCV findContour教程](http://opencv.itseez.com/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html#find-contours)使用'CV_RETR_TREE'。 – SSteve

3

我认为法哈德被问是从原始图像裁剪轮廓。

要做到这一点,你需要找到轮廓如上​​所述,然后用面膜来从原来里面,然后将结果与相同大小的轮廓裁剪成图像。

0

的findcontours功能存储所有在不同的载体中给出的所有轮廓的轮廓,在代码被绘制,你就必须绘制对应于内一个轮廓,IDX是状态其轮廓绘制的变量。