RaspberryPiにOpenCV3.4+Tensorflow1.4+keras2.1をインストールする
以前のエントリーではRaspberryPiで新しめのtensorflowを使ってみようということでインストール設定を行いました。いろいろWarningが出ながらも動作できるようになり、あとはやるだけなんだよと思いつつ、腰はまだ上がりませんでした。
そんな時大垣のソフトピアで
なるイベントが開催され参加することもできましたので、今回はPCではなくRaspberryPiでやってみようと思いました。PCではAnacondaでの設定だけど、RaspberryPiでは自分の設定したものでできるなあとタカをくくっていて、あとはOpenCVを入れれば実験できるなあとかなり軽く考えていました。
ただ、python3.5ではOpenCVの設定がなくあれー?(お手軽じゃないじゃんの意)って感じになり、仕方なくソースコードからOpenCVをインストールすることにました。
茨の道に入ったような気がしますが、色々(2週間ほどビルド地獄だったw)あり、違う方法も含めて実験には成功できましたので、そのときのメモ。
OpenCVインストール放浪編【結論を求めるなら読む必要のない情報】
OpenCVをソースからインストールするということで以下のサイトを参考にしてインストールしてみました。
基本的な流れとしては
- ビルドに必要なパッケージのインストール
- OpenCVのソース関連の取得
- VirtualEnv環境のセッティング
- numpyのインストール
- ビルド
- ビルド後の設定
こんな感じになります。
$ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install build-essential cmake pkg-config $ sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev $ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev $ sudo apt-get install libxvidcore-dev libx264-dev $ sudo apt-get install libgtk2.0-dev $ sudo apt-get install libatlas-base-dev gfortran $ sudo apt-get install python2.7-dev python3-dev $ wget -O opencv.zip https://github.com/Itseez/opencv/archive/3.4.0.zip $ wget -O opencv_contrib.zip https://github.com/Itseez/opencv_contrib/archive/3.4.0.zip $ unzip opencv.zip $ unzip opencv_contrib.zip $ wget https://bootstrap.pypa.io/get-pip.py $ sudo python3 get-pip.py $ sudo pip3 install virtualenv virtualenvwrapper $ sudo rm -rf ~/.cache/pip $ echo -e "\n# virtualenv and virtualenvwrapper" >> ~/.profile $ echo "export WORKON_HOME=$HOME/.virtualenvs" >> ~/.profile $ echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.profile $ source ~/.profile $ mkvirtualenv cv-python3 -p python3 $ workon cv-python3 $ pip install numpy $ cd opencv-3.4.0/ $ mkdir build $ cd build/ $ cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_PYTHON_EXAMPLES=ON -D OPENCV_EXTRA_MODULES_PATH=~/opencv/opencv_contrib-3.4.0/modules -D BUILD_EXAMPLES=ON .. $ make clean $ time make
ここまででビルドがされますが、とても時間がかかります。
参考サイトではmake -j4
となっていますが、発熱やmakeする順序などによっては失敗する様です。自分は3回失敗したので-j2
としてみましたが、それでもダメ。最終的にmake
のみにしています。(make
だけでは失敗したことはないです)実際かかる時間はこんな感じなので、寝る前にやりましょう。
real 283m10.666s user 246m21.650s sys 6m20.950s
ビルドが終了したらインストールを行います。
$ sudo make install $ sudo ldconfig $ ls -l /usr/local/lib/python3.5/site-packages/ $ cd /usr/local/lib/python3.5/site-packages/ $ sudo mv cv2.cpython-35m.so cv2.so $ cd ~/.virtualenvs/cv-python3/lib/python3.5/site-packages/ $ ln -s /usr/local/lib/python3.5/site-packages/cv2.so cv2.so
これでインストール完了になりました。
あとは確認となるのですが…
$ workon cv-python3 (cv-python3) $ python Python 3.5.3 (default, Jan 19 2017, 14:11:04) [GCC 6.3.0 20170124] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import cv2 >>> cv2.__version__ '3.4.0' >>>
無事インストール成功です。ちゃんといっているのですが…
OpenCV以外のパッケージが消えていますw。前のエントリーで折角インストールしたTensorflowとkerasも消えてます。
(cv-python3) $ pip list DEPRECATION: The default format will switch to columns in the future. You can use --format=(legacy|columns) (or define a format=(legacy|columns) in your pip.conf under the [list] section) to disable this warning. numpy (1.14.0) pip (9.0.1) setuptools (38.4.1) wheel (0.30.0)
うわああああ
この手順をいろいろと5回ほど実験したところ(w)VirtualEnv環境を設定したあたりでこの状況になるようです。この手順を外せば行けそうです。
ただ、なんとなくこれではつらみがあるので、再度ググって設定方法を見直したいと思います。
再度見直し
再度ネットをググってビルド済みのパッケージも含めて探してみました。
opencv3.4のインストールパッケージ
https://github.com/mt08xx/files/raw/master/opencv-rpi/libopencv3_3.4.0-20180115.1_armhf.deb
tensorflow1.4.1のインストールパッケージ
python2.7
python3.5
インストール作業へ
今回使用したRaspbianのバージョンはこちらになります。
- 2017-11-29-raspbian-stretch.img
バージョン情報を確認すると…
$ lsb_release -a No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 9.1 (stretch) Release: 9.1 Codename: stretch $ python --version Python 2.7.13 $ python3 --version Python 3.5.3
pythonが3.5.3になっているで前回のエントリーの設定では動作はするのですが、Warningが出るというものでした。
OpenCV3.4のインストール
以下のブログがありました。OpenCVの構築にほとんどの時間が割かれるのでこれは助かりました。
今から思えば、最初からこれを使えばよかったのではないのかと思います。
$ wget https://github.com/mt08xx/files/raw/master/opencv-rpi/libopencv3_3.4.0-20180115.1_armhf.deb
$ sudo apt install -y ./libopencv3_3.4.0-20180115.1_armhf.deb
$ sudo ldconfig
これでOpenCV3.4をインストールができました。この作業でPython2系もPython3系も使用可能になっています。
Tensorflow1.4.1のインストール
以下の作業ではTensorflowとともにkerasもインストールします。
TensorflowのWhlパッケージを作成されている方がいらっしゃいました。tensorflowのバージョンが1.4.1でかつpython3.5様なのも嬉しいところです。大概のパッケージがpython3.4なのが辛いです(minicondaにあわせているのかも?)
python2.7で使用する場合
$ sudo apt-get install libblas-dev liblapack-dev python-dev libatlas-base-dev gfortran python-setuptools $ sudo pip install https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.4.1/tensorflow-1.4.1-cp27-none-linux_armv7l.whl $ sudo apt-get install python-h5py $ sudo pip install keras
これで完了です。REPL環境でチェックしてみます。
$ python Python 2.7.13 (default, Jan 19 2017, 14:48:08) [GCC 6.3.0 20170124] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import numpy >>> import cv2 >>> import tensorflow >>> import keras Using TensorFlow backend. >>> numpy.__version__ '1.12.1' >>> cv2.__version__ '3.4.0' >>> tensorflow.__version__ '1.4.1' >>> keras.__version__ '2.1.3' >>>
python3.5で使用する場合
$ pip3 install numpy==1.13 $ sudo apt-get install libblas-dev liblapack-dev python3-dev libatlas-base-dev gfortran python3-setuptools $ sudo pip3 install https://github.com/lhelontra/tensorflow-on-arm/releases/download/v1.4.1/tensorflow-1.4.1-cp35-none-linux_armv7l.whl $ sudo apt-get install python3-h5py $ sudo pip3 install keras
一行目のnumpyのバージョンを1.13をしています。3.5系ではtensorflowをimportするとWarningが発生します。
Warningは
>>> import tensorflow RuntimeError: module compiled against API version 0xb but this version of numpy is 0xa
こんな感じで表示されます。インストール後にpipでバージョンアップしても問題は無いようです。
ただ、バージョンアップをすればいいと思って、以下のようにnumpyを2018.02.10現在以下のようにアップグレートすると
$ pip install --upgrade numpy
インストールが終わると1.14がインストールされ、tensorflowのimport時にWarningが発生するので、この設定は必須になります。
ではREPL環境でバージョンの確認を行ってみます。
$ python3 Python 3.5.3 (default, Jan 19 2017, 14:11:04) [GCC 6.3.0 20170124] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import numpy >>> import cv2 >>> import tensorflow >>> import keras Using TensorFlow backend. >>> numpy.__version__ '1.13.0' >>> cv2.__version__ '3.4.0' >>> tensorflow.__version__ '1.4.1' >>> keras.__version__ '2.1.3' >>>
前回のエントリーではなんとなくWarningもでていましたが、今回のインストール方法では全く問題はなく、すんなり完了できたと思います。
サンプルの実行
OpenCVのテスト
画像は表示されるのですが以下のようなWarningがでます。
** (image:1479): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files
org.a11y.Bus
のWarningは解決手段があまりないようでしたので動くので良しとしました。
Tensorflowのテスト
TensorflowのHello worldの実行になります。
【ソース】
import tensorflow as tf import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' hello = tf.constant('Hello, Tensorflow') sess = tf.Session() print(sess.run(hello))
【実行結果】
b'Hello, Tensorflow'
OpenCV&Tensorflow&kerasのサンプル
【07tf.py】
from keras.models import Sequential from keras.layers import Activation, Dense, Dropout from keras.utils.np_utils import to_categorical from keras.optimizers import Adagrad from keras.optimizers import Adam import numpy as np from PIL import Image import os image_list = [] label_list = [] # トレーニングデータを読み込む for dir in os.listdir("data/train"): traindir = "data/train/" + dir if os.path.isdir(traindir) == False: continue label = 0 # 正解ラベル if dir == "apple": label = 0 # りんごの場合は、0 elif dir == "orange": label = 1 # オレンジの場合は、1 for file in os.listdir(traindir): if file != ".DS_Store": label_list.append(label) # 正解ラベルを配列に入れる filepath = traindir + "/" + file # ファイルパス resized_img = Image.open(filepath).resize((25, 25)) # 画像を25x25にリサイズする image = np.array(resized_img) # 25x25の2次元配列にする→[[R,G,B], [R,G,B]...] image = image.transpose(2, 0, 1) # 配列を次元を変換する→[[R,R,R,...], [G,G,G,...], [B,B,B,...]] image = image.reshape(1, image.shape[0] * image.shape[1] * image.shape[2]).astype("float32")[0] # 1次元配列に変換→[R,R,R,...,G,G,G,...,B,B,B] image_list.append(image / 255.) # 0.0〜1.0までの値にして配列に入れる image_list = np.array(image_list) # 画像リストをnumpy配列に変換 Y = to_categorical(label_list) # 正解ラベルを配列にする(0→[1,0], 1→[0,1]) # 層を構築 model = Sequential() # 入力層 model.add(Dense(200, input_dim=1875)) model.add(Activation("relu")) model.add(Dropout(0.2)) # 隠れ層 model.add(Dense(200)) model.add(Activation("relu")) model.add(Dropout(0.2)) # 出力層 model.add(Dense(2)) model.add(Activation("softmax")) # オプティマイザにAdamを使用 opt = Adam(lr=0.001) model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"]) # nb_epoch: 学習回数 # batch_size: 1度に処理する分量(GPUモードの際は、メモリ制限がある場合がある) model.fit(image_list, Y, nb_epoch=1500, batch_size=100, validation_split=0.1) # model.fit(image_list, Y, nb_epoch=10, batch_size=100, validation_split=0.1) total = 0. ok_count = 0. for dir in os.listdir("data/test"): testdir = "data/test/" + dir if os.path.isdir(testdir) == False: continue label = 0 if dir == "apple": label = 0 # りんごの場合は、0 elif dir == "orange": label = 1 # オレンジの場合は、1 for file in os.listdir(testdir): if file != ".DS_Store": label_list.append(label) filepath = testdir + "/" + file resized_img = Image.open(filepath).resize((25, 25)) image = np.array(resized_img) image = image.transpose(2, 0, 1) image = image.reshape(1, image.shape[0] * image.shape[1] * image.shape[2]).astype("float32")[0] # 予測する print(filepath) result = model.predict_classes(np.array([image / 255.])) print("label:", label, "result:", result[0]) total += 1. if label == result[0]: ok_count += 1. print(ok_count / total * 100, "%")
【実行結果】
$ python3 07tf.py Using TensorFlow backend. /usr/local/lib/python3.5/dist-packages/keras/models.py:944: UserWarning: The `nb_epoch` argument in `fit` has been renamed `epochs`. warnings.warn('The `nb_epoch` argument in `fit` ' Train on 35 samples, validate on 4 samples Epoch 1/1500 35/35 [==============================] - 3s 93ms/step - loss: 0.9337 - acc: 0.5429 - val_loss: 0.0025 - val_acc: 1.0000 Epoch 2/1500 35/35 [==============================] - 0s 2ms/step - loss: 2.7587 - acc: 0.4571 - val_loss: 0.3437 - val_acc: 1.0000 (中略) Epoch 1498/1500 35/35 [==============================] - 0s 2ms/step - loss: 8.9737e-06 - acc: 1.0000 - val_loss: 3.8743e-07 - val_acc: 1.0000 Epoch 1499/1500 35/35 [==============================] - 0s 2ms/step - loss: 3.3191e-05 - acc: 1.0000 - val_loss: 3.5763e-07 - val_acc: 1.0000 Epoch 1500/1500 35/35 [==============================] - 0s 2ms/step - loss: 6.7218e-06 - acc: 1.0000 - val_loss: 3.5763e-07 - val_acc: 1.0000 data/test/apple/1212043top.jpg label: 0 result: 0 data/test/apple/81306024002554.jpg label: 0 result: 0 data/test/apple/81306024002557.jpg label: 0 result: 0 data/test/apple/1757f226647a6f1.jpg label: 0 result: 0 data/test/orange/images (1).jpeg label: 1 result: 1 data/test/orange/8242_1.jpg label: 1 result: 1 data/test/orange/1152194_orange_isolated_on_white_background.jpg label: 1 result: 1 data/test/orange/DKCcTzZXUAA0ckm.jpg label: 1 result: 1 100.0 % Exception ignored in: <bound method BaseSession.__del__ of <tensorflow.python.client.session.Session object at 0x6f3a1430>> Traceback (most recent call last): File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py", line 696, in __del__ TypeError: 'NoneType' object is not callable
若干のWarningとExceptionがでているんですが、概ね実行はできているっぽいようです。このサンプルの内容はりんごとオレンジを画像を学習して分類するというものです。
最初と最後にでているExceptionに関してはググってみると解決方法はあるようです。 Keras2系のバージョンによるものの模様です。
keras+tensorflowで終了処理でエラーが発生する | CodeLab技術ブログ
おわりに
前回はスッキリしない終わり方でしたが、今回はimport時のWarningなどは発生せずにうまくロードできました。