2015-05-29 71 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:这只是一个测试的建议!这将是非常缓慢的转换。我会尝试你的代码,并可能找到原因。 –