前言:
终于要来点干货了,本次教程会取出视频帧,笔者使用的是Qt5.15.2
在Qt5.15.2(qml)摄像头显示示例的基础上修改
一、增加图像提供者类
定义类ImageProvider,头文件如下
class ImageProvider : public QQuickImageProvider
{
public:
explicit ImageProvider();
QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
//设置图像
static void setImage(const QImage &image);
signals:
private:
//存储最后一帧
static QImage ms_image;
};
源文件关键代码如下
//qml调用,以获取显示图像
QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
{
qDebug()<<"ImageProvider::requestPixmap"<<id;
int width = ms_image.width();
int height = ms_image.height();
if (size)
*size = QSize(width, height);
return QPixmap::fromImage(ms_image.scaled(requestedSize.width() > 0 ? requestedSize.width() : width,
requestedSize.height() > 0 ? requestedSize.height() : height));
}
//设置最后一帧图像
void ImageProvider::setImage(const QImage &image)
{
qDebug()<<"ImageProvider::setImage"<<image;
ms_image = image;
}
二、增加取帧的处理类
新建一个类Tool_VideoFrames,在类内部,实例化QVideoProbe,并设置源
关键代码如下
connect( &m_probe, &QVideoProbe::videoFrameProbed,
this, &Tool_VideoFrames::onProcssFrame );
void Tool_VideoFrames::setQmlCamera(QObject *qmlCamera)
{
this->m_qmlCamera = qmlCamera;
if( m_qmlCamera )
{
//将QML对象转换为C++对象
m_camera = qvariant_cast< QCamera* >( m_qmlCamera->property( "mediaObject" ) );
//将类QVideoFrameProbe的实例化对象_probe的数据来源设为_camera
m_probe.setSource( m_camera );
}
qDebug() << "set Camera success!";
}
//处理获取到的视频帧
void Tool_VideoFrames::onProcssFrame(const QVideoFrame &frame)
{
const QImage image = frame.image();
//将视频帧放入图像提供者
ImageProvider::setImage(image);
emit newVideoFrame(image);
}
三、主函数main()修改
1.初始化,并增加图像提供者
添加代码如下
engine.addImageProvider(QLatin1String("imageProvider"), new ImageProvider);
2.注册帧的处理类
添加代码如下
qmlRegisterType<Tool_VideoFrames>("com.xdqd.classes", 1, 0, "Tool_VideoFrames");
四、修改UI显示
如下所示,是笔者修改的UI
注:一定记得Image的cache属性要设置为false,否则图像不会发生变化
修改qml文件,关键代码如下
Tool_VideoFrames {
id: tool_VideoFrames
//此处会调用C++类 CameraFromQML中, 属性的setQmlCamera( QObject *qmlCamera ) 方法
qmlCamera: camera
}
Connections {
target: tool_VideoFrames
function onNewVideoFrame(videoFrame){
//必须要更换下,否则图像不会发生变化
image.source = "image://imageProvider/0"
image.source = "image://imageProvider/1"
}
}
注:Image的源也可用使用随机数,但必须要更换下,否则不会触发图像的变化
程序运行如下
大功告成
本教程示例源码
后记:
取视频帧成功,只使用Qt/qml的库,看起来不错。有细心的小伙伴已经注意了,怎么预览画面与取出的帧不太一样?没错,可能是一样的,但若换个摄像头,取出的帧就可能发生倒置或镜像。若使用的摄像头是确定的,这没问题,但无法做成通用程序。
因时间关系,笔者只在win10下使用minGW(64+32位)和VS2019(64+32位),android(arm8_64)测试,其他平台未测试,感兴趣的小伙伴可以测试下其他平台
下一往篇,继续讲解处理方法