使用opencv: VideoCapture的内存泄漏



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

它使用cv:: videoccapture和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()));
}

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

EDIT:函数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);
}

很可能是convert16uc1

如果你不能在这里发布convert16uc1,尝试在openv中使用imwrite暂时保存图像并在Qt中加载图像。分析convert16uc1 .

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

我找到了导致问题的原因以及如何修复它,阅读此线程。

来自Qt文档:

void QGraphicsScene::removeItem (QGraphicsItem * item)

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

参见addItem()。

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

修复:FenetrePrinc::tick(): 函数removeItem(img_src):之后调用delete img_src
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();
}

相关内容

  • 没有找到相关文章

最新更新