如何通过 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:如何编写 Windows 桌面实用程序?

Qt Android,如何访问 QRunnable 中的外部对象?

如何在 Android 上部署 Qt imageformats 插件

如何在 C# 桌面应用程序和移动(android)设备之间通过本地网络进行通信? [关闭]

如何将 QT 5.2.0 (win7 x86) 与 OpenCV2.4.6 和 Android 集成