2016-07-05 6 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 ) 以上です。リアルタイムのフィルタリングとオーバーレイを行いたい場合、より多くの作業が必要になります。 2番目のシナリオの詳細については、[この回答](http://stackoverflow.com/a/33238150/2538363)の冒頭にあるリンクを参照してください。 – BaCaRoZzo

+0

私が達成したいのは、QRコードをスキャンすることです。 [this](https://bugreports.qt.io/browse/QTBUG-53083)のためgrabWindow()を使用することができないので、毎秒カメラの出力をキャプチャして画像を処理したいと思います。 – 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")); 

videoFrameProbedを接続すなわち

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

QVideoProbeオブジェクトのためのソースとして使用します。どちらの場合も、あなたは、このようなコードで終わる必要があります適切なスロットへの信号、すなわち

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であるという強い前提を設定しました。それは現在のOS上でifdefの条件を介して管理する方が良いでしょう。
  2. フレームをスキップする(単純にこの方法にカウンタを追加する)か、専用のスレッドに作業をロードすることができるので、デコードにはかなりのコストがかかる可能性があります。それはフレームが精緻化されるペースにも依存します。また、そのサイズを縮小する。 QImageの一部のみを取ることで、パフォーマンスを大幅に向上させることができます。私はmediaObjectをフェッチするために、すべてのobjectNameアプローチで避けるだろうし、代わりに私がregister a new typeようQ_PROPERTYアプローチを使用することができますそのことについては

setSourceは単純です

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); 
} 

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

いつものように登録されると、すなわち、私はこの線に沿って何かを考えています

// other imports 
import FrameAnalyzer 1.0 

Item { 
    Camera { 
     id: camera 

     // camera stuff here 

     Component.onCompleted: analyzer.source = camera 
    } 

    FrameAnalyzer { 
     id: analyzer 
    } 
} 

このアプローチの大きな利点はreadibilityとCameraコード及び処理コードとの間のより良好なカップリングである:次のように直接QMLでsourceプロパティを設定することができ

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

それは(わずかに)より高い実装努力を犠牲にして来る。

関連する問題