内存泄漏使用opencv:VideoCapture

时间:2015-05-29 09:33:02

标签: c++ qt opencv memory-leaks

我使用Qt Creator 2.4.1(Qt 4.8.4)和OpenCV 2.4.2开发了一个应用程序,它从文件夹中读取图像并显示它们。

它使用cv :: VideoCapture和QGraphicsScene / QGraphicsView。它运行良好,但我遇到了内存泄漏:如果我查看任务管理器中消耗的内存,每次读取新图像并最终崩溃时内存会上升。

我的主窗口是使用Qt Designer创建的,它是一个继承QMainWindow的类。它上面有一个QGraphicsView view_src,还有一个按钮:buttonStart

以下是代码示例:类声明:

using namespace std;
using namespace cv;

namespace Ui {
    class FenetrePrinc;
}

class FenetrePrinc : public QMainWindow {
    Q_OBJECT
public:
    explicit FenetrePrinc(QWidget *parent = 0);
    ~FenetrePrinc();

public slots:
    virtual void start();
    virtual void tick();
    virtual void stop_timer();

private:
    Ui::FenetrePrinc *ui;

    QString filename;
    QGraphicsScene *scene_src;
    QGraphicsItem *img_src;

    VideoCapture sequence;

    Mat src;
};

班级定义:

FenetrePrinc::FenetrePrinc(QWidget *parent) : QMainWindow(parent), ui(new Ui::FenetrePrinc){

    ui->setupUi(this);
    scene_src = new QGraphicsScene();
    timer = new QTimer(this);

    img_src = scene_src->addPixmap(QPixmap("vide.jpg"));
    ui->view_src->setScene(scene_src);

    connect(ui->buttonStart, SIGNAL(clicked()), this, SLOT(start()));
}

FenetrePrinc::~FenetrePrinc(){
    delete scene_src;
    delete img_src;
    delete ui;
}

void FenetrePrinc::start(){
    if(src.empty())
        sequence.open(filename.toStdString());

    connect(timer, SIGNAL(timeout()), this, SLOT(tick()));
    timer->start(1000/24);   //24 frames per second

    disconnect(ui->buttonStart, SIGNAL(clicked()), this, SLOT(start()));
    connect(ui->buttonStart, SIGNAL(clicked()), this, SLOT(stop_timer()));
}

void FenetrePrinc::tick(){
    sequence >> src;

    if(src.empty())
    {
        sequence.release();
        stop_timer();
        return;
    }

    scene_src->removeItem(img_src);
    img_src = scene_src->addPixmap(convert16uc1(src));

    src.release();
}

void FenetrePrinc::stop_timer(){
    timer->stop();
    disconnect(timer, SIGNAL(timeout()), this, SLOT(tick()));

    disconnect(ui->buttonStart, SIGNAL(clicked()), this, SLOT(stop_timer()));
    connect(ui->buttonStart, SIGNAL(clicked()), this, SLOT(start()));
}

我不明白为什么每次读取图像时内存使用率都会上升,我会在每次读取时释放图像,并在完成后释放序列。但也许我错过了什么?

编辑:函数QPixmap convert16uc1(Mat img)是内存泄漏的原因。我必须使用这个功能,因为我正在使用16位灰度图像,Qt无法读取。我用OpenCV打开图像并执行图像处理,并用Qt显示图像。

该功能的代码如下:

QPixmap FenetrePrinc::convert16uc1(const cv::Mat& source)
{
  quint16* pSource = (quint16*) source.data;
  int pixelCounts = source.cols * source.rows;

  QImage dest(source.cols, source.rows, QImage::Format_RGB32);

  char* pDest = (char*) dest.bits();

  for (int i = 0; i < pixelCounts; i++)
  {
    quint8 value = (quint8) ((*(pSource)) >> 8);
    *(pDest++) = value;  // B
    *(pDest++) = value;  // G
    *(pDest++) = value;  // R
    *(pDest++) = 0;      // Alpha
    pSource++;
  }
  return QPixmap::fromImage(dest);
}

2 个答案:

答案 0 :(得分:1)

最有可能的是convert16uc1

如果您无法在此处发布convert16uc1,请尝试使用imwrite将图像暂时保存在opencv中并在Qt中加载图像。如果memleak消失了。分析convert16uc1

或者不要调用convert16uc1(src),而是使用先前在Qt中加载的其他常量图像调用addPixmap

答案 1 :(得分:0)

我找到导致问题的原因以及解决方法,阅读此thread

来自Qt文档:

  

void QGraphicsScene :: removeItem(QGraphicsItem * item)

     

从场景中移除项目项及其所有子项。 item的所有权传递给调用者(即,QGraphicsScene在销毁时将不再删除项目。)

     

另见addItem()。

一旦调用了QGraphicsScene :: removeItem(QGraphicsItem * item)`,QGraphicsScene将在销毁时不再删除该项目。

修正:在delete img_src之后致电removeItem(img_src):在函数FenetrePrinc::tick()中:

void FenetrePrinc::tick(){
    sequence >> src;

    if(src.empty())
    {
        sequence.release();
        stop_timer();
        return;
    }

    scene_src->removeItem(img_src);
    delete img_src;
    img_src = scene_src->addPixmap(convert16uc1(src));

    src.release();
}