2017-06-12 55 views
1

このシーンは、リアルタイムのビデオ処理で一般的です。そして、私は他のデバイスと同期するためにタイムスタンプが必要です。USBカメラで取得した各フレームからタイムスタンプを抽出する方法は?

私はcv::VideoCaptureを試しましたが、ビデオストリームからタイムスタンプを抽出できません。

  1. は、USBカメラによって提供されるビデオストリームが実際にタイムスタンプ情報が含まれています:

    は、だから私はここに2つの質問がありますか?

  2. あります。それを抽出するにはどうすればよいですか? C++の解決策は最高ですが、C++はOKです。

追加:これら二つの特性は動作しません使用

secCounter = (long) cap.get(CAP_PROP_POS_MSEC); 
frameNumber = (long) cap.get(CAP_PROP_POS_FRAMES); 

それは、常に次のような結果が得られます。

VIDEOIO ERROR: V4L2: getting property #1 is not supported

msecCounter = 0

frameNumber = -1

+0

ストリームはどのような形式ですか?または少なくともどのモデル/ブランドのUSBカメラ? –

+0

@ VC.One実際に私はusbカメラの特定のパラメータについてはっきりしていません。私はすべてのUSBカメラが同じだと思う。それらは、ビデオデバイス(UVC)プロトコルのためのユニバーサルシリアルバスデバイスクラス定義に従うべきである。私はUVCプロトコルをチェックしたところ、すべてのフレームにタイムスタンプが含まれていることがわかりました。だから多分USBカメラのすべての種類の普遍的なソリューションがありますか? – jinge

+0

現在、どのようにカメラからフレームを取得していますか? – ozeanix

答えて

1

のOpenCVのVideoCaptureクラスが非常にありますカメラからフレームを取り出すための高水準のインターフェースです。したがって、たくさん「隠す」カメラに接続し、カメラからフレームを取り出し、それらのフレームをBGRのような有用な色空間にデコードするために必要な細部の詳細を表示します。フレームをつかむ詳細については心配する必要がないので、これはいいですが、フレーム番号やフレームのタイムスタンプなど、他のデータに直接アクセスできないという欠点があります。しかし、それはあなたが望むデータを得ることは不可能ではありません!

ここでは、フレームを取得するループの例を示します。これは、ゆるやかにexample code from hereに基づいています。これはC++です。

#include "opencv2/opencv.hpp" 
using namespace cv; 
int main(int, char**) 
{ 
    VideoCapture cap(0); // open the default camera 
    if(!cap.isOpened()) // check if we succeeded 
     return -1; 

    // TODO: change the width, height, and capture FPS to your desired 
    // settings. 
    cap.set(CAP_PROP_FRAME_WIDTH, 1920); 
    cap.set(CAP_PROP_FRAME_HEIGHT, 1080); 
    cap.set(CAP_PROP_FPS, 30); 

    Mat frame; 
    long msecCounter = 0; 
    long frameNumber = 0; 

    for(;;) 
    {    
     // Instead of cap >> frame; we'll do something different. 
     // 
     // VideoCapture::grab() tells OpenCV to grab a frame from 
     // the camera, but to not worry about all the color conversion 
     // and processing to convert that frame into BGR. 
     // 
     // This means there's less processing overhead, so the time 
     // stamp will be more accurate because we are fetching it 
     // immediately after. 
     // 
     // grab() should also wait for the next frame to be available 
     // based on the capture FPS that is set, so it's okay to loop 
     // continuously over it. 

     if(cap.grab()) 
     { 
      msecCounter = (long) cap.get(CAP_PROP_POS_MSEC); 
      frameNumber = (long) cap.get(CAP_PROP_POS_FRAMES); 

      // VideoCapture::retrieve color converts the image and places 
      // it in the Mat that you provide. 
      if(cap.retrieve(&frame)) 
      { 
       // Pass the frame and parameters to your processing 
       // method. 
       ProcessFrame(&frame, msecCounter, frameNumber); 
      } 
     } 

     // TODO: Handle your loop termination condition here 
    } 
    // the camera will be deinitialized automatically in VideoCapture destructor 
    return 0; 
} 

void ProcessFrame(Mat& frame, long msecCounter, long frameNumber) 
{ 
    // TODO: Make a copy of frame if you are going to process it 
    // asynchronously or put it in a buffer or queue and then return 
    // control from this function. This is because the reference Mat 
    // being passed in is "owned" by the processing loop, and on each 
    // iteration it will be destructed, so any references to it will be 
    // invalid. Hence, if you do any work async, you need to copy frame. 
    // 
    // If all your processing happens synchronously in this function, 
    // you don't need to make a copy first because the loop is waiting 
    // for this function to return. 

    // TODO: Your processing logic goes here. 
} 

あなたがC#とEmgu CVを使用している場合、それは少し違って見えます。私はこのコードをテストしていませんが、うまくいくはずです。取り込んだフレームがRetrieveで使用する準備ができているとき

using System; 
using Emgu.CV; 
using Emgu.CV.CvEnum; 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     VideoCapture cap = new VideoCapture(0); 
     if(!cap.IsOpened) 
     { 
      return; 
     } 

     cap.SetCaptureProperty(CapProp.FrameWidth, 1920); 
     cap.SetCaptureProperty(CapProp.FrameHeight, 1080); 
     cap.SetCaptureProperty(CapProp.Fps, 30); 

     Mat frame = new Mat();    
     long msecCounter = 0; 
     long frameNumber = 0; 

     for(;;) 
     { 
      if(cap.Grab()) 
      { 
       msecCounter = (long) cap.GetCaptureProperty(CapProp.PosMsec); 
       frameNumber = (long) cap.GetCaptureProperty(CapProp.PosFrames); 

       if(cap.Retrieve(frame)) 
       { 
        ProcessFrame(frame, msecCounter, frameNumber); 
       } 
      } 

      // TODO: Determine when to quit the processing loop 
     } 
    } 

    private static void ProcessFrame(Mat frame, long msecCounter, long frameNumber) 
    { 
     // Again, copy frame here if you're going to queue the frame or 
     // do any async processing on it. 

     // TODO: Your processing code goes here. 
    } 
} 

EmguのVideoCapture実装は、非同期Grabあなたのために行うべき操作、および通知することができます。これは次のようになります。

using System; 
using Emgu.CV; 
using Emgu.CV.CvEnum; 
static class Program 
{ 
    private static Mat s_frame; 
    private static VideoCapture s_cap; 
    private static object s_retrieveLock = new object(); 

    [STAThread] 
    static void Main() 
    { 
     s_cap = new VideoCapture(0); 
     if(!s_cap.IsOpened) 
     { 
      return; 
     } 

     s_frame = new Mat(); 

     s_cap.SetCaptureProperty(CapProp.FrameWidth, 1920); 
     s_cap.SetCaptureProperty(CapProp.FrameHeight, 1080); 
     s_cap.SetCaptureProperty(CapProp.Fps, 30); 

     s_cap.ImageGrabbed += FrameIsReady; 

     s_cap.Start(); 

     // TODO: Wait here until you're done with the capture process, 
     // the same way you'd determine when to exit the for loop in the 
     // above example. 

     s_cap.Stop(); 
     s_cap.ImageGrabbed -= FrameIsReady; 
    } 

    private static void FrameIsReady(object sender, EventArgs e) 
    { 
     // This function is being called from VideoCapture's thread, 
     // so if you rework this code to run with a UI, be very careful 
     // about updating Controls here because that needs to be Invoke'd 
     // back to the UI thread. 

     // I used a lock here to be extra careful and protect against 
     // re-entrancy, but this may not be necessary if Emgu's 
     // VideoCapture thread blocks for completion of this event 
     // handler. 
     lock(s_retrieveLock) 
     { 
      msecCounter = (long) s_cap.GetCaptureProperty(CapProp.PosMsec); 
      frameNumber = (long) s_cap.GetCaptureProperty(CapProp.PosFrames); 

      if(s_cap.Retrieve(s_frame)) 
      { 
       ProcessFrame(s_frame, msecCounter, frameNumber); 
      } 
     } 
    } 

    private static void ProcessFrame(Mat frame, long msecCounter, long frameNumber) 
    { 
     // Again, copy frame here if you're going to queue the frame or 
     // do any async processing on it. 

     // TODO: Your processing code goes here. 
    } 
} 
+0

ありがとうございますが、それでも動作しません。私は問題の説明に結果を加えました。見てください。 – jinge

関連する問題