2010-12-04 11 views
13

Tengo un video de 33 segundos que estoy tratando de procesar con OpenCV. Mi objetivo es determinar qué instancia en el tiempo (relativa al inicio del video) corresponde a cada cuadro. Hago esto para poder comparar fotogramas de videos de la misma escena que se han grabado a diferentes velocidades de fotogramas.OpenCV no informa la velocidad de cuadros/conteo precisa

Lo más trabajo:

  • El FPS se informa correctamente como 59.75. Esto es coherente con lo que informa ffprobe, por lo que estoy feliz de creer que es correcto.

Los problemas que tengo son:

  • CAP_PROP_POS_MSEC devuelve valores incorrectos. Al final del video, es hasta 557924ms (más de 9 min). Para un video de 33s, esto no puede ser correcto.
  • CAP_PROP_FRAME_COUNT también es incorrecto. Se informa como 33371, que a 59,75 fps daría más de 9 minutos de metraje. De acuerdo con el error anterior, pero sigue siendo incorrecto.
  • CAP_PROP_POS_FRAME es similarmente incorrecto.

El video se puede encontrar here (aproximadamente 10MB).

¿Alguna idea sobre qué podría estar mal?

ffprobe de salida:

FFprobe version SVN-r20090707, Copyright (c) 2007-2009 Stefano Sabatini 
    libavutil  49.15. 0/49.15. 0 
    libavcodec 52.20. 0/52.20. 1 
    libavformat 52.31. 0/52.31. 0 
    built on Jan 20 2010 00:13:01, gcc: 4.4.3 20100116 (prerelease) 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/misha/Dropbox/Public/sequence.mp4': 
    Duration: 00:00:33.37, start: 0.000000, bitrate: 2760 kb/s 
    Stream #0.0(und): Video: h264, yuv420p, 1920x1080, 59.75 tbr, 1k tbn, 2k tbc 
    Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16 

código completo:

#include <iostream> 
#include <assert.h> 

#include <cv.h>  
#include <highgui.h> 

#include <cmath> 
#include <iostream> 
#include <string.h> 
#include <stdio.h> 

extern "C" 
{ 
#include "options.h" 
} 

using namespace std; 

#define DEBUG 0 

static void 
print_usage(char *argv0) 
{ 
    cerr << "usage: " << argv0 << " video.avi [options]" << endl; 
} 

int main(int argc, char** argv) 
{ 
    if (argc < 2) 
    { 
     print_usage(argv[0]); 
     return -1; 
    } 

    int   step  = 30; 
    struct Option options[] = 
    { 
     { "step",  1, &step }, 
     { NULL,   0, NULL } 
    }; 

    int ret = parse_options(2, argc, argv, options); 
    if (ret == 0) 
    { 
     print_usage(argv[0]); 
     return -1; 
    } 

    CvCapture *capture = cvCaptureFromFile(argv[1]); 
    int counter = 0; 
    while (cvGrabFrame(capture)) 
    { 
     ++counter; 

     IplImage *frame = cvRetrieveFrame(capture); 
     double millis = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC); 
     double current = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES); 
     double total = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT); 
     printf("%d %d/%d %f\n", counter, (int)current, (int)total, millis); 
     int min = (int)(millis/1000/60); 
     millis -= min*60000; 
     int sec = (int)(millis/1000); 
     millis -= sec*1000; 

     printf("%d %02d:%02d:%f\n", counter, min, sec, millis); 
    } 
    cvReleaseCapture(&capture); 

    return 0; 
} 
+0

¿Qué estás usando: Windows/Linux/Mac? – karlphillip

+0

Linux (Ubuntu 10.04 LTS) – misha

+1

Eso explica mucho. OpenCV aún está trabajando para mejorar el soporte de archivos de video en Linux, lo siento. – karlphillip

Respuesta

5

informar siempre a la versión de software que está utilizando: la versión OpenCV está usando para eso? La suya puede ser una versión anterior, por lo tanto, actualice la más reciente si es posible.

Si su archivo de vídeo es parte de algún otro vídeo más grande, esta información podría ser en realidad correcta, ya que:

CV_CAP_PROP_POS_MSEC - film current position in milliseconds or video capture timestamp 

OpenCV podría ser simplemente leer todas estas cosas de la cabecera del archivo, que es obviamente erróneo. Esto podría suceder si alguien usara un hacha (u otra herramienta medieval) para quitarle esta pieza del video original.

Debe probar con los videos que hizo y sabe que no han sido manipulados.

En el peor de los casos, deberá implementar estas características usted mismo. No es gran cosa.

EDIT: @misha No me di cuenta en un primer momento que está utilizando:

CvCapture *capture = cvCaptureFromFile(argv[1]); 

Reemplazar por cvCaptureFromAVI() si se puede, y SIEMPRE comprobar el valor devuelto de OpenCV llama: hace

CvCapture *capture = cvCaptureFromAVI(argv[1]); 
if(!capture) 
{ 
    printf("!!! cvCaptureFromAVI failed (file not found?)\n"); 
    return -1; 
} 

unos días compartí un código que uses OpenCV to read a video file and then save the frames as JPG images on the disk. También informa el FPS actual utilizando el cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); tradicional, por lo que podría ser interesante que lo revise. Ve a verlo.

EDIT:

También debe comprobar this thread sobre recuento de fotogramas usando OpenCV;

Por cierto, me acaba de actualizar algunas bibliotecas en mi sistema Ubuntu y vuelve a compilar OpenCV-2.1.0.tar.bz2 (usando cmake). Cambié mi código fuente (que usa cvCaptureFromAVI()) para imprimir cosas usando su método de depuración en cada fotograma. Parece que funciona:

* Filename: sequence.mp4 
* FPS: 59 
... 
... 
... 
17 00:00:567.000000 
18 601/33371 601.000000 
18 00:00:601.000000 
19 634/33371 634.000000 
19 00:00:634.000000 
20 668/33371 668.000000 
20 00:00:668.000000 
21 701/33371 701.000000 
21 00:00:701.000000 
22 734/33371 734.000000 
22 00:00:734.000000 
23 768/33371 768.000000 
23 00:00:768.000000 
24 801/33371 801.000000 
24 00:00:801.000000 
25 835/33371 835.000000 
25 00:00:835.000000 
26 868/33371 868.000000 
26 00:00:868.000000 
27 901/33371 901.000000 
27 00:00:901.000000 
28 935/33371 935.000000 
... 
+0

Ah, sabía que estaba olvidando algo. 'cout <<" Versión de OpenCV: "<< CV_VERSION << endl;' da 'OpenCV versión: 2.0.0' – misha

+0

Estoy usando OpenCV 2.1 (que no es el más nuevo) y eso funciona bien. Actualice OpenCV en su máquina y vuelva a intentarlo. – karlphillip

+0

Instalé 2.1. El resultado sigue siendo el mismo :(No me importa volver a escribir esta funcionalidad para solucionar el problema, como dijiste, no es gran cosa. Mis preguntas son: ¿cómo sé que puedo confiar en el valor de fps en el encabezado? ¿Qué pasa con los videos fps variables? – misha

Cuestiones relacionadas