如何使用Qt在Android和桌面中使用相机

Mir*_*age 2 c++ qt camera android qml

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

我尝试了各种方式:

  1. 带容器的QQuickView显示QML Camera不能用于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

Mir*_*age 5

我找到了问题的答案(目标是从相机获取帧并在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 ]
    }
}
Run Code Online (Sandbox Code Playgroud)

QAbstractVideoFilter子类:

class MyFilter : public QAbstractVideoFilter
{
    Q_OBJECT
public:
    MyFilter();

    QVideoFilterRunnable *createFilterRunnable();

signals:
    void finished(const QVariant& result); //send QImage got to QML

public slots:
};
Run Code Online (Sandbox Code Playgroud)

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;
};
Run Code Online (Sandbox Code Playgroud)

处理框架(将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
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在C++上,MainWindow:

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 &)));
Run Code Online (Sandbox Code Playgroud)

和显示槽:

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();
}
Run Code Online (Sandbox Code Playgroud)

总结一下:QML相机"发送"帧到c ++过滤器.过滤将帧转换为QImage并将这些QImage作为QVariant发送到QML.从C++显示类,使用connect获取QVariant并转换为QImage以在QWidget上显示.

这当然不是最好的方式(Android转换框架到QImage太慢了,可能用QML和C++进行大量扩展)但它足以满足我的项目(我得到~15 fps).

如果有人有更好的想法来改进这个过程,请说出来!