2016-05-11 17 views
5

Cerco di ottenere immagini dalla webcam con opencv e python. Il codice è così semplice come:BeagleBone Black OpenCV Python è troppo lento

import cv2 
import time 
cap=cv2.VideoCapture(0) 
cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH,640) 
cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,480) 
cap.set(cv2.cv.CV_CAP_PROP_FPS, 20) 

a=30 
t=time.time() 
while (a>0): 
     now=time.time() 
     print now-t 
     t=now 
     ret,frame=cap.read() 
     #Some processes 
     print a,ret 
     print frame.shape 
     a=a-1 
     k=cv2.waitKey(20) 
     if k==27: 
       break 
cv2.destroyAllWindows() 

Ma funziona lentamente. output del programma:

VIDIOC_QUERYMENU: Invalid argument 
VIDIOC_QUERYMENU: Invalid argument 
VIDIOC_QUERYMENU: Invalid argument 
VIDIOC_QUERYMENU: Invalid argument 
VIDIOC_QUERYMENU: Invalid argument 
VIDIOC_QUERYMENU: Invalid argument 
HIGHGUI ERROR: V4L: Property <unknown property string>(5) not supported by device 
8.82148742676e-06 
select timeout 
30 True 
(480, 640, 3) 
2.10035800934 
select timeout 
29 True 
(480, 640, 3) 
2.06729602814 
select timeout 
28 True 
(480, 640, 3) 
2.07144904137 
select timeout 

Configurazione:

  • BeagleBone nero RevC
  • Debian-wheezly
  • OpenCV 2.4
  • pitone 2,7
+1

Per questo problema probabilmente non aiuterà, ma se si sta utilizzando OpenCV effettivamente fare cose cv, probabilmente avrete bisogno di verificare che l'OpenCV si sta utilizzando è compilato contro le estensioni al neon. (facendo google opencv beaglebone neon troverà probabilmente dettagli utili, ad esempio http://blog.lemoneerlabs.com/3rdParty/Darling_BBB_30fps_DRAFT.html) – Foon

+0

"opencv 2.4" - devi essere più specifico, c'è stato un numero di 2.4 .x rilasci di OpenCV nel corso di diversi anni. –

risposta

3

ho incontrato un problema simile quando stavo lavorando su un progetto che utilizza OpenCV 2.4.9 sulla piattaforma Intel Edison. Prima di eseguire qualsiasi elaborazione, ci sono voluti circa 80ms solo per eseguire il frame grab. Risulta che la logica di acquisizione della telecamera di OpenCV per Linux non sembra essere implementata correttamente, almeno nella versione 2.4.9. Il driver sottostante utilizza solo un buffer, quindi non è possibile utilizzare il multi-threading nel livello dell'applicazione per aggirare il problema - finché non si tenta di afferrare il frame successivo, l'unico buffer nel driver V4L2 è bloccato.

La soluzione è di non utilizzare la classe VideoCapture di OpenCV. Forse a un certo punto è stato corretto usare un numero ragionevole di buffer, ma a partire da 2.4.9 non lo era. Infatti, se guardi l'articolo this dallo stesso autore del collegamento fornito da @Nickil Maveli, scoprirai che non appena fornisce suggerimenti per migliorare l'FPS su un Raspberry Pi, smette di usare VideoCapture di OpenCV. Non credo che sia una coincidenza.

Ecco il mio post al riguardo nel forum Intel Edison: https://communities.intel.com/thread/58544.

Fondamentalmente ho finito di scrivere la mia classe per gestire i frame grab, usando direttamente V4L2. In questo modo è possibile fornire un elenco circolare di buffer e consentire al grabbing del frame e alla logica dell'applicazione di essere correttamente disaccoppiati. Ciò è stato fatto in C++, però, per un'applicazione C++. Supponendo che il collegamento sopra riportato mantenga le sue promesse, potrebbe essere un approccio molto più semplice. Non sono sicuro che funzioni su BeagleBone, ma forse c'è qualcosa di simile a PiCamera là fuori. In bocca al lupo.

MODIFICA: ho dato un'occhiata al codice sorgente per 2.4.11 di OpenCV. Sembra che ora utilizzino di default 4 buffer, ma per sfruttare questo vantaggio è necessario utilizzare V4L2. Se si osserva da vicino il messaggio di errore HIGHGUI ERROR: V4L: Property..., si vede che fa riferimento a V4L, non a V4L2. Ciò significa che la build di OpenCV che stai utilizzando sta ricadendo sul vecchio driver V4L. Oltre al buffer singolare che causa problemi di prestazioni, si sta utilizzando un driver antico che probabilmente presenta molte limitazioni e problemi di prestazioni.

La soluzione migliore sarebbe creare da soli OpenCV per assicurarsi che utilizzi V4L2. Se ricordo correttamente, il processo di configurazione di OpenCV controlla se i driver V4L2 sono installati sulla macchina e li costruisce di conseguenza, quindi è necessario assicurarsi che V4L2 e tutti i relativi pacchetti di sviluppo siano installati sulla macchina che si utilizza per creare OpenCV.

+0

il buffer è nella memoria hardware credo (dalla mia esperienza). – user5698387

3

Il "segreto" per ottenere FPS più alto durante l'elaborazione di flussi video con OpenCV è quello di spostare l'I/O (cioè la lettura di fotogrammi dal sensore della fotocamera) su una filettatura separata.

Quando si chiama read() metodo insieme cv2.VideoCapture funzione, rende l'intero processo molto lento perché deve attendere per ogni operazione di I/O per essere completata per poter passare a quello successivo (Blocking Process).

Per raggiungere questa diminuzione di incremento/latenza di FPS, il nostro obiettivo è spostare la lettura dei frame da una webcam o un dispositivo USB in un thread completamente diverso, completamente separato dal nostro script Python principale.

Ciò consentirà la lettura continua dei frame dal thread I/O, mentre il thread principale elabora il frame corrente. Una volta che il thread di root ha terminato l'elaborazione del frame, è sufficiente prendere il frame corrente dal thread I/O. Ciò è possibile senza dover attendere il blocco delle operazioni di I/O.

È possibile leggere Increasing webcam FPS with Python and OpenCV per conoscere i passaggi nell'implementazione dei thread.


EDIT

Sulla base delle discussioni nei nostri commenti, mi sento si potrebbe riscrivere il codice come segue:

import cv2 

cv2.namedWindow("output") 
cap = cv2.VideoCapture(0) 

if cap.isOpened():    # Getting the first frame 
    ret, frame = cap.read() 
else: 
    ret = False 

while ret: 
    cv2.imshow("output", frame) 
    ret, frame = cap.read() 
    key = cv2.waitKey(20) 
    if key == 27:     # exit on Escape key 
     break 
cv2.destroyWindow("output") 
+0

Ho fatto le stesse cose ma python e opencv sono ancora troppo lenti – acs

+0

Prova, imposta il tuo fps della fotocamera su 'cap.set (cv2.cv.CV_CAP_PROP_FPS, 30)' e guarda i risultati. –

+0

Ancora lo stesso. modificato in questione – acs

1

prova questo! Ho sostituito un codice nella sezione cap.set()

import cv2 
import time 
cap=cv2.VideoCapture(0) 
cap.set(3,640) 
cap.set(4,480) 
cap.set(5, 20) 

a=30 
t=time.time() 
while (a>0): 
     now=time.time() 
     print now-t 
     t=now 
     ret,frame=cap.read() 
     #Some processes 
     print a,ret 
     print frame.shape 
     a=a-1 
     k=cv2.waitKey(20) 
     if k==27: 
       break 
cv2.destroyAllWindows() 

output (pc webcam) il codice era sbagliato per me.

>>0.0 
>>30 True 
>>(480, 640, 3) 
>>0.246999979019 
>>29 True 
>>(480, 640, 3) 
>>0.0249998569489 
>>28 True 
>>(480, 640, 3) 
>>0.0280001163483 
>>27 True 
>>(480, 640, 3) 
>>0.0320000648499 
+0

Le chiamate di funzione 'cap.set' originali andavano bene. Le costanti @acs utilizzate valutano gli stessi valori che hai specificato manualmente. Questa non è la causa del problema di prestazioni. – Aenimated1