2015-04-16 18 views
8

Come si acquisiscono video da due o più videocamere contemporaneamente (o quasi) con OpenCV, utilizzando l'API Python?Lettura simultanea di due telecamere in OpenCV

Ho tre webcam, tutte in grado di streaming video, situate in/dev/video0,/dev/video1 e/dev/video2.

Utilizzando la tutorial come esempio, l'acquisizione di immagini da una singola telecamera è semplicemente:

import cv2 
cap0 = cv2.VideoCapture(0) 
ret0, frame0 = cap0.read() 
cv2.imshow('frame', frame0) 
cv2.waitKey() 

E questo funziona bene.

Tuttavia, se cerco di inizializzare una seconda telecamera, cercando di read() da esso restituisce None:

import cv2 
cap0 = cv2.VideoCapture(0) 
cap1 = cv2.VideoCapture(1) 
ret0, frame0 = cap0.read() 
assert ret0 # succeeds 
ret1, frame1 = cap1.read() 
assert ret1 # fails?! 

solo per garantire che non è stato accidentalmente dando OpenCV un indice fotocamera male, ho provato ogni indice fotocamera individualmente e tutti lavorano da soli. per esempio.

import cv2 
#cap0 = cv2.VideoCapture(0) 
cap1 = cv2.VideoCapture(1) 
#ret0, frame0 = cap0.read() 
#assert ret0 
ret1, frame1 = cap1.read() 
assert ret1 # now it works?! 

Cosa sto sbagliando?

Modifica: il mio hardware è un Macbook Pro con Ubuntu. Ricercando il problema in particolare sui MacBook, ho trovato altri che hanno incontrato questo problema, sia su OSX che con diversi tipi di fotocamere. Se accedo a iSight, entrambe le chiamate nel mio codice falliscono.

+0

Se si modifica l'ordine delle istruzioni VideoCapture si verifica l'errore sull'altro canale? – kpie

+0

Questo sembra funzionare bene per me su Windows. – ballsatballsdotballs

+3

Le telecamere sono entrambe integrate o USB? È possibile che non possano operare simultaneamente se [sono sullo stesso bus seriale] (http://answers.opencv.org/question/19556/videocapture-open-wont-open-second-camera/) perché il bus seriale è, beh, seriale. –

risposta

2

Sì, sei decisamente limitato dalla larghezza di banda USB. Il tentativo di leggere da entrambi i dispositivi a full-rez probabilmente hai errore:

libv4l2: error turning on stream: No space left on device 
VIDIOC_STREAMON: No space left on device 
Traceback (most recent call last): 
    File "p.py", line 7, in <module> 
    assert ret1 # fails?! 
AssertionError 

E poi, quando si riducono le res a 160x120:

import cv2 
cap0 = cv2.VideoCapture(0) 
cap0.set(3,160) 
cap0.set(4,120) 
cap1 = cv2.VideoCapture(1) 
cap1.set(3,160) 
cap1.set(4,120) 
ret0, frame0 = cap0.read() 
assert ret0 # succeeds 
ret1, frame1 = cap1.read() 
assert ret1 # fails?! 

ora sembra funzionare! Scommetto che hai entrambe le webcam collegate sulla stessa scheda USB. È possibile eseguire lsusb comando per fare in modo, e dovrebbe indicare qualcosa come:

Bus 001 Device 006: ID 046d:081b Logitech, Inc. Webcam C310 
Bus 001 Device 004: ID 0409:005a NEC Corp. HighSpeed Hub 
Bus 001 Device 007: ID 046d:0990 Logitech, Inc. QuickCam Pro 9000 
Bus 001 Device 005: ID 0409:005a NEC Corp. HighSpeed Hub 
Bus 001 Device 003: ID 0409:005a NEC Corp. HighSpeed Hub 
Bus 001 Device 002: ID 1058:0401 Western Digital Technologies, Inc. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub 
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub 

(Nota entrambe le telecamere sul bus stesso.) Se possibile, è possibile aggiungere un'altra scheda USB alla vostra macchina per ottenere maggiore larghezza di banda. L'ho fatto prima per far girare più camme a piena risoluzione su una singola macchina. Anche se si trattava di una workstation tower con slot per schede madri disponibili, e sfortunatamente non si può avere questa opzione su un laptop MacBook.

+0

Stranamente, non funziona sempre anche a 160x120. Ho acquistato 6 webcam identiche a basso costo e, con alcune combinazioni di telecamere, la risoluzione ridotta funziona bene e, con altre combinazioni di fotocamere, non funzionano ancora. – Cerin

+0

Potrebbe dipendere dalle risoluzioni native supportate dalla webcam. Prova a eseguire '' v4l2-ctl --all'' o '' v4l-info'' o '' v4l-conf'' o altri per trovare il supporto minimo supportato dalle tue camme, quindi procedi fino al fallimento. –

2

Ho usato "imutils" e ho letto la webcam show sull'immagine.

import imutils

incornicia la cattura di vedio

--- WebCam1

cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH,300) cap.set(cv2.CAP_PROP_FRAME_HEIGHT,300)

--- WebCam2

cap1 = cv2.VideoCapture(1) cap1.set(cv2.CAP_PROP_FRAME_WIDTH,300) cap1.set(cv2.CAP_PROP_FRAME_HEIGHT,300)

--- WebCam3

cap2 = cv2.VideoCapture(2) cap2.set(cv2.CAP_PROP_FRAME_WIDTH,300) cap2.set(cv2.CAP_PROP_FRAME_HEIGHT,300)

--- WebCame4

cap3 = cv2.VideoCapture(3) cap3.set(cv2.CAP_PROP_FRAME_WIDTH,300) cap3.set(cv2.CAP_PROP_FRAME_HEIGHT,300)

genero funzione read_frame() inviare parametri relativi a Image.fromarray e visualizzazione

def read_frame(): webCameShow(cap.read(),display1) webCameShow(cap1.read(),display2) webCameShow(cap2.read(),display6) webCameShow(cap3.read(),display7)
window.after(10, read_frame)

e il video funzione di spettacolo finale sul "IMAGEFRAME"

def webCameShow(N,Display): _, frameXX = N cv2imageXX = cv2.cvtColor(frameXX, cv2.COLOR_BGR2RGBA) imgXX = Image.fromarray(cv2imageXX) #imgtkXX = ImageTk.PhotoImage(image=imgXX) Display.imgtk = imgtkXX Display.configure(image=imgtkXX)

esempio. 4-webcam

Youtube: Youtube

2

Utilizzando OpenCV e due fotocamere USB standard, sono stato in grado di farlo usando il multithreading. In sostanza, definisce una funzione che apre una finestra opencv e un elemento VideoCapture. Quindi, crea due thread con l'ID della videocamera e il nome della finestra come input.

import cv2 
import threading 

class camThread(threading.Thread): 
    def __init__(self, previewName, camID): 
     threading.Thread.__init__(self) 
     self.previewName = previewName 
     self.camID = camID 
    def run(self): 
     print "Starting " + self.previewName 
     camPreview(self.previewName, self.camID) 

def camPreview(previewName, camID): 
    cv2.namedWindow(previewName) 
    cam = cv2.VideoCapture(camID) 
    if cam.isOpened(): # try to get the first frame 
     rval, frame = cam.read() 
    else: 
     rval = False 

    while rval: 
     cv2.imshow(previewName, frame) 
     rval, frame = cam.read() 
     key = cv2.waitKey(20) 
     if key == 27: # exit on ESC 
      break 
    cv2.destroyWindow(previewName) 

# Create two threads as follows 
thread1 = camThread("Camera 1", 1) 
thread2 = camThread("Camera 2", 2) 
thread1.start() 
thread2.start() 

grande risorsa per l'apprendimento come infilare in python: https://www.tutorialspoint.com/python/python_multithreading.htm

Problemi correlati