2016-07-05 82 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代碼和處理代碼之間的更好的耦合。這是以犧牲(稍微)更高的實施努力爲代價的。

相關問題