OpenCV / QThread段错误

时间:2016-05-31 12:35:30

标签: c++ qt opencv segmentation-fault

我正在开展一个生物识别登录项目,其中人脸识别是其中的一部分。我们正在使用OpenCV 2.4.13。我们有一个Qt GUI应用程序,它产生一个线程并传递一张图片进行验证,如下所示:

void MainWindow::on_button_test_auth_clicked()
{
    statusLabel->setText("Authenticating...");
    statusLabel->repaint();

    Mat* takenImage = cam->takePicture();

    AuthThread *authThread = new AuthThread();
    connect(authThread, SIGNAL(resultReady(const QString&)), this, SLOT(setLabelText(const QString&)));
    connect(authThread, &AuthThread::finished, authThread, &QObject::deleteLater);

    authThread->passTakenImage(*takenImage);
    authThread->start();   

    delete takenImage;
}

AuthThread看起来像:

class AuthThread : public QThread
{
    Q_OBJECT
    void run() Q_DECL_OVERRIDE {
        Ptr<FaceRecognizer> model = createLBPHFaceRecognizer(4,8,8,8);

        model->load(Config::getModelFile().toStdString());

        int label = -1;
        double distance = 0.0;

        model->predict(takenImage, label, distance);

        QString labelString;
        QTextStream labelStream(&labelString);

        double threshold = Config::getThreshold();

        if(distance < threshold) {
            labelStream << "Authenticated as " << label << "! " << QString::number((threshold - distance), 'f', 2) << " under threshold.";
        } else {
            labelStream << "Not authenticated! " << QString::number((distance - threshold), 'f', 2) << "over threshold.";
        }

        emit resultReady(labelString);
    }

public:
    void passTakenImage(Mat& img) {
        takenImage = img;
    }

private:
    Mat takenImage;
signals:
    void resultReady(const QString &s);
};

第一次on_button_test_auth_clicked()被调用时,这一切都正常,但第二次在model->predict(takenImage, label, distance);

上进行了段错误

我已经尝试运行valgrind来查看到底出了什么问题,但我对c ++很新,所以我无法理解输出,这是:

==6732== Thread 12 AuthThread:
==6732== Invalid read of size 8
==6732==    at 0x8C94262: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C9432A: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C95E27: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C94C21: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C8F50F: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C8D724: tbb::internal::allocate_root_with_context_proxy::allocate(unsigned long) const (in /usr/lib/libtbb.so.2)
==6732==    by 0x530D7DA: tbb::interface9::internal::start_for<tbb::blocked_range<int>, cv::calcHist1D_Invoker<float>, tbb::auto_partitioner const>::run(tbb::blocked_range<int> const&, cv::calcHist1D_Invoker<float> const&, tbb::auto_partitioner const&) (in /usr/lib/libopencv_imgproc.so.2.4.13)
==6732==    by 0x531378A: cv::calcHist(cv::Mat const*, int, int const*, cv::_InputArray const&, cv::_OutputArray const&, int, int const*, float const**, bool, bool) (in /usr/lib/libopencv_imgproc.so.2.4.13)
==6732==    by 0x5DABFA5: ??? (in /usr/lib/libopencv_contrib.so.2.4.13)
==6732==    by 0x5DB5899: ??? (in /usr/lib/libopencv_contrib.so.2.4.13)
==6732==    by 0x5DB64DD: cv::LBPH::predict(cv::_InputArray const&, int&, double&) const (in /usr/lib/libopencv_contrib.so.2.4.13)
==6732==    by 0x428940: AuthThread::run() (auththread.h:28)
==6732==  Address 0xfffffffffffffff7 is not stack'd, malloc'd or (recently) free'd
==6732== 
==6732== 
==6732== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==6732==  Access not within mapped region at address 0xFFFFFFFFFFFFFFF7
==6732==    at 0x8C94262: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C9432A: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C95E27: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C94C21: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C8F50F: ??? (in /usr/lib/libtbb.so.2)
==6732==    by 0x8C8D724: tbb::internal::allocate_root_with_context_proxy::allocate(unsigned long) const (in /usr/lib/libtbb.so.2)
==6732==    by 0x530D7DA: tbb::interface9::internal::start_for<tbb::blocked_range<int>, cv::calcHist1D_Invoker<float>, tbb::auto_partitioner const>::run(tbb::blocked_range<int> const&, cv::calcHist1D_Invoker<float> const&, tbb::auto_partitioner const&) (in /usr/lib/libopencv_imgproc.so.2.4.13)
==6732==    by 0x531378A: cv::calcHist(cv::Mat const*, int, int const*, cv::_InputArray const&, cv::_OutputArray const&, int, int const*, float const**, bool, bool) (in /usr/lib/libopencv_imgproc.so.2.4.13)
==6732==    by 0x5DABFA5: ??? (in /usr/lib/libopencv_contrib.so.2.4.13)
==6732==    by 0x5DB5899: ??? (in /usr/lib/libopencv_contrib.so.2.4.13)
==6732==    by 0x5DB64DD: cv::LBPH::predict(cv::_InputArray const&, int&, double&) const (in /usr/lib/libopencv_contrib.so.2.4.13)
==6732==    by 0x428940: AuthThread::run() (auththread.h:28)
==6732==  If you believe this happened as a result of a stack
==6732==  overflow in your program's main thread (unlikely but
==6732==  possible), you can try to increase the size of the
==6732==  main thread stack using the --main-stacksize= flag.
==6732==  The main thread stack size used in this run was 8388608.

这似乎表明libtbb.so,线程构建块出现问题,我认为这是QThread的动力。

奇怪的是,当我将AuthThread代码移动到on_button_test_auth_clicked()时,无论调用多少次它都能正常工作。也许旧线程中的东西会粘在一起并且第二次混乱?

opencv Ptr,它的工作方式与shared_ptr类似,应该在模型超出范围后进行清理(显式释放它没有帮助)。所有其他的东西都是堆栈分配的,所以据我所知他们不应该引起任何内存问题。

我尝试的另一件事是克隆图像Mat,以防它在需要之前以某种方式意外删除。这也没有帮助。

为了增加乐趣,这个确切的代码在我正在使用的人的计算机上运行良好。非常感谢任何帮助/提示。

1 个答案:

答案 0 :(得分:0)

您正在传递对空对象的引用:

void passTakenImage(Mat& img) {  

在AuthThread开始工作之前,该对象将被删除:

delete takenImage;  

所以,按值传递,而不是通过引用传递:

void passTakenImage(Mat img) {  

现在,只要AuthThread还活着,AuthThread就会处理一个活着的img副本。