2010-01-12 9 views
12

Tengo un bucle para tomar imágenes de un framegrabbger de alta velocidad a 250 fps.¿Visualiza la imagen en el segundo hilo, OpenCV?

/** Loop processes 250 video frames per second **/ 
while(1){ 
    AcquireFrame(); 
    DoProcessing(); 
    TakeAction(); 
} 

Al mismo tiempo, me gustaría que el usuario pueda controlar lo que está sucediendo. El usuario solo necesita ver imágenes a alrededor de 30 fps (o menos). ¿Cómo configuro un segundo hilo que muestra el marco actual cada cierto tiempo?

Thread(){ 
    cvShowImage(); 
    Wait(30); /** Wait for 30 ms **/ 
} 

Estoy en Windows en una máquina Intel quad core que usa MinGW, gcc y OpenCV 1.1. El criterio principal es que el hilo de visualización debe tomar el menor tiempo posible de mi ciclo de procesamiento principal. Cada milisegundo cuenta.

He intentado usar CreateThread() para crear un nuevo hilo con cvShowImage() y cvWaitKey() pero apparently those functions are not threadsafe.

Estoy considerando usar OpenMP, pero algunas personas report problems with OpenMP and OpenCV. También estoy considerando intentar usar DirectX DirectDraw porque aparentemente es muy rápido. pero es looks complicated y evidentally hay problems using Windows DLL's with MinGw.

¿Cuál de estos caminos sería el mejor lugar para comenzar?

+0

¿No es suficiente usar una condición if y una variable de "conteo" de hasta 250 para mostrar cada 8ª captura (250/30)? –

+0

Ah sí. Pero si lo haces, todo el programa se detendrá mientras muestras la octava captura. Toma ~ 10 ms para visualizar una imagen usando cvShowImage. En ese momento ya te has perdido algunos marcos. – AndyL

+0

¿Obtienes 250 fps de una cámara? Si es así, ¿puedes decirme cómo lo hiciste? Eso es extremadamente rápido. – bakalolo

Respuesta

10

Ok. Tan vergonzosamente mi pregunta es también su propia respuesta.

El uso de CreateThread(), CvShowImage() y CvWaitKey() como se describe en mi pregunta realmente funciona, a diferencia de algunas publicaciones en la web que sugieren lo contrario.

En cualquier caso, he implementado algo como esto:

/** Global Variables **/ 
bool DispThreadHasFinished; 
bool MainThreadHasFinished; 
iplImage* myImg; 

/** Main Loop that loops at >100fps **/ 
main() { 
    DispThreadHasFinished = FALSE; 
    MainThreadHasFinished = FALSE; 
    CreateThread(..,..,Thread,..); 

    while(IsTheUserDone()) { 
    myImg=AcquireFrame(); 
    DoProcessing(); 
    TakeAction(); 
    } 
    MainThreadHasFinished = TRUE; 

    while (!DisplayThreadHasFinished) { 
    CvWaitKey(100); 
    } 

    return; 
} 

/** Thread that displays image at ~30fps **/ 
Thread() { 
    while (!MainThreadHasFinished) { 
    cvShowImage(myImg); 
    cvWaitKey(30); 
    } 
DispThreadHasFinished=TRUE; 
return; 
} 

Cuando Iniciado esta pregunta, mi código estaba fallando por razones no relacionadas. ¡Espero que esto ayude!

4

Dado que la captura de fotogramas no necesita utilizar la interfaz de usuario, configuraría una secuencia secundaria para manejar la captura de fotogramas, y la secuencia original que maneja la UI mostrará los fotogramas de muestra. Si ha intentado mostrar el marco que actualmente se captura, deberá bloquear los datos (que generalmente es bastante lento). Para evitar eso, mostraría un fotograma uno (o posiblemente dos) "detrás" del que está siendo capturado actualmente, por lo que no hay disputa entre capturar y mostrar los datos. Aún deberá asegurarse de que incrementar el número de cuadro actual sea seguro para la ejecución de subprocesos, pero eso es bastante simple: use InterlockedIncrement en el hilo de captura.

+0

Estoy de acuerdo con esta solución, parece que la complejidad aquí radica en el hecho de que el procesamiento se está haciendo en el hilo principal. Si el procesamiento se realizó en un hilo de fondo, guardando una referencia, en la última imagen, el hilo de la interfaz de usuario (o un hilo de trabajo en la interfaz de usuario) podría capturar esa última imagen al ritmo que usted elija. –

0

Disculpa, no puedo ofrecerte una mejor respuesta en este momento, pero parece que tu pregunta no está relacionada con la estructura de tu programa, sino con la herramienta que deberías usar para implementar el multihilo. Para esto, recomendaría Qt. He estado usando Qt por un tiempo, pero ahora estoy entrando en multihilo.

Me parece que su mejor opción podría ser QReadWriteLock. Esto le permite leer desde una imagen, pero el hilo del lector abandonará su bloqueo cuando aparezca el hilo del escritor. En este caso, puede conservar una copia de la imagen que mostró por última vez y mostrarla si la imagen está bloqueada para la escritura.

Una vez más, siento que no puedo ser más detallada, pero, como dije, también me estoy metiendo en esto. Básicamente intento hacer lo mismo que tú, pero no tan rápido :). ¡Buena suerte!

0

No estoy seguro de por qué sucede esto, pero he agregado un cvWaitKey después de cada cvShowImage y la imagen se muestra correctamente.

cvShowImage(myImage); 
cvWaitKey(1); 
Cuestiones relacionadas