OpenCV中的findContours崩溃编译器

Posted

技术标签:

【中文标题】OpenCV中的findContours崩溃编译器【英文标题】:findContours crashing compiler in OpenCV 【发布时间】:2012-12-08 20:36:41 【问题描述】:

当我尝试使用findContours 时,我已经尝试了几个小时来找出 XCode 中的问题。基本上这是我的代码:

#include <opencv2/opencv.hpp>
int main()

    Mat img = imread(helper::getImageSequence(3, image_value_temp));
    Mat img_gray = Mat(Size(img.cols, img.rows), CV_8UC1);
    Mat img_canny;

    cvtColor(img, img_gray, CV_BGR2GRAY);    

    Canny(img_gray, img_canny, someLow, someHigh);

    vector<vector<cv::Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(img_canny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

当我打印轮廓时,我得到 7905747460161236409,所以我想知道我的堆是否溢出?

XCode 版本:4.5.2 编译器:Apple LLVM 4.1

所以基本上崩溃可以追溯到findContours,这就是 XCode 给我的全部内容:

【问题讨论】:

您能否尝试提供一个简短、自包含、正确(可编译)的示例 (sscce.org)? @Dobi,短?是的。自给自足?我不能让它变得更加不同,除非img 必须被替换为任意图像。正确的?是的。例子?见下图。换句话说,我不太确定你想说什么? 【参考方案1】:

如果您提供完整的源代码和为您生成此错误的图像,则重新创建错误会更容易。当我完成你的代码,以便我可以使用它:

#include <opencv2/opencv.hpp>
int main()

    using namespace cv;
    Mat img = imread("test.png");
    Mat img_gray = Mat(Size(img.cols, img.rows), CV_8UC1);
    Mat img_canny;

    cvtColor(img, img_gray, CV_BGR2GRAY);    

    Canny(img_gray, img_canny, 80, 120);

    vector<vector<cv::Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(img_canny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

它在我的系统上运行良好。我看不出它不应该的原因。 您在屏幕截图中发布的错误不是编译器崩溃。您的调试器显示您的程序在执行期间崩溃了。 您有一个显然由您自己编写的函数 circle_fitting_callback 会在破坏 cv::points 向量时产生错误。您的问题不在于您发布的代码,而在于您没有向我们展示的内容。 最好的办法是学习使用调试器。我不知道您的 IDE,但如果您单击调用堆栈中的相应行(您向我们展示的内容),我猜它会直接指向导致崩溃的函数部分。 如果您遇到此问题,请发布完整的代码以重现错误。

【讨论】:

我尝试将确切的代码片段复制到 Visual Studio 中,Visual Studio 编译代码没有任何问题。我高度怀疑它可能是我试图超过的一些堆栈大小。 circle_fitting_callback 确实是运行我帖子中描述的代码的函数。不幸的是,调试器消息中的任何步骤都没有将我指向特定位置,除了 circle_fitting_callback 中的右括号,它更没用。 很抱歉,如果您不提供所有代码,我无法帮助您解决您的问题,这是重现它所必需的。也许您只是在您的 circle_fitting_callback 函数中进行了双重删除或其他一些基本错误。【参考方案2】:

首先,我认为您不应该直接在 Canny 边缘检测器的输出上运行 findContours(...)。原因是对于某些图像和边缘检测器的某些值输入参数(在您的情况下它们是“someLow”和“someHigh”),输出图像将有很多小的碎片边缘。因此,使用 CV_RETR_TREE 选项(返回嵌套轮廓的完整层次结构)调用 findContours(...) 将导致它找到大量轮廓以及构建层次结构的额外开销。

要对此进行测试,您可以尝试在简单的测试图像上运行您的代码,例如带有纯色背景的实心圆圈。精明的边缘检测器应该给出一个单一的“边缘”,即圆。然后调用 findContour(...) 应该给你这个圈子。

另一个测试是使用 CV_RETR_LIST 而不是 CV_RETR_TREE,因为 CV_RETR_LIST 只返回轮廓而不构建层次结构。

另一个测试是运行您的代码,输入到 canny 边缘检测器集,以返回很少数量的边缘。

如果这些情况不会使您的程序崩溃,那么我们大致走在正确的轨道上。

最后,根据我从事图像处理/计算机视觉工作的经验,您几乎从不想在边缘图上调用 findContours(...),因为您想要碎片边缘周围的轮廓是为了什么?如果我的猜测是正确的,那么您正试图在图像中的对象周围找到轮廓。如果是这种情况,那么您应该尝试使用诸如grabCut 或floodfill(分水岭、均值移位分割)等分割方法获取图像中对象的二进制掩码,运行一些基本的image morphology 运算符清理遮罩,然后在此遮罩上运行 findContours(...)。

希望这会有所帮助。

【讨论】:

以上是关于OpenCV中的findContours崩溃编译器的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV4.5 findContours函数崩溃的真正有效解决方案

OpenCV findContours 堆栈溢出

为啥openCV中的输入图像findContours()要转灰度?

为啥 opencv 中的 FindContours 函数会在如下图像中找到两个轮廓而不是一个?

C++ OpenCV:检测两行而不是一行(Canny & findContours)

Python-OpenCV中的图像轮廓检测