Python APIを使用して、OpenCVで一度に(またはほぼ)2台以上のカメラからビデオをキャプチャするにはどうすればよいですか?
/ dev/video0、/ dev/video1、および/ dev/video2にある、すべてビデオストリーミングが可能な3つのWebカメラがあります。
tutorial を例として使用すると、単一のカメラから画像をキャプチャするのは簡単です:
_import cv2
cap0 = cv2.VideoCapture(0)
ret0, frame0 = cap0.read()
cv2.imshow('frame', frame0)
cv2.waitKey()
_
そして、これはうまく機能します。
ただし、2番目のカメラを初期化しようとすると、そこから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?!
_
私は何を間違えていますか?
編集:私のハードウェアはUbuntuを実行しているMacbook Proです。この問題を特にMacbookで調査したところ、OSXとさまざまなタイプのカメラの両方で、この問題に遭遇した他の人も見つかりました。 iSightにアクセスすると、コード内の両方の呼び出しが失敗します。
はい、あなたは間違いなく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
そして、解像度を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カードをマシンに追加して、帯域幅を増やします。単一のマシンで複数のカムを最大解像度で実行するために、これを以前に実行しました。それは、利用可能なマザーボードスロットを備えたタワー型ワークステーションでしたが、残念ながら、MacBookラップトップにはそのオプションがない場合があります。
OPENCVと2つの標準USBカメラを使用して、マルチスレッドを使用してこれを行うことができました。基本的に、opencvウィンドウとVideoCapture要素を開く関数を1つ定義します。次に、カメラIDとウィンドウ名を入力として2つのスレッドを作成します。
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.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)
関数read_frame()を作成し、Image.fromarrayおよびdisplayに関するパラメーターを送信します
def read_frame():webCameShow(cap.read()、display1)webCameShow(cap1.read()、display2)webCameShow(cap2.read()、display6)webCameShow(cap3.read()、display7)
window.after(10、read_frame)
最後の関数は「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)
例。 4-webcam
Youtube: Youtube
frame0 = cv2.VideoCapture(1)
frame1 = cv2.VideoCapture(2)
でなければなりません:
frame0 = cv2.VideoCapture(0) # index 0
frame1 = cv2.VideoCapture(1) # index 1
それで走ります
以前に@TheoreticallyNickが投稿したものに少し追加します。
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():
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 threads as follows
thread1 = camThread("Camera 1", 0)
thread2 = camThread("Camera 2", 1)
thread3 = camThread("Camera 3", 2)
thread1.start()
thread2.start()
thread3.start()
print()
print("Active threads", threading.activeCount())
これにより、使用しているWebカメラごとに新しいスレッドが開きます。私の場合、3つの異なるフィードを開きたいと思いました。テスト済みPython 3.6。何か問題があるかどうかを教えてください。また、読み取り可能/機能コードのTheoreticallyNickに感謝します!
このコードを使用してみてください...それは期待通りに動作しました...これは2つのカム用です。もっと多くのカムが必要な場合は、「VideoCapture()」オブジェクトを作成してください。 3)whileループ内の対応するコード
import cv2
frame0 = cv2.VideoCapture(1)
frame1 = cv2.VideoCapture(2)
while 1:
ret0, img0 = frame0.read()
ret1, img00 = frame1.read()
img1 = cv2.resize(img0,(360,240))
img2 = cv2.resize(img00,(360,240))
if (frame0):
cv2.imshow('img1',img1)
if (frame1):
cv2.imshow('img2',img2)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
frame0.release()
frame1.release()
cv2.destroyAllWindows()
ではごきげんよう !
これは私にとって長い間苦痛だったので、複数のカメラとビューポートを処理するためにOpenCVの上にライブラリを作成しました。ビデオがデフォルトで圧縮されない、ウィンドウがメインスレッドにしか表示されないなどの問題に遭遇しました。これまでのところ、Windowsで2つの720pウェブカメラをリアルタイムで表示できます。
試してください:
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()
比較的新しいので、バグや最適化されていないコードについて教えてください。