我正在开展一个生物识别登录项目,其中人脸识别是其中的一部分。我们正在使用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,以防它在需要之前以某种方式意外删除。这也没有帮助。
为了增加乐趣,这个确切的代码在我正在使用的人的计算机上运行良好。非常感谢任何帮助/提示。
答案 0 :(得分:0)
您正在传递对空对象的引用:
void passTakenImage(Mat& img) {
在AuthThread开始工作之前,该对象将被删除:
delete takenImage;
所以,按值传递,而不是通过引用传递:
void passTakenImage(Mat img) {
现在,只要AuthThread还活着,AuthThread就会处理一个活着的img副本。