2015-04-16 21 views
8

W jaki sposób przechwytujesz wideo z dwóch lub więcej kamer jednocześnie (lub prawie) z OpenCV, korzystając z API Pythona?Odczyt z dwóch kamer jednocześnie OpenCV

Mam trzy kamery internetowe, wszystkie z możliwością przesyłania strumieniowego wideo, zlokalizowane w/dev/video0,/dev/video1 i/dev/video2.

Używanie tutorial jako przykład, przechwytywania obrazów z pojedynczej kamery jest prosta:

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

I to działa prawidłowo.

Jednak gdy próbuję zainicjować drugi aparat, próbując read() od zwraca 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?! 

Wystarczy, aby upewnić się, że nie został przypadkowo dając OpenCV zły indeks kamery, testowałem każdy indeks kamery indywidualnie i wszystkie działają samodzielnie. na przykład

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?! 

Co robię źle?

Edytuj: Mój sprzęt to Macbook Pro z uruchomionym systemem Ubuntu. Analizując problem specyficznie na komputerach MacBook, znalazłem innych, którzy również napotkali ten problem, zarówno na OSX, jak i na różnych typach kamer. Jeśli uzyskam dostęp do iSight, oba wywołania w moim kodzie zawodzą.

+0

Jeżeli zmienisz kolejność wypowiedzi VideoCapture czy błąd występuje na innym kanale? – kpie

+0

To wydaje się działać dobrze dla mnie w systemie Windows. – ballsatballsdotballs

+3

Czy kamery są zintegrowane, czy USB? Możliwe, że nie mogą działać jednocześnie, jeśli [są w tym samym szeregowym autobusie] (http://answers.opencv.org/question/19556/videocapture-open-wont-open-second-camera/), ponieważ magistrala szeregowa jest, no cóż, seryjna. –

Odpowiedz

2

Tak, zdecydowanie jesteś ograniczony przepustowością USB. Próby odczytu z obu urządzeń w pełnym wymiarze rez pewnie dostaje błąd:

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 

A potem, kiedy zmniejszyć res do 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?! 

teraz wydaje się do pracy! Założę się, że oba kable połączone są na tej samej karcie USB. można uruchomić komendę lsusb, aby upewnić się, i powinno to oznaczać coś takiego:

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 

(uwaga obu kamer na tej samej magistrali.) Jeśli to możliwe, można dodać inną kartę USB do komputera, aby uzyskać większą przepustowość. Zrobiłem to wcześniej, aby uruchomić wiele kamer w pełnej rozdzielczości na jednym komputerze. Chociaż była to stacja robocza typu tower z dostępnymi gniazdami na płycie głównej, a niestety może nie mieć takiej opcji na laptopie MacBooka.

+0

Dziwne, to nie zawsze działa na 160 x 120. Kupiłem 6 identycznych tanich kamer internetowych, a przy niektórych kombinacjach kamer zmniejszona rozdzielczość działa dobrze, a w przypadku innych kombinacji kamer nadal się nie udaje. – Cerin

+0

Może to zależeć od rozdzielczości obsługiwanych przez kamerę internetową. Spróbuj uruchomić '' v4l2-ctl --all'' lub '' v4l-info'' lub '' v4l-conf'' lub inne, aby znaleźć minimalną rozdzielczość obsługi kamer, a następnie przeprowadź swoją pracę aż do awarii. –

2

Używam "imutils" i czytam obraz z kamery na obrazie.

import imutils

przechwytywania vedio ramki

--- 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)

tworzę funkcja read_frame() wysłać parametr o Image.fromarray i wyświetlaczem

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

i ostatecznego Funkcja pokazu filmu na "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)

przykład. 4-webcam

Youtube: Youtube

2

Używanie OpenCV i dwóch standardowych kamer USB, byłem w stanie to zrobić przy użyciu wielowątkowości. Zasadniczo zdefiniuj jedną funkcję, która otwiera okno opencv i element VideoCapture. Następnie utwórz dwa wątki z identyfikatorem kamery i nazwą okna jako wejścia.

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() 

Wielki zasób za nauczenie się wkręcić w Pythonie: https://www.tutorialspoint.com/python/python_multithreading.htm

Powiązane problemy