tutorials docs image-processing opencv

image-processing - docs - opencv tutorials



leer marcos sucesivos OpenCV usando cvQueryframe (3)

Tengo una pregunta básica con respecto a cvQueryFrame () en OpenCV.

Tengo el siguiente código:

IplImage *frame1,*frame2; frame1 = cvQueryFrame(capture); frame2 = cvQueryFrame(capture);

Ahora mi pregunta es: si frame1 es un puntero al primer fotograma, ¿ frame2 es un puntero al segundo fotograma? ¿Las dos llamadas a cvQueryFrame() leerán cuadros sucesivos?

Pensé en verificarme primero, pero los punteros frame1 , frame2 parecen tener el mismo valor hexadecimal. : s Solo necesito capturar dos cuadros a la vez y luego necesito procesarlos.

Gracias por adelantado

EDITAR: encontré desde google que llamar a cvQueryFrame () devuelve dos veces el mismo puntero. ahora estoy un poco confundido. Si uso call solo una vez en un ciclo while, los cuadros progresan pero no si lo llamo dos veces? ¿Hay alguna manera fácil de obtener dos marcos?


Okay !

Tienes que hacer una copia de tu marco. frame1 = cvQueryFrame (captura); es un puntero como dijiste.

El código que encontré es:

IplImage* img1(null), img2(null); CvCapture* cap = cvCaptureFromAVI("mavideo.avi"); img2 = cvQueryFrame( cap ); img1 = cvCloneImage( img2 ); // on alloue une nouvelle image while( cvGrabFrame( cap ) ) { cvCopy( img2, img1 ); // copie de l''image, pas du pointeur img2 = cvRetrieveFrame( cap ); } cvReleaseCapture( &cap ); cvReleaseImage( &img1 );

Puede reemplazar el tiempo con un waitkey o cualquier cosa, pero si lo hace, use

img2 = cvQueryFrame( cap );

en lugar de

img2 = cvRetrieveFrame( cap );

porque no tendrás la

cvGrabFrame( cap )

nunca más

No sé si estoy claro, así que ... me quedo aquí ^^

Disfrutar;)

Laurent


ok siguiendo la respuesta de Laurent: creo que la clave es cvCloneImage (). cvCloneImage crea una nueva copia de la imagen original que incluye el encabezado, ROI, imageData, etc. y luego apunta a frame2 a esta nueva información.

Como cvQueryFrame es un contenedor para cvGrabFrame y cvRetrieveFrame, no quería dividir las funciones, por lo que con una pequeña modificación aún puedo usar cvQueryFrame.

A continuación está mi solución modificada.

IplImage *frame = cvQueryFrame(capture); //to read properties of frame. IplImage *frame2 = NULL;

while (1){ if(frame2) frame = cvCloneImage(frame2); // copy image to allow grabbing next frame frame2 = cvQueryFrame(capture); //read next frame if(!frame2) break; //if frame cannot be read, EOF so break from loop }

Espero que entiendas lo que he hecho aquí. Siéntase libre de hacer más preguntas.


cvQueryFrame() devuelve el puntero al búfer interno "privado" de OpenCV que siempre llena con el último marco capturado.
Si quiere 2 cuadros necesitará guardar una copia en caché. Una vez que asigna (por ejemplo, usando el cvCloneImage() ) para su cuadro anterior, puede usar cvCopy() para copiar solo los datos de la imagen. No use cvCloneImage() dentro del bucle ya que es muy ineficiente debido a las asignaciones de memoria interna (y desasignaciones, de lo contrario también tendrá fugas de memoria).

Actualización: el código se verá más o menos así:

IplImage* currFrame = 0; IplImage* prevFrame = 0; CvCapture* cap = cvCaptureFromAVI("sample.avi"); currFrame = cvQueryFrame( cap ); // Clone the frame to have an identically sized and typed copy prevFrame = cvCloneImage( currFrame ); while(currFrame = cvQueryFrame( cap )) { // process the video using currFrame and prevFrame... // ... // When done, overwrite prevFrame with current copy in preparation // for the next frame. cvCopy( currFrame , prevFrame); } cvReleaseImage( &img1 ); cvReleaseCapture( &cap );

Nota: a menudo, puede evitar este tiempo de copia "redundante" haciendo una conversión.
Por ejemplo, supongamos que su pantalla está en color, pero su procesamiento está en escala de grises. Solo necesita las 2 copias consecutivas en escala de grises. Ya que necesitará convertir a escala de grises de todos modos, puede hacerlo directamente desde el fotograma capturado, evitando así la redundante cvCopy() . Para guardar el cuadro anterior, simplemente intercambie los punteros entre las 2 imágenes asignadas en escala de grises.