Захват видео с двух камер в OpenCV сразу
как вы снимаете видео с двух или более камер одновременно (или почти) с помощью OpenCV, используя API Python?
у меня есть три веб-камеры, все способные к потоковой передаче видео, расположенные в /dev/video0, /dev/video1 и /dev/video2.
С помощью учебник в качестве примера, Захват изображений с одной камеры просто:
import cv2
cap0 = cv2.VideoCapture(0)
ret0, frame0 = cap0.read()
cv2.imshow('frame', frame0)
cv2.waitKey()
и это прекрасно работает.
однако, если я попытаюсь инициализировать вторую камеру, пытаясь read()
из него возвращается 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?!
просто чтобы убедиться, что я случайно не дал OpenCV плохой индекс камеры, я проверил каждый индекс камеры индивидуально, и все они работают сами по себе. например,
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?!
что я делаю не так?
Edit: мое оборудование-это Macbook Pro под управлением Ubuntu. Исследуя проблему конкретно на Macbooks, я нашел другие, которые тоже столкнулись с этой проблемой, как на OSX, так и с различными типами камер. Если я получу доступ к iSight, оба вызовы в моем коде терпят неудачу.
4 ответов
Да, вы определенно ограничены полосой пропускания USB. При попытке чтения с обоих устройств в full-rez вы, вероятно, получили ошибку:
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
а затем, когда вы уменьшите res до 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?!
теперь, кажется, работает! Держу пари, у вас обе камеры подключены к одной USB-карте. Вы можете запустить lsusb
команда, чтобы убедиться, и она должна указывать что-то вроде:
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
(обратите внимание на обе камеры на одной шине.) Если возможно, вы можете добавить другую карту USB к вашей машине, чтобы получить больше пропускной способности. Я делал это раньше, чтобы запустить несколько камер с полным разрешением на одной машине. Хотя это была рабочая станция tower с доступными слотами для материнской платы, и, к сожалению, у вас может не быть этой опции на ноутбуке MacBook.
используя OPENCV и две стандартные USB-камеры, я смог сделать это с помощью многопоточности. По сути, определите одну функцию, которая открывает окно opencv и элемент VideoCapture. Затем создайте два потока с идентификатором камеры и именем окна в качестве входных данных.
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()
отличный ресурс для обучения потоку в python:https://www.tutorialspoint.com/python/python_multithreading.htm
Я использую "imutils"и читаю веб-камеру на изображении.
импорт imutils
захват vedio кадров
--- WebCam1
cap = cv2.Захватить видео(0) крышка.набор(cv2.CAP_PROP_FRAME_WIDTH, 300) крышка.набор(cv2.CAP_PROP_FRAME_HEIGHT, 300)
--- WebCam2
cap1 = cv2.Захватить видео(1) cap1.набор(cv2.CAP_PROP_FRAME_WIDTH, 300) cap1.набор(cv2.CAP_PROP_FRAME_HEIGHT, 300)
--- WebCam3
cap2 = cv2.Захватить видео(2) cap2.набор(cv2.CAP_PROP_FRAME_WIDTH, 300) cap2.набор(cv2.CAP_PROP_FRAME_HEIGHT, 300)
--- WebCame4
cap3 = cv2.Захватить видео(3) cap3.набор(cv2.CAP_PROP_FRAME_WIDTH, 300) cap3.набор(cv2.CAP_PROP_FRAME_HEIGHT, 300)
Я создаю функцию read_frame () отправить параметр об изображении.fromarray и дисплей
def read_frame(): webCameShow (cap.читать(),display1) webCameShow (cap1.читать(),монитор display2) webCameShow (cap2.читать(),display6) webCameShow (cap3.read (), display7)
окно.после(10, read_frame)
и финальная функция показать видео на "imageFrame"
def webCameShow(N, дисплей): _ , frameXX = N cv2imageXX = cv2.cvtColor (frameXX, cv2.COLOR_BGR2RGBA) imgXX = изображение.fromarray (cv2imageXX) #imgtkXX = ImageTk.Фотоизображение (image=imgXX) Дисплей.imgtk = imgtkXX Дисплей.настройка (image=imgtkXX)
пример. 4-веб-камера
на YouTube: на YouTube
Это было болью для меня в течение длительного времени, поэтому я сделал библиотеку поверх OpenCV для обработки нескольких камер и иллюминаторов. Я столкнулся с кучей проблем, таких как видео, не сжимающиеся по умолчанию, или окна, отображаемые только в основном потоке. До сих пор я могу отображать две веб-камеры 720p в режиме реального времени на Windows.
попробуй:
pip install CVPubSubs
затем, в python:
import cvpubsubs.webcam_pub as w
from cvpubsubs.window_sub import SubscriberWindows
t1 = w.VideoHandlerThread(0)
t2 = w.VideoHandlerThread(1)
t1.start()
t2.start()
SubscriberWindows(window_names=['cammy', 'cammy2'],
video_sources=[0,1]
).loop()
t1.join()
t1.join()
это относительно новое, поэтому расскажите мне о любых ошибках или неоптимизированном коде.