44
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Raspberry PiとPythonで複数のUSBカメラを取り扱う方法

Last updated at Posted at 2018-11-14

Raspberry Pi Advent Calendar 2019の11日目の記事です。前日はtera1707さんのRaspberryPi3にI2Cサーマルカメラ(サーモグラフィ)をつなげて温度を画像化するでした。興味深いのでいつかやってみたいと思います。

さて。あるプロジェクトで、Raspberry Pi(以下ラズパイ)から複数台のUSBカメラで静止画を撮影する必要がありました。そのときにプログラムからカメラを指定する方法でつまづきましたので解決方法を記しておきます。

環境

Raspberry Pi 3 モデルB
ロジクール C270 HD WEBCAM(×2台)

2台のUSBカメラはラズパイに4ヵ所あるUSBのいずれかに刺さっている状態です。まずカメラがOSに認識されているかを調べてみましょう。

$ ls /dev/video*

普通なら次のようにデバイスファイルの一覧が出るはずです。ただし、video0とvideo1はそれぞれ特定のカメラとひも付いているわけではありません。

/dev/video0  /dev/video1

Pythonで撮影する

ラズパイでカメラ撮影をする方法はいくつもありますが、OpenCVライブラリをここでは利用します。なければインストールを。

$ pip install opencv-python

ではさっそくプログラムから撮影してみましょう。最小のコードを書くとこうなります。

import cv2

cam = cv2.VideoCapture(0)
ret, im = cam.read()

VideoCaptureインスタンスのreadメソッドで撮影を行いますが、コンストラクタに渡す数はカメラのインデックスであり、上記で一覧出力した/dev/video0 /dev/video1に含まれる整数がそれに該当します。ここでやっかいなのが、0と1は様々なタイミングですり変わります。つまり、0を指定すればカメラAだ、のようにできればシンプルなのですがそれは難しいようです。そこで、USBのどこに接続されているカメラかを調べることでこれを解決します。ここではLinuxでカメラに関する多機能ユーティリティツールであるVideo4Linuxを利用します。

Video4Linuxのインストール

$ sudo apt-get -y install v4l-utils

いまほしい情報は、/dev/video0 /dev/video1と2台のカメラの紐づけであり、これはいくつかの方法があります。

シンボリックリンクを利用する

ls -l /dev/v4l/by-path

シンボリックリンクにUSBのバス情報が含まれているので、矢印右辺と紐づけできます。

lrwxrwxrwx 1 root root 12 Nov 14 15:17 platform-3f980000.usb-usb-0:1.2:1.0-video-index0 -> ../../video0
lrwxrwxrwx 1 root root 12 Nov 14 15:17 platform-3f980000.usb-usb-0:1.4:1.0-video-index0 -> ../../video1

v4lを利用する

次の方法は、以下のコマンドを利用します

v4l2-ctl --list-devices

すると、以下のようにデバイス情報、バス情報、インデックスをペアとして、一覧を出力してくれます。

UVC Camera (046d:0825) (usb-3f980000.usb-1.2):
        /dev/video0

UVC Camera (046d:0825) (usb-3f980000.usb-1.4):
        /dev/video1

Pythonからsubprocessで呼んでみよう

subprocessを使えばPythonから上記の情報を得ることができます。

import subprocess

cmd = "v4l2-ctl --list-devices"
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
ret = p.communicate()[0]
ret = ret.split("\n")
ret = filter(None, ret)
print(ret)

出力は次の通り

['UVC Camera (046d:0825) (usb-3f980000.usb-1.2):', '\t/dev/video0', 'UVC Camera (046d:0825) (usb-3f980000.usb-1.4):', '\t/dev/video1']

おまけ:カメラのシリアル番号を取得する

上記出力のデバイス情報である046d:0825を使って、カメラのシリアル番号を取得することができます。

$ sudo lsusb -v -d 046d:0825 | grep -i serial

以下のような8桁のシリアル番号が取得できるため、使いようによっては便利かと思います。

  iSerial                 2 10763230
  iSerial                 2 B9D5A4E0
44
44
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?