Qt:从相机中连续捕捉图像充满了记忆



我正在尝试连续捕获图像,以便使用UDP发送图像。我这样做是为了实现一个实时视频流程序。

下面的代码连续捕获图像,并将图像分配给QGraphicsScene,这样我就可以测试图像是否像视频一样播放。但当我运行程序时,即使我删除了指针,我的电脑也会在几秒钟后冻结。如何解决此问题?

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
cam = new QCamera;
cam->setCaptureMode(QCamera::CaptureStillImage);
viewfinder = new QCameraViewfinder;
viewfinder->show();
QCameraImageCapture *cap = new QCameraImageCapture(cam);
cap->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
cam->setViewfinder(viewfinder);

QObject::connect(cap, &QCameraImageCapture::imageCaptured, [=] (int id, QImage img) {
while(true){
QByteArray *buf = new QByteArray;
QBuffer *buffer=new QBuffer(buf);
buffer->open(QIODevice::WriteOnly);
img.save(buffer, "BMP");
QPixmap *pixmap = new QPixmap();
pixmap->loadFromData(buffer->buffer());
scene->addPixmap(*pixmap);
delete buf;
delete buffer;
delete pixmap;
QThread::sleep(0.0416);
cap->capture();
}
});
QObject::connect(cap, &QCameraImageCapture::readyForCaptureChanged, [=] (bool state) {
if(state == true) {
cam->searchAndLock();
cap->capture();
cam->unlock();
}
});
cam->start();
}
MainWindow::~MainWindow()
{
delete ui;
}

您应该使用imageAvailable((而不是imageCaptured信号。

这里有一个例子:

connect(cap, &QCameraImageCapture::imageAvailable, [=] (int id, QVideoFrame v ) {
if (v.isValid()) {
if(v.map(QAbstractVideoBuffer::ReadOnly)) {
QByteArray bitsVideo( (char *) v.bits(), v.mappedBytes() );
//call to your send raw data function (over UDP) : 
//datagram will contain frame details e.g : [ width, hight, byteperline, format, rawdata ]
sendDataOverUDP( v.width(), v.height(), 
v.bytesperLine(), 
QVideoFrame::imageFormatFromPixelFormat(v.pixelFormat()), 
bitsVideo );

}
}
});

另一方,服务器或其他客户端将根据收到的原始数据创建图像,如下所示:

void onDataImageReceived( int width, int height, 
int bytePerLine, 
QImage::Format fmt, 
QByteArray bitsVideo )
{
QImage img ((uchar *)bitsVideo.data(), width, height, bytesPerLine, fmt);
//do something with img ...
}

我不熟悉QCamera和相关类,但连接QCameraImageCapture::imageCaptured信号的lambda看起来不正确。该信号是在单个帧准备好进行预览时发出的。然而,在您的lambda中,您已经。。。

while(true){
QByteArray *buf = new QByteArray;
QBuffer *buffer=new QBuffer(buf);
buffer->open(QIODevice::WriteOnly);
img.save(buffer, "BMP");
QPixmap *pixmap = new QPixmap();
pixmap->loadFromData(buffer->buffer());
scene->addPixmap(*pixmap);
delete buf;
delete buffer;
delete pixmap;
QThread::sleep(0.0416);
cap->capture();
}

while循环永远不会退出并且将阻塞Qt事件处理循环。还要注意,代码块。。。

QByteArray *buf = new QByteArray;
QBuffer *buffer=new QBuffer(buf);
buffer->open(QIODevice::WriteOnly);
img.save(buffer, "BMP");
QPixmap *pixmap = new QPixmap();
pixmap->loadFromData(buffer->buffer());
scene->addPixmap(*pixmap);
delete buf;
delete buffer;
delete pixmap;

是过度杀伤和(除非我错了(基本上相当于…

scene->addPixmap(QPixmap::fromImage(img));

所以我认为你的lambda应该更像(未经测试(。。。

[=](int id, QImage img)
{
scene->addPixmap(QPixmap::fromImage(img));
}

您实现的目标是";。。。连续捕捉图像并发送"通过缓慢的QCameraImageCapture循环调用故障(滞后、UI阻塞(。

最好使用下面的子类。

// subclass from QAbstractVideoSurface
class AltVideoSurface: public QAbstractVideoSurface{
Q_OBJECT
public:
AltVideoSurface(QObject * parentLabel=NULL) : QAbstractVideoSurface(parentLabel)
{
this->parentLabel = (QLabel*)parentLabel;
}
QLabel * parentLabel;
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const {
return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_RGB24;
}
// will called on every new video frame
bool present(const QVideoFrame& frame)
{
if ( frame.isValid() ) {

// clone frame
QVideoFrame cloneFrame(frame);
// map frame's memory from video to cpu
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);

// have a full resolution image
QImage imageFull(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat()));

// release cpu mapping
cloneFrame.unmap();

// perhaps make an additional scaled image
QImage imageSmall = imageFull.scaled( 640, 480, Qt::KeepAspectRatio);
// render small image in UI viewlinder (here a QLabel)
parentLabel->setPixmap(QPixmap::fromImage(imageSmall));

return true;
} 

return false;
}
};

mainwindow h-file
~~~~~~~~~~~~~~~~~
...
QScopedPointer<QCamera> m_camera;
AltVideoSurface*        m_surface;
...


mainwindow cpp-file 
~~~~~~~~~~~~~~~~~~~
Call the subclassed QAbstractVideoSurface within your camera init method.
...
// init camera
m_camera.reset(new QCamera(QCameraInfo::defaultCamera()));
// set video mode
m_camera->setCaptureMode(QCamera::CaptureVideo);

// the subclassed QAbstractVideoSurface as view (here a QLabel) gets full resolution images
m_surface = new AltVideoSurface(ui->labelView);

// connect camera, viewfinder and subclassed surface
m_camera->setViewfinder(m_surface);

... 

相关内容

  • 没有找到相关文章

最新更新