Raspberry Pi3でWebカメラ(USB接続)の制御

Pocket



つい先日Raspberry Pi3でLチカをやってみたわけですが、抵抗が手元に無いのでLEDが壊れる前にテストは一旦中断することにしました。
注文した抵抗が届くまでまだしばらく時間がかかりますので、その間はジャンク屋で購入した後ろくに使わず押し入れに放り込んであったUSB接続のwebカメラを制御できるかテストしたいと思います。

Webカメラの認識チェック

今回使うUSBカメラは数年間通電すらしていなかったので、とりあえずは以下コマンドでUSBデバイスとしての認識チェックをしてみましょう。

lsusb

せっかくなので、USBカメラを繋がない状態(電源ケーブルだけを繋いでいる状態)と繋いだ状態で比較してみました。
最初の[lsusb]ではusbデバイスが3つしか表示されていませんが、USBカメラを繋いだ後に実行した2回目の[lsusb]では[Z-Star Microelectronics Corp. Venus USB2.0 Camera]が追加されました。とりあえず認識はしているようです。
raspberrypi3_usb_camera_01

webカメラの映像確認

さきほどlsusbでwebカメラがUSBデバイスとして認識されていることができましたので、続いては映像が表示されるかチェックしましょう。
といってもUbuntuMATEにはデフォルトでwebカメラを制御するソフトがインストールされているので映像のチェックは簡単です。
GUI環境でRaspberry Pi3にアクセスし、左上の「アプリケーション」->「サウンドとビデオ」->「guvcview」を起動しましょう。
raspberrypi3_usb_camera_02

「guvcview」を起動すると、以下スクリーンショットのようにすぐにwebカメラの映像が画面上に表示されます。
光量が足りていないのと、そもそもジャンク屋で手に入れたwebカメラということもあって写りはいまいちですが、ちゃんと動いていることが確認出来ましたので良しとしましょう。
raspberrypi3_usb_camera_03

USBカメラを制御できるツールの検索 その1(libgphoto2)

USBカメラの生存確認が済んだところでpythonからwebカメラを制御する方法を探ってみたいと思います。
まずは以下コマンドでさくっと使えそうなものが無いか検索してみましょう。

sudo apt-cache search usb camera python

コマンドの実行結果

python-piggyphoto – Python bindings for libgphoto2

コマンド実行の結果、上の通りちょうどよいパッケージが存在しているようなので、以下コマンドでインストールしてカメラ制御をテストしたいと思います。

sudo apt-get install python-piggyphoto

インストールが完了したら、こちらを参考に以下のようなテストコードを書き、[~/Documents/raspberrypi/camera.py]として保存します。

コードを保存したら以下コマンドで実行してみます。

sudo python ~/Documents/raspberrypi/camera.py

うーん、なんだかうまくいっていないみたいです。
以下のように、コマンドを実行すると[libgphoto2error]が発生しています。どうやらカメラを認識できていないみたいですね。カメラを認識出来てさえいれば画像ファイルができているはずなんですが・・・
うん、わからん。認識してないんじゃどうにもなりませんね。
ざっと調べた間感じ、たぶんcanonやnikonのデジタル一眼なんかは制御できそうな気がするんですが・・・

Traceback (most recent call last):
File “/home/user/Documents/raspberrypi/camera.py”, line 4, in
c = piggyphoto.camera()
File “/usr/lib/python2.7/dist-packages/piggyphoto/__init__.py”, line 222, in __init__
self.init()
File “/usr/lib/python2.7/dist-packages/piggyphoto/__init__.py”, line 239, in init
check(ans)
File “/usr/lib/python2.7/dist-packages/piggyphoto/__init__.py”, line 205, in check
raise libgphoto2error(result, message)
piggyphoto.libgphoto2error: Unknown model (-105)

USBカメラを制御できるツールの検索 その2(SimpleCV)

我が家のwebカメラはlibgphoto2では動かないことがわかりましたので、別の方法を・・・と調べていたところ、simplecvという画像なんかを扱うオープンソースライブラリがあるようです。
早速インストール・テストしたいと思います。

と言いつつもSimpleCVはaptコマンド一発ではインストールできないようなので、debパッケージを手動でダウンロードの後aptでインストールしようと思います。
まずはSimpleCV公式のダウンロードページにアクセスし、ウィンドウ中央にある「SimpleCV Version x.x Superpack」と書かれたリンクをクリックしてdebファルをダウンロードします。
raspberrypi3_usb_camera_04

debパッケージのダウンロードが完了したら、端末から以下コマンドを実行します。

sudo gdebi ~/Downloads/SimpleCV-1.3.deb

ディレクトリ名を変更していない場合はパスが変わるのでこんな感じです。

sudo gdebi ~/ダウンロード/SimpleCV-1.3.deb

コマンドを実行すると、以下のように本当にインストールするか確認メッセージが表示されるので、[y]で[Enter]キーです。

Do you want to install the software package? [y/N]:

インストールが完了したら、[~/Documents/raspberrypi/camera.py]をSimpleCVの動作テスト用に以下のように書き換えます。

コードを保存したら以下コマンドで実行してみます。

sudo python ~/Documents/raspberrypi/camera.py

ERROR:
Traceback (most recent call last):
File “/home/user/Documents/raspberrypi/camera.py”, line *, in
cam.live()
File “/usr/lib/pymodules/python2.7/SimpleCV/Camera.py”, line 349, in live
d = Display(i.size())
File “/usr/lib/pymodules/python2.7/SimpleCV/Display.py”, line 158, in __init__
scvLogo = SimpleCV.Image(“simple”)scale(32,32)
Fime “/usr/lib/pymodules/python2.7/SimpleCV/ImageClass.py”, line787, in __init__
self._pil = pil.open(self.filename).convert(“RGB”)
File “/usr/lib/pythone2.7/dist-packages/PIL/Image.py”, line 2288, in open
fp = builtines.open(fp, “rb”)
IOError: [Errno 2] No such file or directory: ‘/usr/lib/pymodules/python2.7/SimpleCV/sampleimages/simplecv.png’

・・・
うん、わからん。
pythonのコード書くの初めてだし、サンプルコードでエラー吐かれてもなぁ。pngファイルが無いのが直接的な原因なんでしょうけど、このpngファイルの参照にはどんな意味があるんでしょう。
よくわからないのでエラーメッセージで調べてみたところ、こちらに情報がありました
コードは確認していませんが、実行の際やっぱりSimpleCV内部で[/usr/lib/pymodules/python2.7/SimpleCV/sampleimages/simplecv.png]を参照しているらしいのですが、.debファイルでSimpleCVをインストールした場合には、この該当pngファイルが存在していないためにエラーが発生しているようです。
で、このエラーを解消にするには先ほどの情報元にあるとおり、該当ディレクトリにsimplecv.pngを配置すればOKのらしいです。

というわけで、まずは以下コマンドでディレクトリを作成します。

sudo mkdir /usr/lib/pymodules/python2.7/SimpleCV/sampleimages/

続いてGitHubのSimpleCVのページに置いてある[simplecv.png]をダウンロードします。
raspberrypi3_usb_camera_06

[simplecv.png]をダウンロードしたら、以下コマンドで先ほど作成したディレクトリの中にpng画像をコピーします。仮にsimplecv.pngがダウンロードディレクトリに存在している場合のコマンドは以下のような感じになります。

ディレクトリ名を日本語のまま利用している場合のコマンドはこちら

sudo cp ~/ダウンロード/simplecv.png /usr/lib/pymodules/python2.7/SimpleCV/sampleimages/simplecv.png

ディレクトリ名を英語に変更している場合のコマンドはこちら

sudo cp ~/Downloads/simplecv.png /usr/lib/pymodules/python2.7/SimpleCV/sampleimages/simplecv.png

[simplecv.png]の配置が完了したら、あらためて[camera.py]を実行してみます。

sudo python ~/Documents/raspberrypi/camera.py

ちょっとぼけて映ってはいますが、先ほどと違ってwebカメラの映像が画面上に表示されました。
今度はどうやらうまく行ったようです。何でも試してみるものですね。
raspberrypi3_usb_camera_07
raspberrypi3_usb_camera_08

Webカメラの映像をjpg画像として保存する

とりあえずwebカメラのlive映像を画面上に出力することが可能になりましたので、今度はwebカメラの映像をjpgファイルとして保存してみたいと思います。
今度はこんなコードを書いて[~/Documents/raspberrypi/takePicture.py]として保存します。
このコードを実行する際は、jpgファイルの保存パスをご自分の環境に合わせて変更してください。

コードを書き終わったら、以下コマンドで実行します。

sudo python ~/Documents/raspberrypi/takePicture.py

jpgファイルが作成されたので一見うまくいったように思ったのですが・・・実際に作成されたjpgファイルは以下のようなものでした。
raspberrypi3_usb_camera_09

うちのWebカメラだけの可能性もありますが、先ほどの[camera.py]を何度か実行してその様子を観察していると、コードが実行されてWebカメラに接続した瞬間ノイズが走り、その後1秒ほどすると映像が安定するようです。
というわけで、[~/Documents/raspberrypi/takePicture.py]を少し変更すれば良い映像が得られそうです。ついでに撮影画像のファイル名を撮影日時に変更しましょう。せっかくなので撮影した画像を一回画面に表示させてみましょうか。

コードを変更したら再度コマンドで実行します。

sudo python ~/Documents/raspberrypi/takePicture.py

Webカメラのスペックの影響か、ピントがボケ気味ではありますが先ほどのようなノイズは見られません。
さらにファイル名も日時になったので、毎秒コマンドを実行できるようにもなりました。
raspberrypi3_usb_camera_10

Webカメラの撮影時にエラーが発生したらgmailでメール通知するようにしてみる

先ほどのコードでWebカメラの映像をjpg画像として保存することが可能になりましたが、このままではエラー処理が一切無いので、トラブルが発生したかどうかは目視チェックが必要です。
それでは面倒なので、撮影時に何かしらのエラーが発生したら、gmailでエラーが発生したことを通知するようにしたいと思います。
なお、pythonでgmailを使うコードは、こちらこちらを参考にさせていただきました。
まず、先ほどの[~/Documents/raspberrypi/takePicture.py]を以下のように書き換えます。
(テストのため、40行目の[raise Exception(“error”)]で意図的にエラーを発生させています。運用時はこの行をコメントアウトします。)

コードを変更したら再度コマンドで実行します。
(このまま実行される際は、8行目のパスを実行する環境のパスに変更、9行目、10行目はお持のgmailアカウントの情報に変更してください。)

sudo python ~/Documents/raspberrypi/takePicture.py

ぱっと見動きそうな感じはするのですが、[SMTPAuthenticationError]が発生してしまいました。
私の環境はgmailに2段階認証を設定しているので、恐らくそれが原因かと思います。

save image
ERROR:
Traceback (most recent call last):
File “/home/user/Documents/raspberrypi/takePicture.py”, line 50, in
send_gmail(from_addr, to_addr, msg)
File “/home/user/Documents/raspberrypi/takePicture.py”, line 26, in send_gmail
s.login(mailAddr, mailPass)
File “/usr/lib/python2.7/smtplib.py”, line 622, in login
raise SMTPAuthenticationError(code, resp)
SMTPAuthenticationError: (534, ‘5.7.9 Application-specific password required. Learn more at\n5.7.9 https://support.google.com/accounts/answer/185833 fk10sm28355453pab.33 – gsmtp’)

2段階認証を外せば良いんでしょうが、過去「不正なログインがブロックされました」という通知を受け取ったことがある(原因は中国からの不正なログイン試行でした)身としては不正なアクティビティ2段階認証は外したく無いということもあり、アプリパスワードを設定することで対応したいと思います。アプリパスワードを設定するには、設定ページへアクセスし、「アプリパスワード」をクリックします。
raspberrypi3_usb_camera_11

アプリパスワードの設定ページが表示されたら、「端末を選択」「アプリを選択」を任意の項目に選択して「生成」ボタンをクリックします。
ちなみに今回は、「端末を選択」は「その他(名前を入力)」にして「raspberrypi3」、「アプリを選択」は「メール」を選択しています。
raspberrypi3_usb_camera_12

画面が切り替わると自動生成された16桁のパスワードが表示されますので、これを先ほどの[takePicture.py]の10行目にセットして、完了ボタンをクリックします。
ちなみに、見やすいように4桁ごとに空白がありますが、この空白はスペースではありません。あくまで見やすいように間を空けてあるだけです。
raspberrypi3_usb_camera_13

gmailのアプリ用パスワードの設定が完了したら、再度コマンドを実行してみましょう。
40行目で意図的に発生させているエラーによって設定したアドレス宛てにメールが届いているかと思います。

sudo python ~/Documents/raspberrypi/takePicture.py

これで一応メール送信部分のコードが動作していることが確認できましたが、もう少しだけエラーのテストをば。
カメラが存在しない場合は、カメラが初期化されるタイミングでエラーが発生しますので、今度は40行目のコードの行頭に「#」を入れてコメントアウトした後、Raspberry Pi3からUSBカメラを物理的に外した状態で再度コマンドを実行してみましょう。

sudo python ~/Documents/raspberrypi/takePicture.py

端末上に警告メッセージが表示されると共に、メール通知が入ることが確認できました。
Raspberry Pi3がダウンしてしまえばアウトですが、撮影のタイミングで何かトラブルが発生したらわかるので、趣味で使う分にはまぁいいかな。

端末上に表示される警告メッセージ

WARNING: SimpleCV can’t seem to find a camera on your system, or the drivers do not work with SimpleCV.

メールで通知されるエラーメッセージ

error occurred in YYYYmmddHHMMSS
Camera instance has no attribute ‘threaded’

Webカメラの映像を動画として保存する・・・のはまた今度ということで

とりあえずではありますが、Webカメラの映像を取り込んでjpg画像で保存することができるようになりましたので、次のステップとして動画の保存を試して・・・なんて考えていたのですが、ちょうど我が家に注文していた抵抗やら何やらが届きました。とりあえず私がやりたいのは定点撮影だけで、その目的を達成するpythonコードは最低限のレベルではあるものの完成しましたので、今回はこんな感じで一旦ストップしたいと思います。
一応海外の方が動画を撮影するコードを公開してくださっているので、もし動画撮影のサンプルコードを探している方はこちらこちらを参考にしていただければと思います。

pythonって今まで名前を認識しているだけだったのですが、こうやって実際に触ってみると割ととっつきやすいですね。もっと前から触れてみれば良かったなぁ。
あ・・・何気にこの投稿を最初から見返してみたら書き始めから1週間も経ってるじゃん。ちょっとのんびり書き過ぎかなぁ。まぁ趣味でメモ代わりに書いてるだけだしそんなことはどうでもいいか。

コメントを残す

メールアドレスが公開されることはありません。