ラズパイには、ラズパイ専用のカメラモジュールがあるが、音声認識用にマイクも欲しかったのでマイク内蔵のUSBカメラを使うことにした。まずはUSBカメラを接続して写真を撮影できるようにして、次に人物画像を認識する画像認識というものに挑戦してみる。ここで選んだカメラは、ピント合わせが手動というのが残念だけど、実験用にお手頃価格2,000円以下で買えた「マイク内蔵120万画素WEBカメラ BSWHD06M」。
カメラで撮影した画像を表示させたいので、Raspberry Pi3のデスクトップ(X-Window)を使えるようにする。X-WindowとVNCの組み合わせもいいけど、メンテナンス用PCがWindows10なのでリモートデスクトップ接続を試してみたい。手順はとっても簡単。ラズパイに「xrdp」をインストールして、WindowsのRDPを起動するだけ。まずは「xrdp」のインストールから。
# xrdpをインストールする。 sudo apt-get install xrdp
上記コマンドを実行するだけで「xrdp」が起動した。念のため「systemctl」コマンドで動作状況を確認する。"active(running)"になっていればOK。
$ systemctl status xrdp ● xrdp.service - LSB: Start xrdp and sesman daemons Loaded: loaded (/etc/init.d/xrdp) Active: active (running) since 土 2017-05-06 11:31:51 JST; 12min ago CGroup: /system.slice/xrdp.service ├─19406 /usr/sbin/xrdp └─19408 /usr/sbin/xrdp-sesman
次にWindowsのRDPを起動する。
ラズパイのIPアドレスは、「ip a」または「ifconfig」コマンド表示させて調べる。有線LANなら"eth0"のinet行に記載されるIPアドレスを、無線LANなら"wlan0"行に表示されるIPアドレスが接続先となる。下図の場合は、"192.168.1.14"。
2: eth0: mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000 3: wlan0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 192.168.1.14/24 brd 192.168.1.255 scope global wlan0
RDP接続のユーザ名とパスワードを入力する(デフォルトは、"pi"と"raspberry")。
ラズパイのデスクトップが表示された。
アプリケーション「guvcview」をインストールする。
$ sudo apt-get install guvcview
ラズパイのメニューでアプリを起動する([Menu]→[サウンドとビデオ]→[guvcview])。
USBカメラの画像が表示された。静止画像ファイルと動画ファイルの取得ができるようになった。
ここまでの初期設定で、購入したUSBカメラがラズパイで動くことを確認できた。次は画像認識にトライ。
Raspberry pi3で顔認識するために、画像処理ライブラリ「OpenCV」とプログラミング言語「Python」をインストールします。
$ sudo apt-get install libopencv-dev $ sudo apt-get install python-opencv
USBカメラから画像を取得するプログラムを書いてみる。"capture.py"というファイル名を作成し、以下のスクリプトを書いて保存。
#!/usr/bin/env python # -*- coding: utf-8 -*- # ファイル名: capture.py import cv2 if __name__=="__main__": # 動画ストリームを取得するためのオブジェクト定義 capture = cv2.VideoCapture(0) # 動画ストリームから最新のフレームを取得する rtn, frame = capture.read() # ファイルに出力する if( rtn == True ): cv2.imwrite( "capture.jpg", frame ) # 終了処理(ストリームを解放) capture.release() cv2.destroyAllWindows()
プログラムを実行してみる。何も画面に表示しないけれど「ls」コマンドで画像ファイルが出力されているのを確認した。
$ python capture.py $ ls capture.jpg -la -rw-r--r-- 1 pi pi 92719 5月 6 22:01 capture.jpg
プログラムを実行したディレクトリに"capture.jpg"というファイルがあった。
次は、取得した画像を元にして、顔を認識させてみる。プログラムはこんな感じ(↓)。ソース本文中の「CascadeClassifier」で選択したファイルが人物の顔認識用のデータであり、カスケードファイルと呼ぶそうです。OpenCVに同梱されているカスケードファイルは全部で17個あり、顔5個、目、耳、口などのパーツ抽出用や人物全体像などがインストールされていました。画像ファイルをグレースケールに変換してから、顔を検知しているのは、画像解析に必要なデータだけに絞り込むことで、検知速度を向上させるためである。
#!/usr/bin/env python # -*- coding: utf-8 -*- # ファイル名: capture.py import cv2 if __name__=="__main__": # Haar-like特徴分類器ファイルの読み込み。ファイルの場所は自分の環境に合わせてください。 face_cascade = cv2.CascadeClassifier('opencv-3.1.0/data/haarcascades/haarcascade_frontalface_default.xml') # USBカメラで画像を取得する。 capture = cv2.VideoCapture(0) rtn, frame = capture.read() if( rtn == True ): cv2.imwrite( "capture.jpg", frame ) # 画像ファイルをグレースケールに変換する。 gray = cv2.cvtColor( frame, cv2.COLOR_BGR2GRAY ) # 顔を検知する。 faces = face_cascade.detectMultiScale( gray ) for rect in faces: # 検知した顔を四角で囲む(rect[*]:0=x, 1=y, 2=width, 3=height)。 color = (0,255,0) # 緑色(BGR)。 thickness = 2 cv2.rectangle( frame, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), color, thickness ) # 画像ファイルを保存する。 cv2.imwrite( "capture_output.jpg", frame ) # 終了処理(ストリームを解放) capture.release() cv2.destroyAllWindows()
USBカメラで取得した画像ファイル(左:capture.jpg)と、顔認識をした結果の画像ファイル(右:capture_output.jpg)。さすがにイラストにあるフルマスクやとんがり頭のキャラクタまでは判断出来ないようだが、バイクに乗った人が認識された。目と口があれば顔と判断するのだろうか。
こちらはフリー素材集からお借りした人物写真で試したところ、複数人の画像ファイルは正面を向いているシーンだけですが、1回の画像分析で、同時に複数顔認識が出来ました。
特徴分類器ファイルを「顔」から「目」に変更して画像認識をしてみる。
# Haar-like特徴分類器ファイルの読み込み。ファイルの場所は自分の環境に合わせてください。 face_cascade = cv2.CascadeClassifier('opencv-3.1.0/data/haarcascades/haarcascade_eye.xml')
目だけ認識させることが出来ました。
他にもいろいろな特長分類器があるので試してみると面白いかもしれません。一部ですが、
haarcascade_eye_tree_eyeglasses.xml …眼鏡
haarcascade_fullbody.xml …体全身
haarcascade_upperbody.xml …上半身
USBカメラを使って画像データの取得と人物の顔認識を、わずが16ステップ(コメント文除く)のpythonプログラムで実現することが可能です。Intelが開発したオープンソースの「OpenCV」を使うことでUSBカメラで撮影した画像をファイル出力することも出来るし、それだけならわずか8ステップのpythonプログラムで実現可能。さらに「OpenCV」は、ここで試したカメラ撮影、画像認識の他、動画ファイルの入出力や色数変換、さらには機械学習や手振れ補正なども勉強すれば出来ちゃうらしい。何だか凄いですねー。
そろそろ部品も揃ってきたので、何だか凄いロボットを作ってみる。