如何通过 Qt 在 Android 和桌面中使用相机
Posted
技术标签:
【中文标题】如何通过 Qt 在 Android 和桌面中使用相机【英文标题】:How use Camera in Android and Desktop with Qt 【发布时间】:2016-01-21 13:12:25 【问题描述】:我想在使用 QWidgets/C++、桌面和 android 的 Qt 机器人项目上显示和获取相机的框架。 相机在只有 QML 的程序中工作,但我的实际项目需要在 C++ 中使用 QWidgets。
我尝试了各种方法:
-
带有用于显示 QML 相机的容器的 QQuickView 无法在 Android 中运行
我试过这个:Qt QML Camera to C++ QImage on Android
但我没有得到框架。
我也看到了这个:http://www.programering.com/a/MTN3IjMwATQ.html/
http://blog.csdn.net/kl222/article/details/23187693
但它不适用于 Android
【问题讨论】:
Qt 小部件相机示例:doc.qt.io/qt-5/qtmultimediawidgets-camera-example.html 它在 Android 上不起作用(相机无法启动和崩溃) 我很害怕,但这对于小部件来说是不可能的,请参阅QTBUG-35243。剩下的问题有点模糊,无法回答。 更具体地说:如何从 Android 上的相机获取帧?根据我发布的链接,这似乎是可能的。 QCamera 和 Android 不工作,但也许我可以从 QML 获取帧并导入“C++”,转换并处理为 QImage 以显示在 QWidget 正如@BaCaRoZzo 所说,使用小部件无法做到这一点。我会尝试类似于你所说的 - 将简单的 QML 场景嵌入到你的小部件项目中。 【参考方案1】:我找到了问题的答案(目标是从相机获取帧并在 Android 和 Windows 上的 QWidget 上显示)
首先在 QML 中:获取相机和滤镜:
Item
signal submitFrame(var img)//used to send QImage to C++ after filter process
Camera
id: camera
MyFilter
id: filter
onFinished: submitFrame(result)
VideoOutput
source: camera
filters: [ filter ]
QAbstractVideoFilter 子类:
class MyFilter : public QAbstractVideoFilter
Q_OBJECT
public:
MyFilter();
QVideoFilterRunnable *createFilterRunnable();
signals:
void finished(const QVariant& result); //send QImage got to QML
public slots:
;
QVideoFilterRunnable 子类:
class MyFilterRunnable : public QVideoFilterRunnable
public:
MyFilterRunnable(MyFilter *filter);
~MyFilterRunnable();
QVideoFrame run(QVideoFrame *input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags) Q_DECL_OVERRIDE;
private:
MyFilter *m_filter;
;
处理帧(将QVideoframe转换为QImage)
QVideoFrame run(QVideoFrame *input, const QVideoSurfaceFormat &surfaceFormat, RunFlags flags) Q_DECL_OVERRIDE;
//On Android
if(frame->handleType() == QAbstractVideoBuffer::GLTextureHandle)
/* ...
Need treatment with OpenGL or other to "convert" frame to QImage.
see here : http://code.qt.io/cgit/qt/qtmultimedia.git/tree/examples/multimedia/video/qmlvideofilter_opencl in file rgbframehelper.h
... */
emit m_filter->finished(QVariant (imgToDisplay));// send QImage got to QML
//On Windows
else
//easy convert VideoFrame to QImage
QImage::Format format = VideoFrame::imageFormatFromPixelFormat(frame->pixelFormat());
if (fmt != QImage::Format_Invalid)
QImage img=QImage(frame->bits(), frame->width(), frame->height(), format);
QImage imgToDisplay = img.convertToFormat(QImage::Format_RGB888);
emit m_filter->finished(QVariant(imgToDisplay));// send QImage got to QML
现在在 C++,主窗口:
qmlRegisterType<MyFilter>("my.uri", 1, 0, "MyFilter");
//load QML
QQuickView *view=new QQuickView();
view->setSource(QUrl("qrc:///main.qml"));
view->show();
//connect to get QImage as QVariant from QML to this C++ class
QObject *topLevel =view->rootObject();
QObject::connect(topLevel, SIGNAL(submitFrame(const QVariant &)),this, SLOT(handleFrame(const QVariant &)));
和显示槽:
void MainWindow::handleFrame(const QVariant &in)
//cast Qvariant =>QImage
QImage image = in.value<QImage>();
// QImage to QPixmap for display
ui->label->setPixmap(QPixmap::fromImage(image));
ui->label->resize(image.size());
ui->label->update();
总结:QML 相机“发送”帧到 c++ 过滤器。过滤器将帧转换为 QImage 并将这些 QImage 作为 QVariant 发送到 QML。从 C++ 显示类中,通过 connect 获取 QVariant 并转换为 QImage 以在 QWidget 上显示。
这当然不是最好的方法(Android 将帧转换为 QImage 太慢了,并且可能与 QML 和 C++ 有很大的关系)但它对我的项目来说已经足够了(我得到 ~15 fps)。
如果有人有更好的想法,请分享。
【讨论】:
以上是关于如何通过 Qt 在 Android 和桌面中使用相机的主要内容,如果未能解决你的问题,请参考以下文章
如何在 android 中使用 MySql 服务器(在桌面上下载)?
Qt Android,如何访问 QRunnable 中的外部对象?
如何在 Android 上部署 Qt imageformats 插件