スキップしてメイン コンテンツに移動

サーボモーター、顔を追う。Python + 顔認識 + Firmata

 

背景

今回はHaLaKeで行われている小中学生向けプログラミング教室用にPythonとOpneCVを使って楽しく学べるものを作ろうと思います。
OpenCVと聞くと個人的に何をやっているかわからないことが多々ありますが、今回は簡単にできてかつ「OpenCVと言えば!...」なんて言われている(諸説あり)、顔認識を使っていきたいと思います。顔認識の記事はたくさんあるので特に紹介はしませんがチュートリアルなども出ていてわかりやすいのでそちらを参考にしてください。 しかし,顔認識だけでは味気ないので今回はFirmataを使って顔認識と連動してサーボモータを動かしてみます。
楽しく学べるものを作っていきたいので何かのソフトウェア的なイベントに対して現実のものが動くと楽しんでもらえるのではないかと考えています。
以前、Firmataを使ってPythonからArduinoを操作(記事は前提条件から)をしてみたのでこれと顔認識を組み合わせて作っていきたいと思います。

環境

前提条件

必要なもの

  1. arduino(今回手元にあったUNOを使いますが、nanoや互換機などでも可、しかし使い方に関しては説明を省く)
  2. ジャンパワイヤ
  3. マイクロサーボ SG-90
  4. 通信用ケーブル(arduinoとPCに合う端子のケーブルを各自用意)
  5. テープ(PCにサーボモーターを取り付ける用)

前準備

パッケージのインストール

Pythonがインストール済みとして進めます。
それでは、最初にも説明したように今回はOpneCVとFirmataを使っていくのでPython用のパッケージをそれぞれインストールしていきます。
下記のコマンドを実行していきます。

pip install opencv-python
pip install pyfirmata 

この二つがインストールされれば動くと思います。私の環境ではエラーが一切出なかったので説明することはありませんが、大方この二つのインストール時には特にエラーは出ないと思います。初心者の方でエラーが出るとしたらpipのバージョンが低かったりなどなのでエラー内容を読んでそれに従うか、内容をコピペで検索すれば解決できます。

pip list

で確認しインストールした二つが入っていれば完了です。

こんな感じ。

Arduinoの準備

前提条件で読んでおいて欲しい記事の【ArduinoにFirmataを書き込み】の項を読んで各自設定して下さい。
その際、Arduinoがつながっているシリアルポートの名前をメモしておいて下さい。
そして前提条件の記事ではボード情報がArduino nanoになっているので各自で使用しているArduinoのボード情報に合わせて書き込んでください。

  • 注意:この操作を忘れると動作しないので必ず行って下さい。

ハードウェア

 UNOの場合はこんな感じになります。互換ボードの場合でも同じピンにつなげば動いてくれます。
  PCのウェブカメラの真上に来るように裏からサーボモータを貼り付けました。(適当) 

ちなみにD12ピンを使ったのは個人的に好きな数字だからです。

ソフトウェア

今回はOpenCVインストール時に入っている顔認識用のカスケードファイルを指定するのもいいのですが環境によってまちまちなのと説明が難しくなってしまうのでGitHubから今回は使うファイルをダウンロードできるようにしました。

github.com

クローンするかzipファイルでダウンロードしてください。

OpenCVインストール時に同梱されている中からカスケードファイルを使いたい場合はこちらの記事がとても参考になりました。

naporitan.hatenablog.com

書き換えの説明をします。 5行目あたり

port = 'COM15'                      #ポートの設定

私の場合はCOM15でしたが、前準備の項でシリアルポートの名前をメモしていると思うのでそれに書き換えてください。
私が作ったプログラムには無駄が多いと思います。特にサーボモーターの角度を画面座標から割り出す作業は適当なので48行あたり

pin1.write(ang)

引数に0~180の角度が入るようにそれぞれの環境に合わせて書き換えた方がきれいに動くと思います。

26行あたり

faces = face_cascade.detectMultiScale(frame_gray, minSize=(120,120))

誤認識を減らすためにminSizeを120に設定していますが環境によって変わる可能性もあるので認識されにくい場合や誤認識される場合は適度に変えてください。

15,16行あたり

#/arduinoのmap関数みたいなものを実装
def map(value:float, before_MIN:float, before_MAX:float, after_MIN:float, after_MAX:float) -> float:
    return after_MIN + (after_MAX - after_MIN) * ((value - before_MIN) / (before_MAX - before_MIN))
#/

Arduinoにはmap関数という、とある範囲の値をまた別の範囲の値に置き換えてくれる関数がありますがPythonにはないようなので下記の参考にさせて頂いたサイトをもとに追加しました。
画面座標の範囲をサーボモーターの角度に置き換えるときに必要です。
map関数の作成についてはこちらを参考にさせて頂きました。

qiita.com

他プログラムの内容はコメントで説明しているので説明は省きます。

(余談)おまけの項で紹介するFirmataのテストプログラムではアナログピンからのサーボ制御が出来るようですが、自前のプログラムからの動かし方がわからないので本格的に使う場合は調べる必要がありそうです。

  • 注意:今回のプログラムはカメラに一人だけ写っていることを想定しているので二人以上写ってしまうと予期しない動作をするので気を付けてください。今回はプログラムをなるべく簡潔にするために改善しません。

動作確認

保存したディレクトリまでコマンドプロンプトを移動して実行しましょう。

python face_follow.py

そうするとこんな感じになります。

上記のgifでは顔が塗りつぶされていますが見た目を見やすくすることと自分で顔を出すのが恥ずかしかったので塗りつぶしました。GitHubに載っているコードでは塗りつぶしはされていません。

サーボモーターの角度を求める式は決め打ちで適当なので中心らへんではちゃんと追従してくれている雰囲気はありますが、両端になるといまいち追従してくれていないことがわかります。 環境に合わせて決め打ちしてある値を変えないといけないのは少し面倒なので時間があれば書き換えてもよさそうです。(必ずやるとは言っていない。)

おまけ

以前は紹介しなかったのですが公式が出しているFirmataのテストが出来るプログラムがあります。 下記URLにアクセスし、Firmata Test Programの項の下にそれぞれのOSごとに記載してあるので対応するものをダウンロードし実行してみてください。StandardFirmataが書き込まれたArduinoが繋がっているポートを指定するとそれぞれのピンをGUIで操作することが出来ます。

firmata.org

今回は顔認識だけ紹介しましたが他にも笑顔、目、鼻なども公式からカスケードファイルがあるのでダウンロードするかインストールされているのを見つけるかしてカスケードファイルを入れ替えてみるのも面白そうです。それぞれの使い方はこちらのサイトがわかりやすく参考にさせて頂きました。

symfoware.blog.fc2.com

公式GitHubのカスケードファイル一覧はこちら

github.com

まとめ

  • Arduinoのmap関数がないのは割と不便
  • 動画内の座標とサーボモータの角度の連動精度を出すにはむずかしそう
  • 同じようなことをラジコンカーやドローンでやっている動画をみつけたのでやってみたい
  • 顔の近さ(顔と判定された四角形の大きさ)でターゲットを変えられたら複数人での判定が安定しそう

コメント

このブログの人気の投稿

Phaser3 + Typescriptを使ってRPGゲームの基礎を作ろう!その2

前回の記事 に引き続きPhaser3+Typescriptを使って RPG の基礎を作っていきます。 この記事は前回の記事を呼んだ前提で説明していきますので、ぜひそちらを先に読むことをお勧めします。 また、今回の記事は前回よりも難易度と内容量が上がっていますが、記事の最後に作業後の リポジトリ のリンクがありますので、そちらを先にダウンロードしてそちらと比較しながら学習することができます。 前回まで作成した状態のプログラムが以下の リポジトリ からダウンロードできますので前回まででうまくいっていない方は参考にしてみてください。 github.com 最終目標(再掲) ・Phaser3とTypescriptで RPG ゲームの基礎を作る。 ・Phaser3をTypescriptで使う方法を学ぶ ・Phaser3の使い方を学ぶ 今回の目標 ・ゲームの作り方の断片を知る ・キャラの表示できるようにする ・キャラを移動できるようにする ・当たり判定をつける ・ NPC の追加してみる ・話しかけられるようにする 開発前提(再掲) ・Nodejsの環境・知識がある ・ Javascript ・Typescriptがある程度かける ・当ページ紹介の環境を試す場合はgit・ github の知識がある 使用した主要Nodeモジュール(再掲) ・typescript(Typescriptの コンパイル 用) ・phaser(フロントの Javascript 用ゲームライブラリ) ・live-server(ソースを監視してブラウザのページをリロード) ・ts-loader(webpackがTypescriptをバンドルする用)webpack(言わずと知れたモジュール依存をいい感じに解決しバンドルする) ・webpack- cli (webpackを コマンドライン で使用するのに必要) 注:各Nodeモジュールバージョンは後述 当ブログ仕様の画像素材の注意点 当ブログで使用する画像素材は『 ピポヤ倉庫 』より許可なしで無償再配布・改変が認められたものを改変して作成されたものです。 中には許可なく再配布・改変してはいけない素材もインターネット上には多く存在するのでそれらを使用するときは十分に規約を呼んでから使用しましょう。 1. キャラの表示 想定画面 今回は、はじめにキャラつまり操作

M5Stackで、においセンサー(TGS2450)を使ってみる。(LCDに表示編)

今回は、においセンサー(TGS2450)から取得したデータをM5Stackの LCD にグラフ表示をしていきます。 今回主に使用したもの M5Stack 10Ω抵抗 5本 Pch  MOSFET  2SJ334(スイッチとして利用) M5StackSideBB(ブレッドボード) M5Stackのピンはそのままだと配線するとき手間がかかるかと思いますので、今回はM5StackSideBBを利用しました。 ブレッドボードも付いているので、手軽に電子工作できるので個人的にオススメです。 SideBB for M5Stack www.switch-science.com 諸注意 本ブログのプログラムはArduinoIDEまたはPlatformIOでM5Stackの開発ができる状態であること前提のものですので、各自導入をお願いします。 過去に Windows のArduinoIDEで M5Stackの開発環境を構築する記事 があるので、参考にしてください。 においセンサー(TGS2450)について 今回使用したセンサーは 秋月電子通商 で購入できます。 http://akizukidenshi.com/catalog/g/gP-00989/ akizukidenshi.com TGS2450には4つのピンがあり、使用するのはそのうちの3本でヒーターを温めるピン、センサー情報を得るピン、GNDがあります。 ここで注意したいのは、ヒーター電圧は1.6Vと記述されているのでM5Stackで利用するときは分圧して3.3Vを1.6V近くまでに降圧することをお勧めします。 TGS2450のセンサーは可変抵抗になっており、データシートには5.62kΩ〜56.2kΩの間を抵抗が変化し、においが強いとより低くなると記述されていました。 よって、センサーの値をM5Stackで取得するにはセンサー抵抗と外部に接続する任意の値の抵抗による分圧回路によって求めることができます。 TGS2450の動作方法は、250ms周期でセンサーに電圧を5ミリ秒on、245ミリ秒offの状態にしてヒーターは8ミリ秒on、242ミリ秒offにすることで値を取得します。 配線 においセンサーとM5Stackの配線 上の図が配線図です。 30Ωの抵抗は10Ωの抵抗を三つ直列に接続して作成しました。 また、上部の抵抗10Ω二

Phaser3 + Typescriptを使ってRPGゲームの基礎を作ろう!その1

今回はPhaser3とTypescriptを使って簡単な RPG ゲームを作る方法を紹介していきます。 内容はPhaser3およびゲーム作りについての記事なので、Nodejsの周辺モジュールなどの説明は一部省いての説明になりますのでご了承ください。 またこの記事では Phaser2 ではなく Phaser3 を使用するので注意してください。 この記事は二部構成になりますので、この記事を読んだ際はぜひ次の記事も読むことをお勧めします。 最終目標 ・Phaser3とTypescriptで RPG ゲームの基礎を作る。 ・Phaser3をTypescriptで使う方法を学ぶ ・Phaser3の使い方を学ぶ 今回の目標 ・開発環境を整える ・Phaser3の開発構成を知る ・スタート画面を作る ・マップ表示をさせる 開発前提 ・Nodejsの環境・知識がある ・ Javascript ・Typescriptがある程度かける ・当ページ紹介の環境を試す場合はgit・ github の知識がある 使用した主要Nodeモジュール ・typescript(Typescriptの コンパイル 用) ・phaser(フロントの Javascript 用ゲームライブラリ) ・live-server(ソースを監視してブラウザのページをリロード) ・ts-loader(webpackがTypescriptをバンドルする用)webpack(言わずと知れたモジュール依存をいい感じに解決しバンドルする) ・webpack- cli (webpackを コマンドライン で使用するのに必要) 注:各Nodeモジュールバージョンは後述 1. 最低限の開発環境の準備 今回最低限の環境を整えるために、『Typescript + Phaser3』の開発テンプレートを github リポジトリ で公開しました。 以下からZIPをダウンロードするか、 git clone コマンドで各自環境に展開してみてください。 ここから先は リポジトリ のプログラムを元に説明していきます。 github.com 展開するとファイル構造は以下のようになっているかと思われます。 注: 他にもファイルやフォルダがあるかと思われますが、表記されているのは今回使うものになっています。 - src/ (これから書くプログラムの保存領域)