我希望从QMediaPlayer
获取每个帧并将其转换为QImage
(或cv::Mat
)
所以我使用了来自videoFrameProbed
的{{1}}信号:
QVideoProbe
但我没有找到任何方法从connect(&video_probe_, &QVideoProbe::videoFrameProbed,
[this](const QVideoFrame& currentFrame){
//QImage img = ??
}
获取QImage
!
如何将QVideoFrame
转换为QVideoFrame
?!
答案 0 :(得分:8)
您可以使用QImage的构造函数:
QImage img( currentFrame.bits(),
currentFrame.width(),
currentFrame.height(),
currentFrame.bytesPerLine(),
imageFormat);
您可以从[{1}}的{{1}}获得imageFormat
的位置:
pixelFormat
答案 1 :(得分:5)
对于QCamera输出,该方法并不总是有效。特别是,QVideoFrame :: imageFormatFromPixelFormat()在给定QVideoFrame :: Format_Jpeg时返回QImage :: Format_Invalid,这是我的QCamera中出现的内容。但这有效:
QImage Camera::imageFromVideoFrame(const QVideoFrame& buffer) const
{
QImage img;
QVideoFrame frame(buffer); // make a copy we can call map (non-const) on
frame.map(QAbstractVideoBuffer::ReadOnly);
QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(
frame.pixelFormat());
// BUT the frame.pixelFormat() is QVideoFrame::Format_Jpeg, and this is
// mapped to QImage::Format_Invalid by
// QVideoFrame::imageFormatFromPixelFormat
if (imageFormat != QImage::Format_Invalid) {
img = QImage(frame.bits(),
frame.width(),
frame.height(),
// frame.bytesPerLine(),
imageFormat);
} else {
// e.g. JPEG
int nbytes = frame.mappedBytes();
img = QImage::fromData(frame.bits(), nbytes);
}
frame.unmap();
return img;
}
答案 2 :(得分:1)
在很多情况下,Qt都具有将QVideoFrame
转换为QImage
的私有功能。如果要使用它,则需要像向前声明一样标头:
QImage qt_imageFromVideoFrame( const QVideoFrame& f );
这适用于大多数情况,包括来自YUV的转化。但是,对于Android,您确实需要使用OpenGL调用来从GLTexture检索图像。下面演示了如何获取ARGB32格式的QImage:
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QQmlContext>
QImage qt_imageFromVideoFrame( const QVideoFrame& f );
QImage QVideoFrameToQImage( const QVideoFrame& videoFrame )
{
if ( videoFrame.handleType() == QAbstractVideoBuffer::NoHandle )
{
QImage image = qt_imageFromVideoFrame( videoFrame );
if ( image.isNull() )
{
return QImage();
}
if ( image.format() != QImage::Format_ARGB32 )
{
image = image.convertToFormat( QImage::Format_ARGB32 );
}
return image;
}
if ( videoFrame.handleType() == QAbstractVideoBuffer::GLTextureHandle )
{
QImage image( videoFrame.width(), videoFrame.height(), QImage::Format_ARGB32 );
GLuint textureId = static_cast<GLuint>( videoFrame.handle().toInt() );
QOpenGLContext* ctx = QOpenGLContext::currentContext();
QOpenGLFunctions* f = ctx->functions();
GLuint fbo;
f->glGenFramebuffers( 1, &fbo );
GLint prevFbo;
f->glGetIntegerv( GL_FRAMEBUFFER_BINDING, &prevFbo );
f->glBindFramebuffer( GL_FRAMEBUFFER, fbo );
f->glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0 );
f->glReadPixels( 0, 0, videoFrame.width(), videoFrame.height(), GL_RGBA, GL_UNSIGNED_BYTE, image.bits() );
f->glBindFramebuffer( GL_FRAMEBUFFER, static_cast<GLuint>( prevFbo ) );
return image;
}
return QImage();
}
答案 3 :(得分:1)
对于发现在Qt5.15.0中不再存在qt私有函数“ qt_imageFromVideoFrame”之后到此处结束的任何人,您现在可以使用新实现的方法QImage QVideoFrame :: image()。
QImage img = frame.image();
我已经在Ubuntu上对其进行了测试,并且可以正常工作。