読者です 読者をやめる 読者になる 読者になる

RaspberryPiでUSB接続のWebカメラを使ってみる

RaspberryPi コンピュータ python 電子工作 開発

RaspberryPiでUSB接続のWebカメラを使ってみる

以前はRaspberryPi専用のカメラモジュールを接続していました。

uepon.hatenadiary.com

今回は一般に販売されているUSB接続のWebカメラを接続してみます。

家には2つのWebカメラがありました。

www.logicool.co.jp

www.microsoft.com

ロジクールのものはHDでの動画撮影もできてコンパクトに折りたためるのでなかなかいい感じです。 MicrosoftのLifeCamもカメラは悪くないのですが、足の部分のラバーっぽいのが固定しにくかったり、劣化したりしそうなので微妙です。こちらは720pでの撮影ができます。

今回はこちらのブログを参考にしてみました。

blog.livedoor.jp

カメラを接続してみる

とりあえず、そのまま接続してみます。

以下がUSBカメラを接続する前のlsusbの状態です。

$ lsusb
Bus 001 Device 004: ID 0411:01ee BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM2 Wireless LAN Adapter [Ralink RT3070]
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

キャプチャデバイスも存在していません。

$ ls /dev/video*
ls: /dev/video* にアクセスできません: そのようなファイルやディレクトリはありません

接続すると以下のような状態に変化します。

【hd-webcam-c615の場合】

$ lsusb
Bus 001 Device 005: ID 046d:082c Logitech, Inc.
Bus 001 Device 004: ID 0411:01ee BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM2 Wireless LAN Adapter [Ralink RT3070]
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

以下が追加されます。

Bus 001 Device 005: ID 046d:082c Logitech, Inc.

接続して認識されると

$ ls /dev/video*
/dev/video0

ビデオキャプチャバイスも生成されています。

【ifecam-cinemaの場合】

$ lsusb
Bus 001 Device 007: ID 045e:075d Microsoft Corp. LifeCam Cinema
Bus 001 Device 004: ID 0411:01ee BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM2 Wireless LAN Adapter [Ralink RT3070]
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ ls /dev/video*
/dev/video0

以下が追加されています。デバイスナンバー(Deviceの部分の数字)が連番になっていませんが、抜き差しするとこの部分が変更されるようです。

Bus 001 Device 007: ID 045e:075d Microsoft Corp. LifeCam Cinema

ともに正常に認識されている様です。

ちなみに両方を接続すると以下の用になります。

$ lsusb
Bus 001 Device 006: ID 045e:075d Microsoft Corp. LifeCam Cinema
Bus 001 Device 005: ID 046d:082c Logitech, Inc.
Bus 001 Device 004: ID 0411:01ee BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM2 Wireless LAN Adapter [Ralink RT3070]
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ ls /dev/video*
/dev/video0  /dev/video1

Xの環境で使用してみる。

まずはLogicoolのhd-webcam-c615を接続してテストをしてみます。(これが今回の混乱の原因でした。)

Xの環境でカメラが使用できるか確認します。

カメラの確認するソフトは色々ありますが、今回はguvcviewを使用してみました。

インストールは簡単で

$ sudo apt-get install guvcview

でOKです。あとは

$ guvcview &

で起動して、以下のように表示されていればOKです。

f:id:ueponx:20170122150741j:plain

動作に全く問題はありません。昔はともかく、最近のカメラはHD画質も行けるため、良い画質です。

以前のエントリでKINECTを使用していましたが、そのときに使用したcamoramaでも同様です。

$ camorama -d /dev/video0 &

uepon.hatenadiary.com

f:id:ueponx:20170122154355p:plain

pythonからOpenCV経由でキャプチャしてみる

実際にはpythonからのキャプチャを行いたいのでOpenCVのインストールを行います。KINECTのエントリでもインストールしていますが、復習です。

$ sudo apt-get install python-opencv

これでインストール完了です。 最近知ったのですが、モジュールのインストールの確認だけであれば、わざわざインタラクティブシェルを起動しなくても、以下のようなコマンドで問題無いようです。

$ python -c 'import cv2'

あとはpythonからキャプチャを行います。

$ python
Python 2.7.9 (default, Sep 17 2016, 20:26:04)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> c = cv2.VideoCapture(0)
>>> r, img = c.read()
>>> cv2.imwrite('capture.jpg', img)
True
>>>

一応、Trueが返されているので成功してそうです。キャプチャしたphoto.jpgを 確認すると

f:id:ueponx:20170122160412j:plain

あれ、真っ黒?

処理もデバイスもうまく動作しているのですが、何故かキャプチャがうまくいかないようです。 とりあえず、インタラクティブシェルでは特定が難しいのでプログラム化します。

カメラ特有の設定値、解像度変更、もしかして非同期的な処理があってファイルI/Oが終わるまえに終わってしまったなどを 考慮してコーディングして確認をしてみました。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import cv2

c = cv2.VideoCapture(0) #1 
r, img = c.read() #2
cv2.imwrite('capture.jpg', img) #3
c.release() #4

このファイルでも画像は真っ黒のままでした。予想としては#2の処理が遅くなっているのかなと思い、OpenCVの処理を行っている各行間にtime.sleep(3)を挿入してみたのですが、やはり結果は同じでした。処理に時間がかかっていて問題があるというわけでは内容です。

そこで、ダメ元で以下のように

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cv2
import time

cap = cv2.VideoCapture(0)
while(cap.isOpened()):
    print('capture process')
    cap.read()
    r, img = cap.read()
    path = 'capture.jpg'
    cv2.imwrite(path, img)
    if(r == True):
    break;
cap.release()

無限ループを回して、何回もキャプチャを行ってみるという処理にしてみました。 このプログラムを動作させ、Ctrl+Cで中断すると無事にキャプチャができていました。

f:id:ueponx:20170122163047j:plain

そこで、やっと気が付きました。どうも起動後初回のキャプチャでは画像が真っ暗になるという特徴があるようです。 MicrosoftのLifeCamではどうなるかなと思い、変更すると、画像は真っ暗にはならず問題ありませんでした。

あくまでも予想ですが、Logicoolのhd-webcam-c615では初回キャプチャは空振ってしまうので、2回目以降を使用する必要があるようです。 この予想をもとに以下のようなコードに変更しました。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import cv2

c = cv2.VideoCapture(0)
c.read()
r, img = c.read()
cv2.imwrite('capture.jpg', img)
c.release()

2回目のキャプチャをファイルに保存するという変更です。 これによりキャプチャ結果も問題がなくなりました。結果からしか判断できませんが、そういうカメラの特徴があったのだと思います。

おわりに

問題なくpythonをつかってOpenCV経由でキャプチャができました。初回のキャプチャがうまくいかないというカメラもあるのだなという教訓が得られたので、今回はよしとします。以降はOpenCVを使用したトラッキングなどをやってみたいと思います。