【问题标题】:Finding Contours in OpenCV?在 OpenCV 中寻找轮廓?
【发布时间】:2012-01-16 23:23:56
【问题描述】:

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

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

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

谢谢。

【问题讨论】:

  • 好吧,我真的没有任何唯一代码。我只有一个从相机中取回的垫子。我在上面运行精明的边缘检测器,然后使用 findContours() 找到轮廓。找到的所有轮廓都存储在 vector> 中。这基本上就是我所拥有的,所以我发布实际代码没有多大意义——它只是寻找轮廓的传统过程。
  • 我对轮廓进行了一些研究,尽管我的兴趣只是外部轮廓。我尝试使用“drawContours()”为轮廓着色。这预示着一种层次结构。我使用的“drawContours()”样本没有为内部轮廓着色。我想在这里得到的是,您可能需要使用“findContours()”中的层次数组对它们进行排序。 (我没有发布答案的原因是我对这个层次结构的了解是有限的,我不想让你在这件事上感到困惑。我已经对这些做了一些测试,到目前为止我可以解释我的理解,如果您要求。)
  • 感谢您的回答。如果可能的话,如果你能解释你迄今为止对层次结构的理解,我将不胜感激。谢谢。
  • 外部和内部边界轮廓可以使用 CvSeq* 结构中的 h_next 和 v_next 指针访问,其中轮廓由 findContours() 函数存储。这是书中关于如何组织的链接(我总是只处理外部轮廓,因此没有任何工作代码可发布):books.google.co.in/…
  • 我使用的是 C++ API 而不是 C,因此我没有使用 CvSeq。我正在使用 vector >

标签: c++ image image-processing opencv shape


【解决方案1】:

我在你的图片上运行了这段代码,它返回了一个内外轮廓。

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

这是它找到的轮廓:

【讨论】:

  • 谢谢。你会碰巧知道如何专门访问内部轮廓吗?和洞的边界一样?
  • 如果您将模式设置为CV_RETR_TREE 而不是CV_RETR_LIST,您将获得轮廓的分层树,因此内轮廓将低于外轮廓。它不区分内轮廓和外轮廓,因此如果圆内有一个圆,则这两个轮廓都将低于外圆的内轮廓。 OpenCV findContour tutorial 使用 CV_RETR_TREE
【解决方案2】:

我认为 Farhad 要求的是从原始图像中裁剪轮廓。

为此,您需要按照上述说明找到轮廓,然后使用蒙版从原始图像中获取内部,然后将结果裁剪成与轮廓大小相同的图像。

【讨论】:

    【解决方案3】:

    findcontours 函数将所有轮廓存储在不同的向量中,在给定所有轮廓的代码中,您只需绘制与内部轮廓对应的轮廓,idx 是说明绘制哪个轮廓的变量。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-18
      • 2012-01-04
      • 1970-01-01
      • 2012-11-06
      • 1970-01-01
      • 2012-12-28
      • 1970-01-01
      相关资源
      最近更新 更多