2011-12-12 14 views
8

Emgu CVを使用してビデオファイルからすべてのフレームを取得するのを手伝ってください。 CaptureクラスとそのQueryFrame()メソッドを使用できますが、これは1つのフレームだけを返します。すべてのフレームを取得する最も簡単な方法は何ですか? (そして、例えばImage<Bgr, Byte>[]に保存してください)もっと具体的には、ビデオの要約のためのキーフレーム抽出という処理を行うために、すべてのフレームが必要です。Emgu CVビデオファイルからすべてのフレームを取得

ありがとうございました。

答えて

13

は参照Emgu Capture plays video super fast

ため、ここで私の答えを参照してくださいしかし、あなたは私はあなたが、配列を使用することができますが、あなたはあなたのAVIファイルがどのように大きな知っている必要があります画像を保存するために、リストを使用しました尋ねると、これは行う必要があります。

Timer My_Time = new Timer(); 
int FPS = 30; 
List<Image<Bgr,Byte>> image_array = new List<Image<Bgr,Byte>>(); 
Capture _capture;  

public Form1() 
{ 
    InitializeComponent(); 

    //Frame Rate 
    My_Timer.Interval = 1000/FPS; 
    My_Timer.Tick += new EventHandler(My_Timer_Tick); 
    My_Timer.Start() 
    _capture = new Capture("test.avi"); 
} 

private void My_Timer_Tick(object sender, EventArgs e) 
{ 
    Image<Bgr, Byte> frame = _capture.QueryFrame(); 
    if (frame != null) 
    { 
     imageBox.Image = _capture.QueryFrame(); 
     image_array.Add(_capture.QueryFrame().Copy()); 
    } 
    else 
    { 
     My_Timer.Stop(); 
    { 
} 

これは、あなたが

List<Image<Bgr,Byte>> image_array = new List<Image<Bgr,Byte>>(); 
Capture _capture; 

public Form1() 
{ 
    InitializeComponent(); 

    //Frame Rate 
    _capture = new Capture("test.avi"); 
    Application.Idle += ProcessFrame; 
} 

private void ProcessFrame(object sender, EventArgs arg) 
{ 
    Image<Bgr, Byte> frame = _capture.QueryFrame(); 
    if (frame != null) 
    { 
     image_array.Add(frame.Copy()); 
    } 
    else 
    { 
     Application.Idle -= ProcessFrame;// treat as end of file 
    } 

} 

...責任のレートではなく、あなたは、単にあなたが同じように簡単にこのようなApplication.Idleメソッドを使用することができます変換などのビデオファイルの再生を許可するように設計されましたあなたはエラーを受け取るファイルエラーの終わりに注意する必要があります。 try catchステートメントを使用して、単に変換を終了するのではなく、特定のエラーをキャッチすることができます。

イメージ配列を使用する場合は、ファイルをループして変数をインクリメントし、フレーム数をカウントして、ビデオファイルを配列に変換する前にイメージ配列を作成する必要があります。


[EDIT]

これは私がプログラムがあるためクラッシュすることを期待して、私は大規模なビデオファイルでこれをテストしていないビデオファイルからすべてのフレームを取得する方法バージョンで要求されるようにそれは多くのメモリを必要とします。

private List<Image<Bgr, Byte>> GetVideoFrames(String Filename) 
    { 
     List<Image<Bgr,Byte>> image_array = new List<Image<Bgr,Byte>>(); 
     Capture _capture = new Capture(Filename); 

     bool Reading = true; 

     while (Reading) 
     { 
      Image<Bgr, Byte> frame = _capture.QueryFrame(); 
      if (frame != null) 
      { 
       image_array.Add(frame.Copy()); 
      } 
      else 
      { 
       Reading = false; 
      } 
     } 

     return image_array; 
    } 

は、代わりに私は、このメソッドはそれを行いますので、私はwhileループのようにストップウォッチを使用し、あなたがマルチスレッド化しない限り、タイマーの使用を禁止しているウェブカメラから録音したい場合も、ビデオの10秒と言う実感しますアプリケーション

private List<Image<Bgr, Byte>> GetVideoFrames(int Time_millisecounds) 
    { 
     List<Image<Bgr,Byte>> image_array = new List<Image<Bgr,Byte>>(); 
     System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch(); 

     bool Reading = true; 
     Capture _capture = new Capture(); 
     SW.Start(); 

     while (Reading) 
     { 
      Image<Bgr, Byte> frame = _capture.QueryFrame(); 
      if (frame != null) 
      { 
       image_array.Add(frame.Copy()); 
       if (SW.ElapsedMilliseconds >= Time_millisecounds) Reading = false; 
      } 
      else 
      { 
       Reading = false; 
      } 
     } 

     return image_array; 
    } 

、これはこのように呼ばれることになります。

List<Image<Bgr, Byte>> Image_Array = GetVideoFrames(10000); //10 Secounds 

・ホープこれは、

乾杯を助け、

クリス

+0

ありがとう、私はちょうど 'Application.Idle'でそれを使いたくありません。私は、私が望むときにいつでも呼び出すことができる機能を持たせたいだけであり、与えられたビデオ入力からImage フレームのリストを返すだけです。 – tom

+0

こんにちは私はあなたが呼び出すことができるメソッドでコードに追加しました、私はこれがあなたの後に何かを願っていない場合はうれしい – Chris

+0

@Chrisあなたはあなたを助けることができます http://stackoverflow.com/questions/31259051/detect -hand-from-web-camera-emgu-cv – gihansalith

0

がさえ、私は同じissue.Soに直面し、私は別のタイマーを初期化し、このタイマーが有効になっているビデオがthere.Andにコードを保存し提供する場合にのみ録音ボタン[フォームをクリックしてビデオを録画する]ボタンをクリックします。ビデオをキャプチャできますが、オーディオは録画されません。

関連する問題