2011-12-12 9 views
8

Chciałbym poprosić o pomoc w uzyskaniu wszystkich klatek z pliku wideo za pomocą Emgu CV. Wiem, że mogę używać klasy Capture i jej metody QueryFrame(), ale to zwraca tylko jedną klatkę. Jaki jest najprostszy sposób na uzyskanie wszystkich ramek? (i zapisz go na przykład do Image<Bgr, Byte>[]) Potrzebuję wszystkich ramek, aby wykonać trochę więcej przetwarzania (aby być bardziej szczegółowym: wyodrębnianie ramki klucza do podsumowania wideo).Emgu CV uzyskać wszystkie ramki z pliku wideo

Bardzo dziękuję za pomoc.

Odpowiedz

13

Zobacz moją odpowiedź tutaj odniesienie Emgu Capture plays video super fast

Ale to czynili, jak pytasz Użyłem listę do przechowywania obrazów można wykorzystać tablicę ale trzeba wiedzieć, jak duży plik avi jest.

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

ten został zaprojektowany, aby umożliwić odtwarzanie pliku wideo w sposób odpowiedzialny za swoje stopy, ale po prostu konwersji można użyć metody Application.Idle równie łatwo, jak to ...

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 
    } 

} 

You będzie musiał uważać na koniec błędu pliku, pojawi się błąd. Zawsze możesz użyć instrukcji catch catch, aby uchwycić konkretny błąd, który da, zamiast po prostu przerwać konwersję.

Jeśli używasz macierzy obrazów, będziesz musiał przechodzić przez plik zwiększając liczbę zmiennych i licząc klatki, a następnie utworzyć tablicę obrazów przed konwersją pliku wideo do tablicy.


[EDIT]

Zgodnie z wnioskiem jest to wersja metody pobierania wszystkie klatki z pliku wideo nie testowałem to na duży plik wideo jako Spodziewam się, że program będzie katastrofy, ponieważ będzie wymagało dużo pamięci.

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

Alternatywnie Zdaję sobie sprawę, może chcesz rekordu powiedzmy 10 sekund wideo z kamery internetowej, więc ta metoda będzie zrobić, użyłem Stoper jako pętli while zabrania używania czasomierz chyba, że ​​wielu nawlekania aplikacja

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

a to nazwać tak:

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

Nadzieja to pomaga,

Cheers,

Chris

+0

Dzięki, po prostu nie chcę go używać w 'Application.Idle'. Po prostu chcę mieć funkcję, którą mogę wywołać, kiedy tylko zechcę, i zwraca mi listę klatek Image z danego wejścia wideo. – tom

+0

Witam Dodałem do kodu w metodzie, że mógłbyś zadzwonić, mam nadzieję, że to jest to, co twoi po, jeśli nie dajcie mi znać Wiwaty – Chris

+0

@Chris możecie pomóc mi http://stackoverflow.com/questions/31259051/detect -hand-from-web-camera-emgu-cv – gihansalith

0

nawet ja w obliczu tego samego issue.So i zainicjowane inny timer i pod warunkiem, że wideo zapisać kod w there.And ten zegar jest aktywna tylko wtedy, gdy przycisk nagrywania [ Przycisk na formularzu, który po kliknięciu nagrywa wideo] jest kliknięty. Teraz mogę przechwycić wideo, ale dźwięk nie jest nagrywany.

Powiązane problemy