简体   繁体   中英

Program crashes when using cv::findContours with Qt Gui

I have been stuck with this issue for days;

I created a Qt console project, connected it with OpenCV and everything was working just fine;

I created a Qt Gui project, added a button and copied the same code from the previous project in the button's slot, I got a windows segFault and program exited with code -1073741819.

So I used the debugger to detect the problem and it turned out to be at the use of function cv::threshold .

I changed it and instead used cv::Canny but then I got the same problem with cv::findContours !

The strange thing is that when I called the button's 'MainWindow::on_pushButton_clicked()' in the windows' constructor it worked!!!

here's debugger output:

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) const  C:\OpenCV2.4\OpenMinGw\install\bin\libopencv_core240.dll    0   0x65c1a838  
2   ??      0   0x00000000

and here's the function where I get the error (which I got from OpenCV tutorials):

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);

    }

Using:

  • Windows 7 x64

  • OpenCV 2.4.0 compiled using mingw 4.1.0

  • Qt Creator 2.0.0 Based on Qt 4.7.0 (32 bit)

here's a shorter version of my code :

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 );

}

in console mode, there's no problem. when called from GUI app constructor there's also no problem. It only crashes when actually clicking on the button.

I took a screenshot ![here] http://i.stack.imgur.com/1LyeF.png canny_output was displayed which means image was loaded. 我截图了![在这里] http://i.stack.imgur.com/1LyeF.png canny_output被显示,这意味着图像已加载。

Uploaded project here

First make sure that the image that you want to threshold is really a gray scaled image. Show it in another window after Thresholding.

Do that before cv::FindContours:

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

also change that:

vector<vector<Point> > contours;

to:

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

Try this:

/// 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 docs have a full demo on Basic Thresholding Operations .

EDIT:

After carefully reviewing your code and comments, I think I know what's going on: these problems might be happening because imread() can't access the specified file . This makes the function return an empty Mat . To check if this is the case, simply do:

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

The reason why it happens is because Qt Creator builds the .exe of the project in a separate folder, so when the application runs, it tries to load the image from the directory where the .exe was launched, and it fails because the image isn't there.

When calling imread() remember to pass the FULL PATH to the file. See if that fixes the issue.

EDIT :

Remember to convert the image to binary before feeding it to 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);

I used function Qtconcurrent::run() and everything started working. Even though this isn't a permanent (nor a good) solution; this is all I could come up with.

I'm still open to other answers though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM