Ubuntu11.10でOpenCV2.1を使用して、3台のLogitech Webcam Pro900デバイスから同時に画像をストリーミングしようとしています。これらのためにuvcvideoドライバーがロードされます。
2つのデバイスのキャプチャは正常に機能しますが、3つでは、3番目のデバイスでスペース不足エラーが発生します。
libv4l2: error turning on stream: No space left on device
私はこの問題に遭遇しているようです: http://renoirsrants.blogspot.com.au/2011/07/multiple-webcams-on-zoneminder.html そして私は癖をしようとしました= 128(または他のほとんどすべての2の累乗の値)トリックですが、役に立ちません。また、2つのUSB 2.0ハブを備え、2台のカメラを1台に、3台目のカメラを2台目に接続した別のマシンで試したところ、同じ問題が発生しました。私は大まかに次のように初期化しています(N台のカメラを使用して結果が実際にSTLベクトルに入れられるようにします):
cv::VideoCapture cap0(0); //(0,1,2..)
ループ内のすべてのカメラを次のようにキャプチャしようとしています
cap0.retrieve(frame0);
これは、N = 2カメラで正常に機能します。 N = 3に設定すると、3番目のウィンドウが開きますが、画像が表示されず、コンソールはV4L2エラーでいっぱいにスパムされます。同様に、N = 2を設定し、たとえばCheese(単純なWebカメラキャプチャアプリケーション)で3番目のカメラを開こうとすると、これも機能しません。
大きな問題になりましたが、3つのインスタンスを開始してguvcviewを試した後、一度に3台のカメラを表示できたので(フレームレートや関連する問題はありません)、ハードウェアの問題ではないようです。設定する必要のあるプロパティがあると思いますが、それが何であるかはわかりません。 MJPEG(これらのカメラがサポートしているようです)を調べましたが、このプロパティの設定に成功していません。また、OpenCVから起動した場合、どのモード(yuyv?)で実行されているかを検出できません。
考え?
3台のlogitechquickcam pro 9000カメラ(ubuntuを使用)を使用して、この正確な問題が発生しました。私は2つから読むことができましたが、3つではありませんでした。私の場合、opencvを使用していませんでしたが、メモリマップドIOを使用して、V4L2を介してカメラに直接アクセスしていました。簡単に言えば、3つのバッファを割り当てるのに十分なUSB帯域幅がありませんでした。
しかし、私は非圧縮フレームで読んでいました。フォーマットをMJPEGに切り替えるとすぐに、データは十分に小さく、3台のカメラから読み取ることができました。 libjpegを使用してMJPEGストリームをデコードしました。
OpenCVを使用して画像形式を変更する方法については調べていませんが、すべてのデータに合わせるにはMJPEGである必要があることはわかっています。
MJPEGに切り替える前は、各カメラに一度に1つずつアクセスし、次のフレームに切り替える前に1つのフレームをストリーミングすることに多くの時間を費やしていました。お勧めしません!
ほとんどの場合、ビデオキャプチャデバイスのドライバによって報告されたUSB帯域幅の競合があります。ピクセルフォーマットがYUYVであるかどうかを確認します。これは、たまたま非圧縮です。逆に、ピクセル形式がMJPG(圧縮)の場合、同じUSBチャネルに複数のデバイスを配置することができます。
v4l2-ctl -d /dev/video0 --list-formats
出力は次のようになります。
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: 'YUYV'
Name : 16bpp YUY2, 4:2:2, packed
考えられる解決策は次のとおりです。
OpenCVは、v4lまたはlibv4lのいずれかを使用するように構築でき、 v4lバージョンは圧縮形式をサポートしますが、libv4lバージョンはOpenCV2.4.11の非圧縮形式を1つだけサポートします。 (v4lの場合は autosetup_capture_mode_v4l2() を、libv4lの場合は 692行目 を参照してください。)OpenCV 3.0.0は、ここでは2.4.11を大幅に上回っていません。それでも、libv4lの非圧縮形式のみをサポートします。
エラーにlibv4l2
が記載されているため、libv4lバージョンとOpenCVが圧縮されていない状態でキャプチャされているようです。 OpenCVのv4lバージョンをビルドするには、cmakeコマンドに次のものが含まれている必要があります
-D WITH_LIBV4L=OFF
(WITH_LIBV4L
はデフォルトで有効になっています。)
帯域幅とUSBに関する注意。 USB 2.0(事実上すべてのWebカメラが使用)の帯域幅は480 Mbit/sです。 30fpsおよび24ビット/ピクセルの非圧縮での640x480は約221Mbit/sであるため、非圧縮のWebカメラでUSB2.0帯域幅をすばやく使い切ることができます。 USBホストコントローラーごとに480 Mbit/sを取得します。リストする方法については、これを参照してください answer 。 (USBハブはホストコントローラーを追加せず、マザーボード上の複数のUSBポートは通常、同じホストコントローラーに接続されます。ホストコントローラーに接続されたすべてのデバイスとハブは帯域幅を共有します。 )
必要以上のUSB帯域幅を予約するWebカメラの場合、たとえば、 VCドライバーページ に 脚注[13] があるWebカメラの場合、FIX_BANDWIDTH quirk 助けて。ただし、この癖は非圧縮形式でのみ機能します(ここでのAcornの回答でカーネルハックを行わない限り)。私の場合(Ubuntu 14.04、320x240の多くのMicrosoft LifeCam Cinemas)、OpenCVのlibv4lバージョン(ASMedia USBホストコントローラー上の4つのLifeCamsがうまく機能しました)を使用したときに癖が機能しましたが、v4lバージョンでは-使用することを確認しましたMJPEG-2番目のLifeCamからキャプチャしようとすると、すぐにVIDIOC_STREAMON: No space left on device
エラーが発生しました。 (同じマシンの場合、IntelとVIAホストコントローラーの方が優れており、それぞれがv4l用の2つのLifeCamsで動作しました。LifeCamはUSB 2.0帯域幅の48%を予約します。)
Ubuntu18.04のカーネル4.15.0-34-genericおよびgstreamer/v4lサポートでコンパイルされたOpenCV3.4を使用すると、pythonでgstreamerを使用したMJPG圧縮を使用して、パワードハブを使用して単一のUSBポートで3x720pをストリーミングできます(2xC922を使用)および1xC920カメラ-これが機能するために10fpsのフレームレートは必要ありません):
def open_cam_usb(dev, width, height):
gst_str = (
"v4l2src device=/dev/video{} ! "
"image/jpeg,widh=(int){},height=(int){},framerate=10/1,"
"format=(string)RGB ! "
"jpegdec ! videoconvert ! appsink"
).format(dev, width, height)
return cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
これは私にとって魅力として機能します
Sudo rmmod uvcvideo
Sudo modprobe uvcvideo quirks = 128
これは再起動するたびにリセットされます。これが機能する場合は、次のファイルを作成します。次の行を含むSudo vi /etc/modprobe.d/uvcvideo.conf:options uvcvideo quirks = 128
このリンクを確認してください http://renoirsrants.blogspot.in/2011/07/multiple-webcams-on-zoneminder.html
私が発見した最も有用なことの1つは、キャプチャの初期化の間にSleep(ms)呼び出しを行う場合でした。これにより、2つのWebカメラキャプチャを問題なく同時に取得できました。