簡體   English   中英

使用opencv的內存泄漏:VideoCapture

[英]Memory leak using opencv : VideoCapture

我使用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)是內存泄漏的原因。 我必須使用此功能,因為我正在處理Qt無法讀取的16位灰度圖像。 我打開圖像並使用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,請嘗試使用imwrite將圖像臨時保存在opencv中並將圖像加載到Qt中。 如果memleak消失。 分析convert16uc1

或者不調用convert16uc1(src),而是使用先前在Qt中加載的其他常量圖像來調用addPixmap

通過閱讀此線程 ,我找到了導致該問題的原因以及如何解決該問題。

從Qt文檔中:

無效的QGraphicsScene :: removeItem(QGraphicsItem * 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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM