Qt QML摄像头至C++;Android上的QImage
我有一个基于Qt5.4的带有一些图像处理的程序。我使用Qt QML摄像头至C++;Android上的QImage,android,qt,camera,qml,Android,Qt,Camera,Qml,我有一个基于Qt5.4的带有一些图像处理的程序。我使用QCamera和我的videoSurface(源自QAbstractVideoSurface)来获取视频帧。它在Windows上运行良好 但现在我需要Android版本的应用程序。我发现QCamera在Android上不起作用。但我看到QML摄像头示例在Android上运行时没有任何问题 所以我决定用QML重写我的应用程序。 主要问题:在C++中,我不能访问QML相机的表面。 void myVideoOutput::setSource(QOb
QCamera
和我的videoSurface
(源自QAbstractVideoSurface
)来获取视频帧。它在Windows上运行良好
但现在我需要Android版本的应用程序。我发现QCamera
在Android上不起作用。但我看到QML摄像头示例在Android上运行时没有任何问题
所以我决定用QML重写我的应用程序。
主要问题:在C++中,我不能访问QML相机的表面。
void myVideoOutput::setSource(QObject *source)
{
qDebug() << Q_FUNC_INFO << source;
if (source == m_source.data())
return;
m_source = source;
if (m_source) {
const QMetaObject *metaObject = m_source.data()->metaObject();
QStringList properties;
for(int i = metaObject->propertyOffset(); i < metaObject >propertyCount(); ++i)
properties << QString::fromLatin1(metaObject->property(i).name());
qDebug() << properties;
}
.....
emit sourceChanged();
}
void myVideoOutput::setSource(QObject*source)
{
qDebug()propertyOffset();ipropertyCount();++i)
属性(i.name());
是的,这是可能的。我想到了两种方法
使用QBStractVideoFilter和QVideoFilterRunnable类(仅限Qt5.5!)非常好。它们是专门为这种情况开发的,非常容易使用
网络上有几个使用它的好例子:
这种方法的缺点是,正如我们所说的,在Android设备上,QVideoFrame指针没有原始像素数据,相反,它有一个需要读回的OpenGL纹理(我发布的第二个示例有一个解决这个问题的方法),因此这种方法对于实时目的来说并不是很好
我最后用来解决这个问题的是课堂
首先,您必须命名QML相机的实例:
Camera {
id: camera
objectName: "qrCameraQML"
}
然后从C++方面得到这个实例,类似于:
QObject *qmlCamera = engine.rootObjects().at(0).findChild<QObject*>("qrCameraQML");
在我的示例中,摄像头和探头只是:
QCamera *camera_;
QVideoProbe probe_;
根据我的经验,这种方法(对于android平台)比使用qt视频过滤器类快得多,但它的缺点是基本上只读取来自qml的视频输出,并且可能无法将后处理视频帧发送回qml
如果您真的需要将处理后的图像发送回qml,我建议您尝试第一种方法,看看会发生什么
2) Qtafaik没有,可能是OpenCv或其他库
我认为上面的答案充分解释了QML摄像机的处理过程
是的,我发现这个项目对我有很多帮助:
将插件注册到QML,可以这样使用:
处理图像非常简单。该类只绘制项目,以便它可以在QML上使用。所有其他处理都在后端进行,因此相机使用的Mat图像可以用于处理。我想突出显示@waldez junior first answer。在QML中,您将QAbstractVideoFilter
组件添加到视频输出中
Camera {
id: camera
}
VideoOutput {
id: videoOutput
source: camera
filters: [ videoFilter ]
autoOrientation: true
}
MyVideoFilter {
id: videoFilter
// orientation: videoOutput.orientation
}
在C++中,你实现了QueXToFieldFulter 组件,这里有一个极小的例子:
class MyVideoFilter : public QAbstractVideoFilter
{
Q_OBJECT
public:
QVideoFilterRunnable *createFilterRunnable() Q_DECL_OVERRIDE
{
return new CustomFilterRunnable(this);
}
};
class MyVideoFilterRunnable : public QVideoFilterRunnable
{
public:
QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat& surfaceFormat, RunFlags flags)
{
if (!input->isValid())
{
return *input;
}
// do stuff with input
return *input;
}
};
```
Qt源代码中有一个QAbstractVideoFilter示例:
为了使事情更容易,考虑使用Qt内部函数<代码> QtyIMAGIVIOVFROWRAME/<代码>将<代码> qVoFrRAME> <代码>转换为<代码> QImage <代码>。该代码适用于<代码> NoHandle Case>>并在大多数平台上运行。不幸的是,它不适用于很多Android设备,因为<代码> QVIEFFRAM::MAP()
将返回false
extern QImage qt_imageFromVideoFrame(const QVideoFrame& f);
对于Android,您需要处理GLTextureHandle
的情况,即使用OpenGL填充QImage
在某些设备上,图像内部位缓冲区将出现翻转
#ifdef Q_OS_ANDROID
bool flip = true;
#else
bool flip = surfaceFormat.scanLineDirection() == QVideoSurfaceFormat::BottomToTop;
#endif
在某些设备上,图像也可能会旋转。处理旋转的最佳方法是在VideoOutput
组件中设置autoOrientation:true
。然后,您的组件就可以复制VideoOutput.orientation
了解图像是如何翻转和旋转的将有助于视频识别应用(例如人脸识别)
我还使用
qbstractvideofilter
和QVideoFilterRunnable
类在上创建了一个最小的工作示例。我想强调一下@WaldezJunior First solution中显示的OpenGL代码处理GLTextureHandle在Qt5.9.1上不工作,setSource始终返回False对于所有其他具有类似问题的人问题:看,我希望这能帮上一点忙
class MyVideoFilter : public QAbstractVideoFilter
{
Q_OBJECT
public:
QVideoFilterRunnable *createFilterRunnable() Q_DECL_OVERRIDE
{
return new CustomFilterRunnable(this);
}
};
class MyVideoFilterRunnable : public QVideoFilterRunnable
{
public:
QVideoFrame run(QVideoFrame* input, const QVideoSurfaceFormat& surfaceFormat, RunFlags flags)
{
if (!input->isValid())
{
return *input;
}
// do stuff with input
return *input;
}
};
extern QImage qt_imageFromVideoFrame(const QVideoFrame& f);
#ifdef Q_OS_ANDROID
bool flip = true;
#else
bool flip = surfaceFormat.scanLineDirection() == QVideoSurfaceFormat::BottomToTop;
#endif