2019年9月2日月曜日

本書の演習をウェブカメラで実行する方法

1. はじめに

本書では、Raspberry Piで機械学習の演習を行います。その際、手の形を認識する演習に用いるカメラとしては、Raspberry Pi専用のカメラモジュールを使う方針を取りました。

本ページでは、カメラモジュールではなく市販のウェブカメラで演習を行う方法を紹介します。こちらで動作検証したカメラはロジクール社のC270およびC920です。

本ページでは「××社の○○と言うカメラで動くか」という質問や「××社の○○と言うカメラで動くようにして欲しい」という要望には応えることができません。

カメラが異なることによるそのようなトラブルを避けるために、本書ではRaspberry Pi専用のカメラモジュールを使用する方針としたのだったからです。 本ページは上級者向けのサービスという位置づけとしますのでご理解ください。

なお、ウェブカメラではRaspberry Pi専用のカメラモジュールに比べて手の形の認識率が悪いようです。 それは、ウェブカメラではホワイトバランスの自動調整の無効化ができないためとおもわれます。その件も合わせてご了承ください。

2. 手順

それではターミナルアプリケーションLXTerminalを開き、本書のサンプルファイル(「ml-」で始まるファイル)が存在するディレクトリに移動してください。 サンプルファイルをホームディレクトリに展開した方は移動の必要はありません。bluebacksディレクトリに展開した方は下記のコマンドを実行するのでした。
cd bluebacks
なお、本ページで紹介するプログラムは、「ml-」で始まる本書のサンプルファイルと同じ位置にないと動作しませんので注意してください。

次に、下記の3つのコマンドを順に実行して、必要なファイルのダウンロードと展開を行ってください。コマンドはコピー&貼り付けで実行することを推奨します。展開後はダウンロードした圧縮ファイルは不要となるので削除しています。
wget https://github.com/neuralassembly/raspi/raw/master/mlbb-webcam.zip
unzip mlbb-webcam.zip
rm mlbb-webcam.zip
なお、展開されるファイルの名前は既存のサンプルファイルとは異なりますので、サンプルファイルが上書きされることはありません。展開により現れるファイルは下記の通りです。Pythonプログラムは、ファイル名の末尾が全て「-webcam.py」で終わっていることに注意してください。 なお、TensorFlow 2 用の学習済ファイルである ml-digits-cnn-tf2.h5 と ml-hand-cnn-tf2.h5 は既存のファイルが展開時に上書きされることがあるかもしれませんが、上書きして構いません。
ml-08-01-cameracheck-webcam.py
ml-08-02-binary-webcam.py
ml-08-04-recognition-webcam.py
ml-09-01-janken-webcam.py
ml-09-02-janken-shorten-webcam.py
ml-10-08-hand-cnn-load-webcam.py
ml-10-09-janken-deep-webcam.py
ml-10-10-janken-deep-shorten-webcam.py
ml-digits-cnn.h5
ml-hand-cnn.h5
あとは、以下に従って実行します。

3. 実行

まず、実行時には下記に注意してください。
  • 「Raspberry Piの設定」で「インターフェイス」の「カメラ」は無効にする必要があります(現在この設定はありません)。
  • ホワイトバランスの無効化ができないので認識率は良くありません。太陽光下よりは蛍光灯下の方が認識しやすいように思われます。
  • 手が白く塗りつぶされた状態が実現されるよう、書籍p.267の対処法、および「書籍で用いたコマンドおよび追加情報」の「p.257 ml-08-02-binary.pyが手の形を反映していない場合」を参考に調整を行ってください。
以上に注意しつつ、下記のコマンドでそれぞれのファイルを実行します。
python3 ml-08-01-cameracheck-webcam.py

python3 ml-08-02-binary-webcam.py

# 以下、ml-08-03 で学習済データを result.pkl に保存した場合
python3 ml-08-04-recognition-webcam.py result.pkl

python3 ml-09-01-janken-webcam.py result.pkl

python3 ml-09-02-janken-shorten-webcam.py result.pkl

# 以下は、TensorFlow 2 系の利用が前提のファイルです
python3 ml-10-08-hand-cnn-load-webcam.py ml-hand-cnn.h5

python3 ml-10-09-janken-deep-webcam.py ml-hand-cnn.h5

python3 ml-10-10-janken-deep-shorten-webcam.py ml-hand-cnn.h5
なお、Raspbian Busterを用いた場合、プログラム起動時に下記のエラーが出て実行に失敗することがありました。その場合、もう一度プログラムを実行し直すと正常動作することが多いでしょう。
VIDEOIO ERROR: V4L: index 0 is not correct!
OpenCV Error: Assertion failed ((scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F)) in cvtColor, file /build/opencv-L65chJ/opencv-3.2.0+dfsg/modules/imgproc/src/color.cpp, line 9815
Traceback (most recent call last):
  File "ml-08-04-recognition-webcam.py", line 70, in 
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.error: /build/opencv-L65chJ/opencv-3.2.0+dfsg/modules/imgproc/src/color.cpp:9815: error: (-215) (scn == 3 || scn == 4) && (depth == CV_8U || depth == CV_32F) in function cvtColor

また、プログラム実行中に下記の警告が大量に出る場合がありました。
Corrupt JPEG data: 2 extraneous bytes before marker 0xd7
その場合、実行していたコマンドが下記だった場合、
python3 ml-08-04-recognition-webcam.py result.pkl
これを下記コマンドで代用してください。
stdbuf -o0  python3 ml-08-04-recognition-webcam.py result.pkl  2>&1 |grep -v JPEG
他のコマンドだった場合も同様です。