2015-05-29 365 views
1

我開發了一個應用程序,使用Qt Creator 2.4.1(Qt 4.8.4)和OpenCV 2.4.2從文件夾讀取圖像並顯示它們。使用opencv的內存泄漏:VideoCapture

它使用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); 
} 
+1

請與最近的OpenCV的版本,2.4試試。2太老 – berak

+1

如果你不顯示的圖像與Qt(只讀圖像,不顯示),它是否泄漏內存呢? – Micka

+0

@Micka:如果我不顯示圖像,即使我沒有通過src.release()釋放圖像也沒有內存泄漏;產生內存泄漏的行是:img_src = scene_src.addPixmap (convert16uc1(src));' – zarachbaal

回答

0

我發現是什麼原因導致了這個問題,以及如何解決這個問題,請閱讀thread

從Qt文檔:

無效QGraphicsScene ::的removeItem(*的QGraphicsItem項目)

刪除項項目,並從現場的所有兒童。 item的所有權被傳遞給調用者(即,QGraphicsScene在銷燬時不再刪除項目)。

另請參閱addItem()。

一旦調用了QGraphicsScene :: removeItem(QGraphicsItem * item)`,QGraphicsScene將不再刪除該物品。

修復:removeItem(img_src)後致電delete 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(); 
} 
1

極有可能是convert16uc1

如果您無法在此處發佈convert16uc1,請嘗試使用imwrite將圖像臨時保存在opencv中,然後在Qt中加載圖像。如果memleak消失。分析convert16uc1

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

+0

是的,如果我將'scene_src-> addPixmap(convert16uc1(srt))'改爲'scene_src-> addPixmap(QPixmap( 「vide.jpg」))'我沒有內存泄漏了。我編輯了我的問題來添加'convert16uc1'代碼。 – zarachbaal

+0

我做了你的建議:我不是使用'QPixmap convert16uc1(Mat source)'將圖像從OpenCV轉換爲Qt,而是使用'mwrite'來臨時保存圖像,並使用Qt加載此圖像。 我沒有內存泄漏了這種技術。 – zarachbaal

+1

@zarachbaal:這只是一個測試的建議!這將是非常緩慢的轉換。我會嘗試你的代碼,並可能找到原因。 –