【问题标题】:How use Camera in Android and Desktop with Qt如何通过 Qt 在 Android 和桌面中使用相机
【发布时间】:2016-01-21 13:12:25
【问题描述】:

我想在使用 QWidgets/C++、桌面和 Android 的 Qt 机器人项目上显示和获取相机的框架。 相机在只有 QML 的程序中工作,但我的实际项目需要在 C++ 中使用 QWidgets。

我尝试了各种方法:

  1. 带有用于显示 QML 相机的容器的 QQuickView 无法在 Android 中运行
  2. 我试过这个:Qt QML Camera to C++ QImage on Android 但我没有得到框架。
  3. 我也看到了这个:http://www.programering.com/a/MTN3IjMwATQ.html/ http://blog.csdn.net/kl222/article/details/23187693 但它不适用于 Android

【问题讨论】:

  • 它在 Android 上不起作用(相机无法启动和崩溃)
  • 我很害怕,但这对于小部件来说是不可能的,请参阅QTBUG-35243。剩下的问题有点模糊,无法回答。
  • 更具体地说:如何从 Android 上的相机获取帧?根据我发布的链接,这似乎是可能的。 QCamera 和 Android 不工作,但也许我可以从 QML 获取帧并导入“C++”,转换并处理为 QImage 以显示在 QWidget
  • 正如@BaCaRoZzo 所说,使用小部件无法做到这一点。我会尝试类似于你所说的 - 将简单的 QML 场景嵌入到你的小部件项目中。

标签: android c++ qt camera 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)。

如果有人有更好的想法,请分享。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-09
    • 1970-01-01
    • 2016-09-17
    • 1970-01-01
    相关资源
    最近更新 更多