2010-01-12 10 views
12

Ho un loop per scattare immagini da un framegrabbger ad alta velocità a 250fps.Visualizza l'immagine nella seconda discussione, OpenCV?

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

Allo stesso tempo, vorrei che l'utente fosse in grado di monitorare cosa sta succedendo. L'utente deve solo vedere le immagini a circa 30 fps (o meno). Come posso impostare un secondo thread che visualizza il frame corrente ogni tanto?

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

Sono su Windows su una macchina quad core Intel utilizzando MinGW, gcc e OpenCV 1.1. Il criterio principale è che il thread di visualizzazione deve impiegare il minor tempo possibile dal mio ciclo di elaborazione principale. Conta ogni millisecondo.

Ho provato a utilizzare CreateThread() per creare una nuova discussione con cvShowImage() e cvWaitKey() ma apparently those functions are not threadsafe.

Sto pensando di utilizzare OpenMP, ma alcune persone report problems with OpenMP and OpenCV. Sto anche considerando di provare a utilizzare DirectX DirectDraw perché apparentemente è molto veloce. ma è looks complicated ed evidentemente ci sono problems using Windows DLL's with MinGw.

Quale di queste strade sarebbe il miglior punto di partenza?

+0

Non è sufficiente utilizzare solo una condizione if e una variabile "count" fino a 250 per visualizzare ogni ottava cattura (250/30)? –

+0

Ah si. Ma se lo fai, allora l'intero programma si bloccherà mentre visualizzi l'ottava cattura. Ci vogliono ~ 10 ms per visualizzare un'immagine usando cvShowImage. A quel punto hai già perso alcuni fotogrammi. – AndyL

+0

Stai ricevendo 250 fps da una fotocamera? Se sei puoi dirmi come hai fatto? È estremamente veloce. – bakalolo

risposta

10

Ok. In modo imbarazzante, la mia domanda è anche la sua risposta.

L'utilizzo di CreateThread(), CvShowImage() e CvWaitKey() come descritto nella mia domanda funziona effettivamente, contrariamente ad alcuni messaggi sul Web che suggeriscono il contrario.

In ogni caso, ho implementato qualcosa di simile:

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

Quando ho originariamente postato questa domanda, il mio codice stava venendo a mancare per ragioni non correlate. Spero che aiuti!

4

Poiché il frame grabbing non ha bisogno di utilizzare l'interfaccia utente, ho impostato un thread secondario per gestire l'acquisizione del frame e il thread originale che gestisce l'interfaccia utente visualizza i frame di esempio. Se hai provato a visualizzare il fotogramma corrente, dovresti bloccare i dati (che in genere è piuttosto lento). Per evitare ciò, visualizzerei un frame uno (o forse due) "dietro" quello che viene afferrato al momento, quindi non c'è nessuna contesa tra l'acquisizione e la visualizzazione dei dati. Dovrai comunque assicurarti che l'incremento del numero di fotogramma corrente sia sicuro per i thread, ma è piuttosto semplice: usa InterlockedIncrement nel thread di cattura.

+0

Sono d'accordo con questa soluzione: sembra che la complessità qui sia radicata nel fatto che l'elaborazione viene eseguita sul thread principale. Se l'elaborazione è stata eseguita su un thread in background, salvando un riferimento, sull'ultima immagine, il thread ui (o un thread di lavoro sull'interfaccia utente) potrebbe catturare quell'ultima immagine in qualsiasi modo si scelga. –

0

Mi dispiace non posso darti una risposta migliore in questo momento, ma sembra che la tua domanda non riguardi la struttura del tuo programma ma piuttosto lo strumento che dovresti usare per implementare il multithreading. Per questo vorrei raccomandare Qt. Ho usato Qt per un po ', ma ora sto entrando nel multithreading.

Mi sembra che la soluzione migliore potrebbe essere una QReadWriteLock. Questo ti permette di leggere da un'immagine, ma il thread del lettore lascerà il suo blocco quando arriva il thread dello scrittore. In questo caso è possibile conservare una copia dell'immagine visualizzata per ultima e visualizzarla se l'immagine è bloccata per la scrittura.

Scusate ancora una volta che non posso essere più dettagliato ma, come ho detto, sto anche entrando in questo. Praticamente sto cercando di fare la stessa cosa che tu sia, ma non altrettanto velocemente :). In bocca al lupo!

0

Non sono sicuro del motivo per cui ciò accada, ma ho aggiunto un cvWaitKey dopo ogni cvShowImage e l'immagine è stata visualizzata correttamente.

cvShowImage(myImage); 
cvWaitKey(1);