Raspberry Pi 3 Model Bの4コアを利用したOpenCVの環境構築と性能評価

# はじめに
- Raspberry PiでOpenCVを使った時、いまいち性能に満足しなかった事がありました
- どうやら、4コアのうち、1コアしか使っていなかったようです
- そこで、4コアをフルに使うための環境構築と性能評価を実施しました
- https://github.com/maedamikio/public/tree/master/raspberrypi_opencv


# 環境情報等
```
$ uname -a
Linux raspberrypi 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l GNU/Linux

$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
```


# 環境構築
- apt、pipとmakeを使うパターンを試しました
- Pythonのバージョンの違いも試しました

## apt python2
- apt 1コマンドでOKです
- ただ、OpenCVのバージョンが古いですね

```
$ sudo apt install python-opencv

$ python -c "import cv2; print(cv2.__version__)"
2.4.9.1
```

## apt python3
- python3は未対応

```
$ sudo apt install python3-opencv
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
E: パッケージ python3-opencv が見つかりません
```

## pip python2
- python2は未対応

```
$ pip install opencv-python
Collecting opencv-python
  Could not find a version that satisfies the requirement opencv-python (from versions: )
No matching distribution found for opencv-python
```

## pip3 python3
- aptで関連ライブラリをインストールする必要があります

```
$ sudo apt install libcblas3 libatlas3-base libjasper1 libqt4-test

$ pip3 install opencv-python

$ python3 -c "import cv2; print(cv2.__version__)"
3.4.4
```

## make python2, python3
- https://docs.opencv.org/master/d7/d9f/tutorial_linux_install.html
- TBB(Intel Threading Building Blocks)のオプションで4コアを使うようになります
- Intelで無い場合は、OpenCVがよろしくARMに切り替えてくれるようです
- makeに3時間40分かかりました。。。
- makeで4コア使うオプション -j4 は、Raspberry Piのメモリ不足で失敗するので、オプション無しでmakeしましょう

```
$ sudo apt install build-essential
$ sudo apt install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
$ sudo apt install python-dev python-numpy python3-dev python3-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

$ cd ~
$ git clone https://github.com/opencv/opencv.git

$ cd ~/opencv
$ mkdir build
$ cd build

$ cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_TBB=ON ..

$ make

$ sudo make install

$ python -c "import cv2; print(cv2.__version__)"
4.1.0-dev

$ python3 -c "import cv2; print(cv2.__version__)"
4.1.0-dev
```

# 性能評価用アプリ
- 顔画像認識の Face Detection using Haar Cascades を使いました
- https://docs.opencv.org/master/d7/d8b/tutorial_py_face_detection.html

## face_detect.py
- 処理を100回繰り返すように修正しています

```
$ vim face_detect.py
import time
import cv2

print('opencv version: {}'.format(cv2.__version__))

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

start = time.time()
for _ in range(100):
    print('{} times'.format(_))
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
        roi_gray = gray[y:y+h, x:x+w]
        roi_color = img[y:y+h, x:x+w]
        eyes = eye_cascade.detectMultiScale(roi_gray)
        for (ex,ey,ew,eh) in eyes:
            cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
end = time.time()
print('elapsed second: {}'.format(end - start))
```

## XML classifiers
- 上記で使う CascadeClassifier をダウンロードしておきましょう

```
$ wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml
$ wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_eye.xml
```

## image.jpg
- 一部界隈ではおなじみの顔画像を使いました
![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68632/db05c79e-ae5e-f4cb-0dbe-c34a0b893577.jpeg)


# 性能評価

## apt python2
- 約353秒です。
- topを見る限り、1コアしか使っていませんね。

```
$ python face_detect.py
opencv version: 2.4.9.1
0 times
省略
99 times
elapsed second: 353.696244955
```

```
top - 19:33:36 up 7 days,  7:43,  3 users,  load average: 0.55, 0.24, 0.11
Tasks: 140 total,   2 running,  91 sleeping,   0 stopped,   1 zombie
%Cpu0  :  0.3 us,  0.0 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.3 us,  0.3 sy,  0.0 ni, 99.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   949448 total,    39748 free,   196808 used,   712892 buff/cache
KiB Swap:   102396 total,    98556 free,     3840 used.   667880 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
23769 pi        20   0  162476  53972  27036 R 100.0  5.7   0:44.58 python
```

## pip3 python3
- 109秒です。速い!
- 4コア使ってますね!

```
$ python3 face_detect.py
opencv version: 3.4.4
0 times
省略
99 times
elapsed second: 109.94710516929626
```

```
top - 20:37:30 up 7 days,  8:47,  3 users,  load average: 1.36, 0.73, 0.61
Tasks: 141 total,   2 running,  91 sleeping,   0 stopped,   1 zombie
%Cpu0  : 96.4 us,  0.7 sy,  0.0 ni,  3.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  : 72.3 us,  4.0 sy,  0.0 ni, 23.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  : 70.6 us,  2.3 sy,  0.0 ni, 27.1 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  : 65.1 us,  3.7 sy,  0.0 ni, 31.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   949448 total,   107776 free,   210048 used,   631624 buff/cache
KiB Swap:   102396 total,    98556 free,     3840 used.   652644 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1307 pi        20   0  208792  69720  31140 R 312.5  7.3   1:35.99 python3
```

## make python2
- 128秒です
- 4コア使ってますね

```
$ python face_detect.py
opencv version: 4.1.0-dev
0 times
省略
99 times
elapsed second: 128.737085104
```

```
top - 00:54:30 up  4:12,  3 users,  load average: 1.96, 1.08, 0.72
Tasks: 127 total,   2 running,  83 sleeping,   0 stopped,   1 zombie
%Cpu0  : 64.2 us,  0.7 sy,  0.0 ni, 35.1 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  : 92.1 us,  7.9 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  : 67.1 us,  1.0 sy,  0.0 ni, 31.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  : 62.0 us,  0.3 sy,  0.0 ni, 37.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   949448 total,   521320 free,   137416 used,   290712 buff/cache
KiB Swap:   102396 total,    80124 free,    22272 used.   742712 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 2024 pi        20   0  175796  63008  27500 R 291.8  6.6   0:36.01 python
```

## make python3
- 128秒です
- 4コア使ってますね

```
$ python3 face_detect.py
opencv version: 4.1.0-dev
0 times
省略
99 times
elapsed second: 128.6926610469818
```

```
top - 00:57:32 up  4:15,  3 users,  load average: 1.65, 1.52, 0.98
Tasks: 127 total,   3 running,  83 sleeping,   0 stopped,   1 zombie
%Cpu0  : 73.0 us,  0.7 sy,  0.0 ni, 26.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  : 69.3 us,  0.7 sy,  0.0 ni, 30.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu2  : 74.0 us,  0.7 sy,  0.0 ni, 25.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  : 98.3 us,  1.7 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   949448 total,   519832 free,   138844 used,   290772 buff/cache
KiB Swap:   102396 total,    80124 free,    22272 used.   741284 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 2029 pi        20   0  178404  65404  28244 R 315.5  6.9   0:41.52 python
```

## 結果一覧

|環境構築|Pythonバージョン|OpenCVバージョン|CPUコア数|時間(秒)|
|---|---|---|---|---|
|apt|2.7.13|2.4.9.1|1|353|
|pip|3.5.3|3.4.4|4|109|
|make|2.7.13|4.1.0-dev|4|128|
|make|3.5.3|4.1.0-dev|4|128|


# おわりに
- 一番のお勧めは、pipです。環境構築の簡単さと性能の良さが決め手です。
- 次に、最新バージョンのOpenCVを使いたい場合は、makeをしましょう。環境構築に4時間弱が必要ですが、性能はpipの場合と同等です。
- 今回の4コアの趣旨とは外れますが、環境構築は1コマンド、性能は必要無く、Python2のサポート終了までの約1年弱戦えれば良い場合は、aptです。