AKIBAko

自分のためのナレッジ的ブログ

Raspberry pi で MNIST

この前トレーニングした MNIST で手書き数字を分類してみたが全然ダメ
なんでじゃー

手書き数字は以下

0.jpg 1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg 8.jpg 9.jpg
f:id:minori-san:20161107231839j:plain f:id:minori-san:20161107231840j:plain f:id:minori-san:20161107231841j:plain f:id:minori-san:20161107231831j:plain f:id:minori-san:20161107231832j:plain f:id:minori-san:20161107231833j:plain f:id:minori-san:20161107231834j:plain f:id:minori-san:20161107231835j:plain f:id:minori-san:20161107231836j:plain f:id:minori-san:20161107231837j:plain

 
やったことを記載しておく

meanファイルを作成

$ cd ~/caffe
$ ./build/tools/compute_image_mean examples/mnist/mnist_train_lmdb examples/mnist/mean.binaryproto

mean.binaryproto から mean.npy を作成
https://github.com/BVLC/caffe/issues/290 を参考に下記のスクリプトを作成して mean.binaryproto を mean.npy に変換する

  • ~/caffe/examples/mnist/mean_bp2npy.py
import caffe
import numpy as np
import sys

if len(sys.argv) != 3:
print "Usage: python convert_protomean.py proto.mean out.npy"
sys.exit()

blob = caffe.proto.caffe_pb2.BlobProto()
data = open( sys.argv[1] , 'rb' ).read()
blob.ParseFromString(data)
arr = np.array( caffe.io.blobproto_to_array(blob) )
out = arr[0]
np.save( sys.argv[2] , out )

スクリプトを実行

$ cd ~/caffe/examples/mnist
$ python mean_bp2npy.py mean.binaryproto mean.npy

mean.npy ができたので、推論してみる
~/caffe/python/classify.py を使っても良いのだろうが、python の勉強のために下記スクリプトを作成

  • ~/caffe/examples/mnist/mnist_iter.py
#!/usr/bin/python

import sys, os

prototxt = sys.argv[1]
model    = sys.argv[2]
mean     = sys.argv[3]
imgs     = ['0.jpg', '1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg', '7.jpg', '8.jpg', '9.jpg']

if os.path.exists(prototxt) == False or os.path.exists(model) == False or os.path.exists(mean) == False :
    print("File does not exist")
    sys.exit()

import cv2
import caffe
import numpy as np

datas = []
net    = caffe.Classifier(prototxt, model, mean=np.load(mean), image_dims=(28,28))

for img in imgs :
    datas.append(caffe.io.load_image(img, color=False))
outdt  = net.predict(datas)

for i in range(0, len(imgs)) :
    sortdt = sorted(range(len(outdt[i])), key=lambda x:outdt[i][x], reverse=True)
    print '--------- [%s] ---------' % (imgs[i])
    for j in sortdt[0:3] :
        score = outdt[i][j]
        if score != 0 :
            print '%d.jpg - %f percent' % (j ,score*100)
    print ''

スクリプトの実行

$ cd ~/caffe/examples/mnist
$ python mnist_iter.py lenet.prototxt lenet_iter_10000.caffemodel mean.npy 

全然分類できていない
スクリプトが悪いのか、画像が悪いのか、やり方が悪いのか。。

--------- [0.jpg] ---------
5.jpg - 100.000000 percent

--------- [1.jpg] ---------
5.jpg - 100.000000 percent

--------- [2.jpg] ---------
5.jpg - 100.000000 percent

--------- [3.jpg] ---------
5.jpg - 100.000000 percent

--------- [4.jpg] ---------
5.jpg - 100.000000 percent

--------- [5.jpg] ---------
5.jpg - 100.000000 percent

--------- [6.jpg] ---------
5.jpg - 100.000000 percent

--------- [7.jpg] ---------
5.jpg - 100.000000 percent

--------- [8.jpg] ---------
5.jpg - 100.000000 percent

--------- [9.jpg] ---------
5.jpg - 100.000000 percent

学習回数も頑張って1万回しても結果変わらないし、mean を消しても結果がぼんやりするだけで全然ダメだった
トレーニング時の accuracy ってなんじゃい

Rasspberry pi で画像解析

をしたかったけど Raspberry pi メモリ 1GB だと結構厳しいみたい。。
Caffe のリファレンスモデルで推論してみたらメモリ不足で落ちてしまった

bvlc_reference_caffenet で推論

リファレンスモデルの取得

$ cd ~/caffe/models/bvlc_reference_caffenet
$ wget http://dl.caffe.berkeleyvision.org/bvlc_reference_caffenet.caffemodel

リファレンスモデルで推論
画像はとりあえず Caltech101 から chair を入力。deploy.prototxt と mean.npy はデフォルトのまま

$ cd ~/caffe/python
$ python classify.py ~/101_ObjectCategories/chair/image_0010.jpg result.npy

実行結果はメモリ不足。。 やり方を考える必要がありそう

:
  File "/home/pi/caffe/python/caffe/classifier.py", line 26, in __init__
    caffe.Net.__init__(self, model_file, pretrained_file, caffe.TEST)
MemoryError

MNIST でトレーニング

mnist なら動かせるかなと思いトレーニングしてみた

mnist データの取得

$ cd ~/caffe/data/mnist
$ ./get_mnist.sh

データベースの作成

$ cd ~/caffe/examples/mnist
$ ./create_mnist.sh

solver.prototxt の編集
学習回数とかスナップショットとか回数をかなり少なく編集

net: "examples/mnist/lenet_train_test.prototxt"
test_iter: 10
test_interval: 50
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005
lr_policy: "inv"
gamma: 0.0001
power: 0.75
display: 10
max_iter: 1000
snapshot: 100
snapshot_prefix: "examples/mnist/lenet"
solver_mode: CPU

トレーニング実施

$ cd ~/caffe
$ examples/mnist/train_lenet.sh

回数かなり減らしたのにめちゃ時間がかかる。。
やってみてから気づいたが、Raspberry pi で学習する必要は全くなかった。

Iteration accuracy loss
100 0.904 0.33312
200 0.888 0.362638
300 0.974 0.0817223
400 0.99 0.0362336
500 0.975 0.0846267
600 0.943 0.158974
700 0.965 0.114721
800 0.982 0.058539
900 0.993 0.0229984
1000 0.975 0.0803299

でも、とりあえず学習はできているようだ。
あとで手書き数字で推論してみよ

RaspberryPi に Caffe

RaspberryPi で画像認識なんかをさせてみようと Caffe をいれてみた
学習は無理でもインファレンスはできるんじゃないかと。。

http://caffe.berkeleyvision.org/install_apt.html
ここを参考に Raspberry Pi で下記を実施  

  • General dependencies
$ sudo apt-get install libprotobuf-dev libleveldb-dev libsnappy-dev libopencv-dev libhdf5-serial-dev protobuf-compiler
$ sudo apt-get install --no-install-recommends libboost-all-dev

 

  • BLASインストール
$ sudo apt-get install libatlas-base-dev 

 

  • その他パッケージ
$ sudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev

 

  • Caffe を取得
$ git clone https://github.com/BVLC/caffe.git
$ cd caffe

 

  • Caffe のビルド
    CPU_ONLY にしなければ、RaspberryPi でも GPU を使ってくれるのかな?
$ mkdir build
$ cmake ..
$ make all
$ make instll
$ make runtest

 

  • pycaffe のビルド
    python で使いたいので pycaffe をビルド
$ make pycaffe

 

  • caffe へのパス設定
$ cd ~/
$ echo 'export PYTHONPATH=~/caffe/python/:$PYTHONPATH' >> ~/.bashrc
$ source .bashrc

 

パスが設定できたところでインストール完了。 あとは python で caffe がインポートできるか確認してみる

ImportError: No module named skimage.io

skimage が無いとのこと。とりあえず apt-get でインストール

$ sudo apt-get install python-skimage

再度、caffe インポートすると、次は protobuf が無いらしい

ImportError: No module named google.protobuf.internal

protobuf も apt-get でインストールすると、やっと caffe のインポートに成功

pi@raspberrypi:~ $ python
Python 2.7.9 (default, Sep 17 2016, 20:26:04)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import caffe
>>> caffe.__version__
'1.0.0-rc3'

とにかくビルドにめちゃ時間かかったので、動きは今度確認しよう

OpenCV2 インストール

家のサーバに OpenCV を入れたが、これがちょっと面倒だったのでメモ

まずは、OpenCV に必要なライブラリをインストール
本当にこんなに必要なのか。。

$ sudo apt-get install git cmake build-essential pkg-config
$ sudo apt-get install libopencv-dev libopencore-amrnb-dev libopencore-amrwb-dev
$ sudo apt-get install libgtk2.0-dev libdc1394-22 libdc1394-22-dev libdc1394-utils
$ sudo apt-get install libjpeg-dev libpng12-dev libtiff4-dev libjasper-dev libavcodec-dev libavformat-dev
$ sudo apt-get install libswscale-dev libxine-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-dev libtbb-dev 
$ sudo apt-get install libqt4-dev libfaac-dev libmp3lame-dev libtheora-dev libvorbis-dev libxvidcore-dev x264 v4l-utils

OpenCV ソースコードgithub から取得
※ 現時点で2系の最新は 2.4.13 みたい

$ wget https://github.com/opencv/opencv/archive/2.4.13.zip
$ unzip 2.4.13.zip
$ cd opencv-2.4.13

cmake の作成

$ mkdir build
$ cd build/
$ sudo cmake -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON -D WITH_QT=ON -D WITH_OPENGL=ON -D WITH_VTK=ON ..

ビルド&インストール

$ make
$ sudo make install

ちゃんと入っているか確認

$ python
>>> import cv2
>>> cv2.__version__
'2.4.13'

あと、opencv インポート時に『libdc1394 error: Failed to initialize libdc1394』が出たら下記で対処

stackoverflow.com

Python で GPIO 制御

以下の図のとおり、Wiiリモコンで GPIO制御して LED を点けたり消したりしたい
まずは、Python でGPIO制御を確認するところまで実施してみる
(電流が LED の定格を多少超えようが気にしない)

f:id:minori-san:20161030160139j:plain

RPi.GPIO をインポートして使いたいGPIO を Out設定すれば行けそうなので下記のとおり実施してみる

  • GPIO設定
$ python
>>> import RPi.GPIO as GPIO
>>> GPIO.setmode(GPIO.BCM)
  • GPIO Out設定
>>> GPIO.setup(4, GPIO.OUT)
>>> GPIO.setup(17, GPIO.OUT)
>>> GPIO.setup(18, GPIO.OUT)
>>> GPIO.setup(23, GPIO.OUT)
  • LED点灯
>>> GPIO.output(4, True)
>>> GPIO.output(17, True)
>>> GPIO.output(18, True)
>>> GPIO.output(23, True)
  • LED消灯
>>> GPIO.output(4, False)
>>> GPIO.output(17, False)
>>> GPIO.output(18, False)
>>> GPIO.output(23, False)

問題なく LED が点灯 ⇒ 消灯 できた

f:id:minori-san:20161030160145j:plain

あとは、下記で使ったスクリプトに上記手順を組み合わせれば完成だけど、また今度にしよう

mino-san.hatenablog.com

Raspberry pi を Wiiリモコンでコントロール

Raspberry pi を外部から制御するように Wiiリモコンを使ってみようと思ったところ下記のように簡単にできるようだ

Raspberry pi から Wiiリモコンが見えているか確認

pi@raspberrypi:~ $ hcitool scan
Scanning ...
00:19:1D:29:F5:34 Nintendo RVL-CNT-01

まずは Python をインストール

$ sudo apt-get update
$ sudo apt-get install python-dev

cwiid をインストール

$ sudo apt-get install python-cwiid

適当なディレクトリを作って、テストプログラムをダウンロード

$ mkdir wiimote
$ cd wiimote
$ wget https://www.raspberrypi.org/learning/robo-butler/code/wii_remote_1.py

実行してみた

pi@raspberrypi:~/wiimote $ python wii_remote_1.py
Press 1 + 2 on your Wii Remote now ...
No wiimotes found
Error opening wiimote connection

なんかエラーが出たと思ったら、sudo を忘れていた

pi@raspberrypi:~/wiimote $ sudo python wii_remote_1.py
Press 1 + 2 on your Wii Remote now ...
Wii Remote connected...
Press some buttons!
Press PLUS and MINUS together to disconnect and quit.
Button 1 pressed
Button 2 pressed
Left pressed
Left pressed
Right pressed
Right pressed
Down pressed
Up pressed
Right pressed
Left pressed
Left pressed
Down pressed
Down pressed
Left pressed
Right pressed
Right pressed
Up pressed
Down pressed

できた。これで Raspberry pi をラジコンとかにして遊んでみようと思う

 

 

Raspberry pi にリモートディスクトップ接続

分かってはいたが、4インチ LCD では使い勝手がいまいち悪い。

そのため、Raspberry pi はリモートディスクトップで運用することにした。

 $ sudo apt-get install xrdp

Google先生が言うには  xrdp をインストールするだけで、リモートディスクトップに接続できるようになるらしいが、何故かセッション確立後に『error - problem connecting』となって先にすすまない

f:id:minori-san:20161029161536p:plain

 色々調べてみたら vncserver をインストールすれば上手くいくことがあるらしい。

$ sudo apt-get install tightvncserver

 

f:id:minori-san:20161029162047p:plain

 上手くいった。

あとは、キーボード入力を日本語対応して完了

$ cd /etc/xrdp/
$ sudo wget http://w.vmeta.jp/temp/km-0411.ini
$ sudo ln -s km-0411.ini km-e0010411.ini
$ sudo ln -s km-0411.ini km-e0200411.ini
$ sudo ln -s km-0411.ini km-e0210411.ini