捕获图像而不保存

时间:2016-07-05 12:37:57

标签: android c++ qml

根据这个thread,有没有办法在不保存的情况下用QML处理相机中的图像?

doc capture()函数的示例开始,将图像保存到图片位置。 我想要实现的是使用onImageCaptured每秒处理相机图像,但我不想将其保存到驱动器。

我尝试使用onImageSaved信号实现清理操作,但它也会影响onImageCaptured。

1 个答案:

答案 0 :(得分:1)

this answer中所述,您可以通过mediaObject桥接C ++和QML。这可以通过objectName完成(如在链接的答案中)或使用专用的Q_PROPERTY(稍后会详细介绍)。无论哪种情况,你都应该得到这样的代码:

QObject * source  // QML camera pointer obtained as described above
QObject * cameraRef = qvariant_cast<QMediaObject*>(source->property("mediaObject"));  

一旦你拿到相机的钩子,就把它用作QVideoProbe物体的来源,即

QVideoProbe *probe = new QVideoProbe;
probe->setSource(cameraRef);

videoFrameProbed信号连接到适当的插槽,即

connect(probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));

就是这样:您现在可以在processFrame函数内处理您的帧。这样一个函数的实现如下所示:

void YourClass::processFrame(QVideoFrame frame)
{
    QVideoFrame cFrame(frame);
    cFrame.map(QAbstractVideoBuffer::ReadOnly);
    int w {cFrame.width()};
    int h {cFrame.height()};
    QImage::Format f;
    if((f = QVideoFrame::imageFormatFromPixelFormat(cFrame.pixelFormat())) == QImage::Format_Invalid)
    {
        QImage image(cFrame.size(), QImage::Format_ARGB32);
        // NV21toARGB32 convertion!!
        //
        // DECODING HAPPENS HERE on "image"
    }
    else
    {
        QImage image(cFrame.bits(), w, h, f);
        //
        // DECODING HAPPENS HERE on "image"
    }
    cFrame.unmap();
}

这里有两个重要的实施细节:

  1. Android设备使用的YUV format目前QImage不支持,应该手动转换。我在这里强烈假设所有无效格式都是YUV。通过当前操作系统上的ifdef条件,可以更好地管理。
  2. 解码可以非常省时,因此您可以跳过帧(只需在此方法中添加计数器)或将工作卸载到专用线程。这也取决于框架的制定速度。还减小它们的尺寸,例如只占QImage的一部分可以大大提高表现。
  3. 就此而言,我会完全避免objectName获取mediaObject的方法,而是register a new type,以便可以使用Q_PROPERTY方法。我正在考虑这个问题:

    class FrameAnalyzer 
    {
        Q_OBJECT
        Q_PROPERTY(QObject* source READ source WRITE setSource)
        QObject *m_source;  // added for the sake of READ function 
        QVideoProbe probe;
        // ...
    
    public slots:
        void processFrame(QVideoFrame frame);
    }
    

    setSource只是:

    bool FrameAnalyzer::setSource(QObject *source)
    {
        m_source = source; 
        return probe.setSource(qvariant_cast<QMediaObject*>(source->property("mediaObject")));
    }
    

    像往常一样注册,即

    qmlRegisterType<FrameAnalyzer>("FrameAnalyzer", 1, 0, "FrameAnalyzer");
    

    您可以直接在QML中设置source属性,如下所示:

    // other imports
    import FrameAnalyzer 1.0
    
    Item {
        Camera {
            id: camera
    
            // camera stuff here
    
            Component.onCompleted: analyzer.source = camera
        }
    
        FrameAnalyzer {
            id: analyzer
        }
    }
    

    这种方法的一大优点是可读性和Camera代码与处理代码之间更好的耦合。这是以(稍微)更高的实施工作为代价的。