Nic*_*ick 14 qt camera android qml
我有一个基于Qt5.4的程序和一些图像处理.我使用QCameramy videoSurface(派生自QAbstractVideoSurface)来获取VideoFrames.它在Windows上运行良好.
但现在我需要我的应用程序的Android版本.我发现QCamera在Android上不起作用.但我看到QML Camera示例在Android上运行没有任何问题.
所以我决定用QML重写我的应用程序.主要问题:我无法在C++中访问QML Camera表面.
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();
}
Run Code Online (Sandbox Code Playgroud)
此代码提供对属性的访问.但我无法以这种方式访问videoSurface(使用QCamera我可以做到).我想知道QML Camera是如何工作的?它是基于QCamera?我看QCamera *m_camera在QDeclarativeCamera...
所以我有两个问题:
小智 9
1)是的,这是可能的.我有两种方法可以做到这一点.
使用QAbstractVideoFilter和QVideoFilterRunnable类(仅限QT 5.5),这些都非常棒.它们是专门针对这种情况开发的,并且非常易于使用.
网上有一些很好的例子:
https://blog.qt.io/blog/2015/03/20/introducing-video-filters-in-qt-multimedia/
http://code.qt.io/cgit/qt/qtmultimedia.git/tree/examples/multimedia/video/qmlvideofilter_opencl
这种方法的缺点是,就像这里所说的那样,在Android设备上,QVideoFrame指针不具有原始像素数据,相反,它具有需要回读的OpenGL纹理(我发布的第二个示例有解决此问题的解决方法) ),因此使这种方法不是真正的实时目的恕我直言.
我最终用来解决这个问题的是QVideoProbe类.
首先,您必须命名QML相机的实例:
Camera {
id: camera
objectName: "qrCameraQML"
}
Run Code Online (Sandbox Code Playgroud)
然后你从C++端获得这个实例,例如:
QObject *qmlCamera = engine.rootObjects().at(0).findChild<QObject*>("qrCameraQML");
Run Code Online (Sandbox Code Playgroud)
QML相机实例实际上有一个QVariant元素,只能通过C++访问,可以转换为QCamera*:
camera_ = qvariant_cast<QCamera*>(qmlCamera->property("mediaObject"));
Run Code Online (Sandbox Code Playgroud)
然后你要做的就是将探针连接到一个实际处理QVideoFrames的插槽,然后将探针源设置为QCamera*previouslly cast:
connect(&probe_,SIGNAL(videoFrameProbed(QVideoFrame)),this,SLOT(handleFrame(QVideoFrame)));
probe_.setSource(camera_);
Run Code Online (Sandbox Code Playgroud)
在我的示例中,camera_和probe_只是:
QCamera *camera_;
QVideoProbe probe_;
Run Code Online (Sandbox Code Playgroud)
根据我的经验,这种方法比使用qt视频过滤器类要快得多(对于Android平台),但它的缺点是你基本上只读取qml的视频输出,而AFAIK你不能将后处理的视频帧发送回QML.
如果你真的需要将处理过的图像发送回qml,我建议你尝试第一种方法,看看会发生什么.
2)不使用Qt AFAIK,可能使用OpenCv或其他lib.
我想强调@ waldez-junior的第一个答案.在QML中,您将QAbstractVideoFilter组件添加到VideoOutput.
Camera {
id: camera
}
VideoOutput {
id: videoOutput
source: camera
filters: [ videoFilter ]
autoOrientation: true
}
MyVideoFilter {
id: videoFilter
// orientation: videoOutput.orientation
}
Run Code Online (Sandbox Code Playgroud)
在C++中,您实现了QAbstractVideoFilter组件,这是一个最小的例子:
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;
}
};
Run Code Online (Sandbox Code Playgroud)
```
Qt源代码中有一个QAbstractVideoFilter示例:http://code.qt.io/cgit/qt/qtmultimedia.git/tree/examples/multimedia/video/qmlvideofilter_opencl.
为了简化操作,请考虑使用Qt内部函数qt_imageFromVideoFrame将a转换QVideoFrame为a QImage.此代码适用于NoHandle大小写并适用于大多数平台.不幸的是,它不适用于很多Android设备因为QVideoFrame::map()会返回false.
extern QImage qt_imageFromVideoFrame(const QVideoFrame& f);
Run Code Online (Sandbox Code Playgroud)
对于Android,您需要处理GLTextureHandle使用OpenGL填充a的情况QImage.
在某些设备上,图像内部位缓冲区将出现翻转.
#ifdef Q_OS_ANDROID
bool flip = true;
#else
bool flip = surfaceFormat.scanLineDirection() == QVideoSurfaceFormat::BottomToTop;
#endif
Run Code Online (Sandbox Code Playgroud)
在某些设备上,图像也可以旋转.处理旋转的最佳方法是autoOrientation: true在VideoOutput组件中设置.然后,您的组件可以只复制一份videoOutput.orientation.
知道如何翻转和旋转图像将有助于视频识别应用(例如,面部识别).
我还在https://github.com/stephenquan/MyVideoFilterApp上创建了一个最小工作样本
| 归档时间: |
|
| 查看次数: |
7200 次 |
| 最近记录: |