【问题标题】:Program crashes when using cv::findContours with Qt Gui将 cv::findContours 与 Qt Gui 一起使用时程序崩溃
【发布时间】:2013-03-30 14:26:09
【问题描述】:

我已经被这个问题困扰了好几天了;

我创建了一个 Qt 控制台项目,将其与 OpenCV 连接,一切正常;

我创建了一个 Qt Gui 项目,添加了一个按钮并从按钮槽中复制了之前项目中的相同代码,我得到了一个 windows segFault 并且程序以代码 -1073741819 退出。

于是我使用调试器检测问题,结果发现是在使用函数cv::threshold

我更改了它并改为使用 cv::Canny 但后来我遇到了与 cv::findContours 相同的问题!

奇怪的是,当我调用按钮的 'MainWindow::on_pushButton_clicked()' 在 Windows 的构造函数中它起作用了!!!

这里是调试器输出:

0 cv::thresh_8u(cv::Mat const&, cv::Mat&, unsigned char, unsigned char, int) C:\OpenCV2.4\OpenMinGw\install\bin\libopencv_imgproc240.dll 0 0x62b2c624 1 cv::_InputArray::getMat(int) 常量 C:\OpenCV2.4\OpenMinGw\install\bin\libopencv_core240.dll 0 0x65c1a838 2 ?? 0 0x00000000

这是我得到错误的函数(我从 OpenCV 教程中得到的):

void MainWindow::on_pushButton_clicked(){

    Mat src; Mat src_gray;
    int thresh = 100;
    RNG rng(12345);
    Mat canny_output;

    vector<vector<Point> > contours;

    /// Load source image and convert it to gray
    src = imread( "hat-10.bmp", 1 );

    cvtColor( src, src_gray, CV_BGR2GRAY );
    blur( src_gray, src_gray, Size(3,3) );

    /// Detect edges using canny
    Canny( src_gray, canny_output, thresh, thresh*2, 3 );
    qDebug("Ok 1");

    /// Find contours
    if(cv::sum(src_gray).val[0] > 0.0){

        qDebug("Ok 2");
        cv::findContours( src_gray, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );
        /// Draw contours
        Mat drawing = Mat::zeros( src_gray.size(), CV_8UC3 );
        for( int i = 0; i< contours.size(); i++ )
        {
            Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
            drawContours( drawing, contours, i, color, 2);//, 8, hierarchy, 0, Point() );
        }
        /// Show in a window
        imshow( "Contours", drawing);

    }

使用:

  • Windows 7 x64

  • 使用 mingw 4.1.0 编译的 OpenCV 2.4.0

  • Qt Creator 2.0.0 基于 Qt 4.7.0(32 位)

编辑:

这是我的代码的较短版本:

void MainWindow::on_toolButton_clicked(){
 std::vector<std::vector<cv::Point> > contours;

/// Load source image and convert it to gray
Mat src = imread( "C:/Users/poste/L3 ISIL/PFE Licence/new bmp/hat-10.bmp", 1);
// my image is already a binary one
Mat canny_output(src.size(), src.type());

Canny(src,canny_output,100,200,3);

imshow("Source",  canny_output); // here image is displayed before crash
waitKey(500);

/// Find contours
findContours(canny_output, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );

}

在控制台模式下,没有问题。从 GUI 应用程序构造函数调用时也没有问题。 只有在实际点击按钮时才会崩溃。

编辑: 我截图了![这里]http://i.stack.imgur.com/1LyeF.png 显示canny_output,表示图片已加载。

上传项目here

【问题讨论】:

    标签: c++ qt opencv


    【解决方案1】:

    首先确保您要设置阈值的图像确实是灰度图像。在 Thresholding 之后在另一个窗口中显示它。

    在 cv::FindContours 之前这样做:

    cvThreshold(originalImage,resultingImage,100,100,CV_THRESH_BINARY) 
    

    也改变一下:

    vector<vector<Point> > contours;
    
    to:
    
    vector<vector<cv::Point2f> > contours;
    

    【讨论】:

    • 当我将 cv::Point 更改为 cv::Point2f 时,我得到了 Invalid parameter passed to C runtime function. 至于 threshold,我使用它然后回到 Canny(因为它给出了相同的结果)这是输出图像当我从构造函数调用函数时!Picture 显然代码有效。问题是,为什么我点击 QButton 时它不起作用?
    • 请上传我要测试的示例项目。
    • imgread 失败,请检查图像的 bps,您使用 1 表示它是 3 通道图像!并且附加的图像是灰度的!
    • 好的。我将其更改为 Mat src = imread( "hat-10.bmp", 0) 并这样做:Mat canny_output(src.size(), CV_8U) 仍然是一样的。它对你有用吗?
    • 如果imread失败,src为空,则imread函数有问题,可能是图片本身有问题。
    【解决方案2】:

    试试这个:

    /// Load source image and convert it to gray
    Mat src = imread( "hat-10.bmp", 1 );
    
    Mat src_gray(src.size(), CV_8U);
    cvtColor( src, src_gray, CV_BGR2GRAY );
    
    blur( src_gray, src_gray, Size(3,3) );
    
    //Apply threshold
    cv::Mat thres_output(src_gray.size(), src_gray.type());
    cv::threshold(src_gray, thres_output, 100, 255, cv::THRESH_BINARY);
    qDebug("Ok 1");
    

    OpenCV 文档在 Basic Thresholding Operations 上有完整的演示。

    编辑:

    在仔细检查了您的代码和 cmets 之后,我想我知道发生了什么:这些问题可能是因为 imread() 无法访问指定的文件。这使得函数返回一个空的Mat。要检查是否是这种情况,只需执行以下操作:

    Mat src = imread( "hat-10.bmp", 1 );
    if (src.empty())
    {
        std::cout << "!!! imread failed to open image\n";
        return;
    }
    

    之所以会出现这种情况是因为Qt Creator将项目的.exe构建在一个单独的文件夹中,所以当应用程序运行时,它会尝试从.exe所在的目录加载图片已启动,但由于图像不存在而失败。

    当调用imread() 时记得将完整路径传递给文件。看看这是否能解决问题。

    编辑

    记得在将图像输入到findContours() 之前将其转换为二进制:

    // Convert from 32F to 8U
    cv::Mat binary_img;
    canny_output.convertTo(binary_img, CV_8U);
    
    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(binary_img, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    

    【讨论】:

    • 我认为 cv::threshold() 导致了崩溃,这就是它让你使用 Canny 的原因。
    • 是的,它曾经导致崩溃,但现在不再(我必须检查我的 PATH 目录)问题是:此代码在命令行中运行良好,但在 GUI 中崩溃;有什么想法吗?
    • 更新帖子。它没有解决问题,但调试输出改变了(?)
    • 新调试中列出的函数均与 OpenCV 无关。您需要查明是哪个 OpenCV 调用导致了崩溃。
    • 好像是findContours,因为函数后面的注释没有显示,而是Qt以代码-1073741819退出了找了之后,发现这段代码表明我正在尝试访问不存在的内存。但是当我在窗口的构造函数中调用这个相同的函数时,它就像一个魅力!
    【解决方案3】:

    我使用了函数 Qtconcurrent::run() 并且一切都开始工作了。 即使这不是永久(也不是好的)解决方案;这就是我能想到的。

    不过,我仍然愿意接受其他答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-06
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 2018-07-30
      • 2017-07-12
      相关资源
      最近更新 更多