Raspberry pi4でPyenv、OpenCV3.4.3(4.5.2)、Tensorflow Liteの環境を構築する

# はじめに
今回Pyenvを採用しているのは、Ubuntu20.04のデフォルトがPython3.8で、
~~TensorflowLiteは3.7までしか対応していないため、Pyenvで3.7の環境を構築していきます。~~
**追記[2021/06/30] Python3.8も対応しています。**
**OpenCV4.5.2が最新なので、そちらに対応しました**

# 開発環境
- Raspberry pi4 8GB
- Ubuntu20.04LTS
- UbuntuMate
Xubuntuの極度に抽象化されたトラ？ヒョウ？チーター？の壁紙がツボるも、Mateの方が使いやすいのでUbuntuMateを採用しました。
ちなみにXubuntuはUbuntuMateを入れれば一緒に入ってきます。
ログイン時に歯車マークからOSの選択ができるので、Mateを選択します。

# 初めの一歩
## aptを使ったライブラリのインストール
まずは必要なライブラリ等をターミナルからaptを使ってインストールします。
apt-get installとapt installがあって、特に気にしてはいなかったがapt installが推奨みたいです。
**追記[2021/06/30] 足りないライブラリがあったので追加しました**

```sh:Terminal
# Build tools
sudo apt -y install build-essential cmake pkg-config
# Image
sudo apt -y install libjpeg-dev libtiff5-dev libpng-dev
# Movie
sudo apt -y install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt -y install libxvidcore-dev libx264-dev libgtk2.0-dev
# Optimize
sudo apt -y install libatlas-base-dev gfortran
# HDF5
sudo apt -y install libhdf5-dev libhdf5-serial-dev libhdf5-103
# Qt
sudo apt -y install python3-pyqt5
# Python
sudo apt -y install python3-dev python3-numpy git
# その他
sudo apt -y install libtbb2 libtbb-dev libopenblas-dev libblas-dev
```
'#'の部分はコメントアウトなので「sudo apt~」の部分のみコピペしていきます。
sudoは管理者として実行するためのコマンドです。
-yをつけておくと、インストールする際の確認を全てYesで答えてくれるようになり、Yes/Noを聞かれなくなります。
## Pyenvの環境構築
TensorflowLiteのためにPyenvをインストールして、Python3.7の環境を構築しておきます。
もしTFLiteを使わないのであればこの項目はスキップしてもOKです。
### 必要となるライブラリやgitの準備

```sh:Terminal
# pyenv setup (If you dont use TFlite, you can skip. Because python version must be 3.7  for TFlite)
# Install required library
sudo apt -y install --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
# Download pyenv
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```
libraryは何点か被っているかもしれません。既にインストールされていれば勝手に飛ばしてくれるので、あまり気にしなくても良いです。
もし特定の場所にpyenvをcloneしたい場合は、pyenvのURL以降の「~/.pyenv」を書き換えます。
### bashrcへの書き込み
ターミナルからpyenvを呼び出せるようにbashrcに書き込んでおきます。

```sh:Terminal
# Configuration on terminal
echo 'export PYENV_ROOT="${HOME}/.pyenv"' >> ~/.bashrc
echo 'if [ -d "${PYENV_ROOT}" ]; then' >> ~/.bashrc
echo '    export PATH=${PYENV_ROOT}/bin:$PATH' >> ~/.bashrc
echo '    eval "$(pyenv init -)"' >> ~/.bashrc
echo 'fi' >> ~/.bashrc
exec $SHELL -l
source ~/.bashrc
```
前項でpyenvのダウンロード場所を変えている場合は適宜「/.pyenv」の箇所を書き換えます。
pyenvがちゃんと入っているかの確認も行います。

```sh:Terminal
pyenv version
```
### pyenvのバージョンが表示されない
もしversionが表示されない場合は、一度ターミナルを閉じて、新しく開いた後にもう一度上記コマンドを入力します。
もしくはラズパイ自体を再起動してみます。
それでもダメな場合は、うまく環境構築できていないのでvim等でbashrcを開いてちゃんと書き込まれているか確認してみましょう。

```sh:Terminal
sudo vim ~/.bashrc
```
vimでbashrcが開くので、ちゃんとpyenvの設定が書き込まれているかを確認してみましょう。
vimがインストールされてない場合は、

```sh:Terminal
sudo apt install vim
```
でインストールすることができる。vimの操作方法はちょっとクセがあるので適宜調べてください。
## PyenvでPython3.7の環境を作る
以下のコマンドでインストールします。

```sh:Terminal
# Make python 3.7 environment
CONFIGURE_OPTS="--enable-shared" pyenv install 3.7.8
```
10分ほどかかるのでコーヒーでも作って待ちます。
インストール後、

```sh:Terminal
pyenv versions
```
で3.7.8が表示されることを確認します。

```sh:Terminal
pyenv shell 3.7.8
```
としておけば、そのターミナル上では常にPython3.7.8が実行されるようになります。
試しに

```sh:Terminal
python
```
とすると、Python3.7.8が起動する。戻る時は

```sh:Terminal
quit()
```
でPythonを終了できます。
## pyenv環境上にOpenCVを構築する
### swap領域の拡張
~~ビルド時にスワップメモリが不足するので、スワップ領域を拡張します。~~
**追記[2021/06/30] スワップ領域の拡張はしなくてもいいです。**

```sh:Terminal
sudo dd if=/dev/zero of=/swap1 bs=1M count=2048
sudo mkswap /swap1
sudo chmod 600 /swap1
sudo swapon /swap1
```
# Numpyのインストール

```sh:Terminal
pip install numpy
```
でnumpyをインストールする。上記pyenv環境構築後を前提としているので、
もしpyenv環境に移っていなければ、

```sh:Terminal
pyenv shell 3.7.8
```
をした後にpipでインストールしてください。
pipが入っていなければ、

```sh:Terminal
sudo apt install python3-pip
```
を実行してpipをインストールしてください。
# OpenCVのzipファイルをダウンロード
公式のGithubからzipファイルをダウンロードして、解凍します。

## OpenCV3.4.3

```sh:Terminal
wget -O opencv.zip https://github.com/opencv/opencv/archive/3.4.3.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/3.4.3.zip
unzip opencv.zip
unzip opencv_contrib.zip
```

## OpenCV4.5.2
```sh:Terminal
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.2.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.5.2.zip
unzip opencv.zip
unzip opencv_contrib.zip
```

# OpenCVのビルド
OpenCVの中に移動します。
## 3.4.3

```sh:Terminal
cd opencv-3.4.3
mkdir build
cd build
```
## 4.5.2
```sh:Terminal
cd opencv-4.5.2
mkdir build
cd build
```

ここで気をつけてほしいのは、下記に記載しているのは私の環境上のファイルの位置なので、自分でしっかり調べて自身の環境に合わせてください。
特に、
- PYTHON3_EXECUTABLE
- PYTHON3_INCLUDE_DIR
- PYTHON3_NUMPY_INCLUDE_DIRS
- PYTHON3_LIBRARIES
- INCLUDE_DIRS
- INCLUDE_DIRS2
- PYTHON_PACKAGES_PATH
- OPENCV_EXTRA_MODULES_PATH
あたりは人によって違うので、気をつけてください。
**追記[2021/06/30] 特に4.5.2でビルドする方は```OPENCV_EXTRA_MODULES_PATH```を4.5.2のcontribにしてください**

```sh:Terminal
sudo cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local \
-D WITH_OPENCL=OFF -D WITH_CUDA=OFF -D BUILD_opencv_gpu=OFF \
-D BUILD_opencv_gpuarithm=OFF -D BUILD_opencv_gpubgsegm=OFF \
-D BUILD_opencv_gpucodec=OFF -D BUILD_opencv_gpufeatures2d=OFF \
-D BUILD_opencv_gpufilters=OFF -D BUILD_opencv_gpuimgproc=OFF \
-D BUILD_opencv_gpulegacy=OFF -D BUILD_opencv_gpuoptflow=OFF \
-D BUILD_opencv_gpustereo=OFF -D BUILD_opencv_gpuwarping=OFF \
-D BUILD_DOCS=OFF -D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF \
-D BUILD_opencv_python3=ON -D FORCE_VTK=ON \
-D WITH_TBB=ON -D WITH_V4L=ON \
-D WITH_OPENGL=ON -D WITH_CUBLAS=ON \
-D BUILD_opencv_python3=ON \
-D PYTHON3_EXECUTABLE=~/.pyenv/versions/3.7.8/bin/python \
-D PYTHON3_INCLUDE_DIR=~/.pyenv/versions/3.7.8/include/python3.7m \
-D PYTHON3_NUMPY_INCLUDE_DIRS=~/.pyenv/versions/3.7.8/lib/python3.7/site-packages/numpy/core/include \
-D PYTHON3_LIBRARIES=~/.pyenv/versions/3.7.8/lib/libpython3.7m.a\
-D INCLUDE_DIRS=~/.pyenv/versions/3.7.8/include/python3.7m \
-D INCLUDE_DIRS2=~/.pyenv/versions/3.7.8/include/python3.7m \
-D PYTHON_PACKAGES_PATH=~/.pyenv/versions/3.7.8/lib/python3.7/site-packages \
-D WITH_FFMPEG=ON \
-D WITH_GTK=ON \
-D OPENCV_EXTRA_MODULES_PATH=/home/ubuntu/opencv_contrib-3.4.3/modules \
..
```
cmakeが終わったら、makeします。

```sh:Terminal
make -j4
```
結構時間がかかります。30分くらい？
終わったらインストールします。

```sh:Terminal
make install
```
インストールは結構早い。

# TensorflowLiteを入れる
Tensorflow Liteを使う上で、恐らく[PINTO](https://qiita.com/PINTO)さんには一生お世話になると思います。
PINTOさんの[TensorflowLite-bin](https://github.com/PINTO0309/TensorflowLite-bin)からwhlファイルを拝借して、環境構築を行います。
今回はTensorflowLite2.3.0を入れていきます。
[こちら](https://github.com/PINTO0309/TensorflowLite-bin/blob/master/2.3.0/download_tflite_runtime-2.3.0-py3-none-linux_aarch64.whl.sh)からbashファイルを拝借し、whlファイルをダウンロードします。
ダウンロード後、whlファイルのあるディレクトリへ移動し、先程構築したpython3.7の仮想環境上で以下のコマンドを打ちインストールします。

```sh:Terminal
pip install tflite_runtime-2.3.0-py3-none-linux_aarch64.whl
```

最後にPython3を起動し、tflite-runtimeがインポートできれば完了です。お疲れさまでした。
**追記[2021/06/30] Interpreterをimportするところまでやってみてください。**

```sh:Terminal
python3
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) 
Type "help", "copyright", "credits" or "license" for more information.
>>> from tflite-runtime.interpreter import Interpreter
>>>
```