2016-07-05 80 views
0

基于此thread,有没有办法在QML中处理来自相机的图像而不保存它?在不保存的情况下捕获图像

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

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

+0

这真的取决于你想要的。如果您只想处理帧(例如搜索标记/ Qr代码),则可以将[mediaObject](http://doc.qt.io/qt-5/qml-qtmultimedia-camera.html#mediaObject-prop )就是这样。如果你想做实时过滤和覆盖,那么需要做更多的工作。有关第二种场景的更多详细信息,请参阅[本答案](http://stackoverflow.com/a/33238150/2538363)开头处的链接。 – BaCaRoZzo

+0

我想实现的是扫描QR码。由于我不能使用grabWindow(),因为[this](https://bugreports.qt.io/browse/QTBUG-53083),我想每秒捕获一次摄像头输出并处理图像。 – ABCplus

+0

因此,根据您使用mediaObject的建议,一旦我获得对QCamera对象的引用,那么我需要做什么? – ABCplus

回答

0

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设备使用的不QImage目前支持的,哪些应该由手工转换YUV format。我在这里做出了强有力的假设,即所有无效的格式都是YUV。通过当前操作系统的ifdef的条件可以更好地管理。
  2. 解码可能非常昂贵,因此您可以跳过帧(只需向此方法添加计数器)或将工作卸载到专用线程。这也取决于框架制定的速度。同样减小它们的尺寸,例如只取一部分QImage可以大大提高表演。

对于这个问题我会避免在所有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代码和处理代码之间的更好的耦合。这是以牺牲(稍微)更高的实施努力为代价的。

相关问题