2011-12-12 10 views
8

Me gustaría pedirle que me ayude a obtener todos los cuadros de archivo de video utilizando Emgu CV. Sé que puedo usar la clase Capture y su método QueryFrame(), pero esto solo devuelve un marco. ¿Cuál es la forma más fácil de obtener todos los marcos? (y guárdelo, por ejemplo, en Image<Bgr, Byte>[]) Necesito todos los marcos para hacer un poco más de procesamiento (para ser más específicos: extracción de cuadros clave para resúmenes de videos).Emgu CV obtener todos los marcos del archivo de video

Muchas gracias por su ayuda.

Respuesta

13

Véase mi respuesta aquí por referencia Emgu Capture plays video super fast

pero esto debe hacer lo que le pide que he usado una lista para almacenar las imágenes que se pueden utilizar una gran variedad pero se necesita saber el tamaño de su archivo AVI es.

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

Este fue diseñado para permitir la reproducción del archivo de vídeo a una velocidad responsable sino simplemente como su conversión se puede utilizar el método Application.Idle tan fácilmente como esto ...

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 
    } 

} 

Usted Tendrás que tener cuidado de que al final del error de archivo recibas un error. Siempre puedes usar una declaración try catch para detectar el error específico que dará en lugar de simplemente terminar la conversión.

Si usa una matriz de imágenes tendrá que recorrer el archivo incrementando una variable y contando los cuadros y luego crear la matriz de imágenes antes de convertir el archivo de video a una matriz.


[EDIT]

Como solicitó esta es una versión método de recuperación de todos los fotogramas de un archivo de vídeo no he probado esto en un archivo de vídeo de gran tamaño como espero que el programa se estrellaría desde requerirá mucha memoria.

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

alternativa que se dan cuenta de que puede anotar por ejemplo, 10 segundos de vídeo desde una cámara web por lo que este método va a hacer eso, he usado un cronómetro como el bucle al mismo tiempo que prohíbe el uso de un contador de tiempo a menos que su multi-threading la aplicación

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

y esto se llamaría así:

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

esperanza esto ayuda,

Cheers,

Chris

+0

Gracias, simplemente no quiero usarlo en 'Application.Idle'. Simplemente quiero tener una función a la que pueda llamar siempre que lo desee y me devuelve una lista de fotogramas de Image a partir de una entrada de video determinada. – tom

+0

Hola, he agregado el código en un método que podrías llamar, espero que esto sea lo que buscas si no me dejas saber Cheers – Chris

+0

@Chris me puedes ayudar http://stackoverflow.com/questions/31259051/detect -hand-from-web-camera-emgu-cv – gihansalith

0

Incluso se enfrentó al mismo issue.So i inicializado otro temporizador y siempre que el vídeo guardar el código en there.and este temporizador se activa sólo cuando el botón de grabación [ Se hace clic en el botón del formulario que hace clic en grabar el video]. Ahora puedo capturar video pero el audio no se graba.

Cuestiones relacionadas