「TensorFlowで遊びながら学んだ、はじめてのLED点滅」IoTLTの準備で得た知識の整理
この記事は、IoTLT Advent Calendar 2016 の10日目の記事です。
IoTLT Advent Calendar 2016
http://qiita.com/advent-calendar/2016/iotlt
今年(2016年)の8/12に開催されたIoTLTでLTした、
「TensorFlowで遊びながら学んだ、はじめてのLED点滅」
の準備をする中で得た知識や参考にしたサイトを、この記事で整理しておこうと思います。
LTを準備する中で、
TensorFlow、OpenCVとArduinoを扱ったのですが、
私自身、3つともはじめて扱ったこともありいろいろと勉強になりました。
IoT縛りの勉強会! IoTLT vol.18 @ Amazon
https://iotlt.connpass.com/event/35436/
TensorFlowで遊びながら学んだ、はじめてのLED点滅
LT発表資料
SlideShareにLT資料をアップしています。
# 「アイドルマスタープラチナスターズ」から
# キャプチャした画像を含むスライドは省略しています。
システムの概要
システムの概要はこんな感じです。
Python及びJupyterNotebookの環境構築
まずはじめに、Pythonの環境を構築します。
以下を参考にして、anyenv, pyenv, pyenv-virtualenv をインストールします。
pythonの開発環境の切り替え用に anyenv, pyenv, pyenv-virtualenv, anacondaを入れる流れ
http://takemikami.com/2016/10/20/python-anyenv-pyenv-pyenvvirtualenv-anaconda.html
以下のように、anacondaをインストールし切り替えます。
$ mkdir ~/iotlt20160812 && cd $_
$ pyenv install anaconda3-4.2.0
$ pyenv local anaconda3-4.2.0
opencv, tensorflow用に環境を作成し、切り替えます。
$ conda create -n iotlt20160812 python=3.5
$ pyenv activate iotlt20160812
jupyterをインストールし、起動します。
$ conda install jupyter
$ jupyter notebook
ブラウザが起動して以下のような画面が表示されます。
OpenCVでの顔認識
環境構築
以下のように、homebrewでopencvをインストールします。
$ brew install homebrew/science/opencv
anaconda環境にOpenCV, matplotlibをインストールします。
$ conda install -c https://conda.anaconda.org/menpo opencv3
$ pip install matplotlib
顔認識の実行
以下のようなコードでjpgファイルをjupyter notebook上にinline表示することが出来ます。
画像は適当なjpegファイルを用意してください。
# アイドルマスター プラチナスターズの画像を使いたい場合は、
# PS4のシェア機能を使ってTwitterなどに上げれば良いと思います。
import cv2, matplotlib
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img = cv2.imread('※ここにファイル名※.jpg') # ゆきほ エクストリームバースト画像読込
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # convert image to RGB color for matplotlib
plt.imshow(img) # show image with matplotlib
参考: 画像処理入門講座 : OpenCVとPythonで始める画像処理 | プログラミング | POSTD
http://postd.cc/image-processing-101/
次に、lbpcascade_animeface.xmlを使って、顔認識をします。
以下のようなコードになります。
下記の参考サイトから、lbpcascade_animeface.xmlをダウンロードしておいてください。
# アニメ顔認識器読み込み
cascade_path = "./lbpcascade_animeface.xml"
cascade = cv2.CascadeClassifier(cascade_path)
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) # convert image to grayscale
cv2.equalizeHist(gray_img, gray_img) # ヒストグラムの平坦化
facerect = cascade.detectMultiScale(gray_img, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1)) # 顔認識
color = (255, 255, 255)
image = img
#検出した顔を囲む矩形の作成
if len(facerect) > 0:
for rect in facerect:
cv2.rectangle(image, tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]), color, thickness=2)
plt.imshow(image)
参考: OpenCVによるアニメ顔検出ならlbpcascade_animeface.xml | デー
http://ultraist.hatenablog.com/entry/20110718/1310965532
TensorFlowでの分類
環境構築
anaconda環境にTensorFlowをインストールします。
$ conda install -c conda-forge tensorflow
教師データの切り出し
教師データは、YouTubeで公開されている以下のキャラクターPVから切り出しました。
PS4「アイドルマスター プラチナスターズ」キャラクターPV ~萩原雪歩~ | YouTube
https://www.youtube.com/watch?v=o7WCt196x6Y
PS4「アイドルマスター プラチナスターズ」キャラクターPV ~星井美希~ | YouTube
https://www.youtube.com/watch?v=i-jjWfJytso
PS4「アイドルマスター プラチナスターズ」キャラクターPV ~高槻やよい~ | YouTube
https://www.youtube.com/watch?v=v0jUg6r2_u0
以下のように、FRAMEを少しずつ動かしてイメージを読み込み、
顔認識してその部分を教師データとして切り出していきます。
import cv2, matplotlib
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
cap = cv2.VideoCapture("※動画ファイル名※.mp4")
max_frame = cap.get(cv2.CAP_PROP_FRAME_COUNT);
print(max_frame)
image_idx = 0
for i in range(110):
print(i)
cap.set(cv2.CAP_PROP_POS_FRAMES,10*(i+1));
ret, img = cap.read()
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert image to grayscale
※以降は顔認識のコードと同様※
学習と予測の実行
学習と予測は、以下の参考ページをそのまま持ってきて実行したので、
参考サイトを上げるだけにしておきます。
参考: TensorFlowでアニメゆるゆりの制作会社を識別する | kivantium活動日記 http://kivantium.hateblo.jp/entry/2015/11/18/233834
畳み込みニューラルネットについては、以下の記事がわかりやすいので参考にして下さい。
参考: 畳み込みニューラルネットワークの仕組み | コンピュータサイエンス | POSTD
http://postd.cc/how-do-convolutional-neural-networks-work/?1479446220158=1
ArduinoでのLED点滅
環境構築
anaconda環境に、pyserialをインストールします。
$ pip install pyserial
LED点滅用の信号送出の実行
以下のように、pyserialでusbポートにつないだarduionoに0または1の信号を送出し、
LEDのOn/Offを切り替えます(Arduiono側のコードは省略しますが)。
# 0を送出
import serial
ser = serial.Serial(port='/dev/cu.usbmodem141121', baudrate=9600)
output_bytes = b'0' # 1を送出する場合は、ここを1に
if ser.isOpen():
ser.write(output_bytes)
print("send: " + str(output_bytes))
肝心の学習と予測の部分が参考サイト上げるだけになってしまいましたが、
この記事で全体の流れの雰囲気(意外と簡単に出来るということ)は
わかっていただけるのかなと思います。
皆さんもこんな感じでカジュアルに遊んでみてください。