Docker(Ubuntu18.04+CUDA10.1+cudnn7)でOpenCV4.1.1インストールするメモ

## 修正履歴
* 2019/12/05 コメントで提案いただいた内容を反映しました。 
* 2019/12/05 fix typo

## 概要
1. NVIDIA Driverのインストール
2. dockerのインストール
3. nvidia-dockerのインストール
4. docker image(nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04)のpull
5. docker runしてOpenCV4.1.1のインストール
6. docker imageにcommit

## 前提
* [Ubuntu16.04へのOpenCV 3.3.0インストールメモ](https://qiita.com/nakasuke_/items/51664807bdd7794db0da)から１年以上経ってOpenCVのメジャーバージョンも上がったので。
* 作業したノートパソコンでは、「Intel® HD Graphics」で画面表示しないと、ログインループが発生したので表示は「Intel® HD Graphics」、計算等にNVIDIA GPUを使うことにしました。
* コピペで動くようにコマンドはそのまま貼りつけています。
  * historyから抽出して貼り付けているので、間違っているかも...
* 不要なパッケージも入るけれどとりあえず動けばOK。
* nvidia-dockerでnvidia/cudaレポジトリのimageにOpenCVをインストールします。

## 環境
* 環境は下表の通り。

|            |Name              |Version                    |
|:-----------|:----------------:|:-------------------------:|
|OS(host)    |Ubuntu            |18.04.3 LTS (Bionic Beaver)|
|CPU         |Intel® Core™      |i5-8300H CPU @ 2.30GHz × 8 |
|kernel      |Linux             |5.0.0-23-generic           |
|GPU         |NVIDIA GeForce    |GTX 1050                   |


##前準備
### NVIDIA Driverのインストール
#### runファイルのダウンロード
* https://www.nvidia.co.jp/Download/index.aspx?lang=jp からrunファイルをダウンロード
  * 作業時にダウンロードしたのは「NVIDIA-Linux-x86_64-430.40.run」

#### install
```
sudo apt update
sudo apt install build-essential
sudo bash NVIDIA-Linux-x86_64-430.40.run --no-opengl-files
sudo prime-select intel
```

### Dockerのインストール
* [Get Docker Engine - Community for Ubuntu | Docker Documentation](https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-from-a-package)を参考に、packageからDockerをインストール

#### packageのダウンロード
* Ubuntu 18.04(64bit)用のDocker最新版を以下のURLで確認
    * https://download.docker.com/linux/ubuntu/dists/bionic/pool/stable/amd64/
* 19.03.1~3-0が最新版だったので以下のファイルをダウンロード
  * containerd.io_1.2.6-3_amd64.deb
  * docker-ce-cli_19.03.1~3-0~ubuntu-bionic_amd64.deb
  * docker-ce_19.03.1~3-0~ubuntu-bionic_amd64.deb

```
sudo apt install wget
wget https://download.docker.com/linux/ubuntu/dists/bionic/pool/stable/amd64/containerd.io_1.2.6-3_amd64.deb
wget https://download.docker.com/linux/ubuntu/dists/bionic/pool/stable/amd64/docker-ce-cli_19.03.1~3-0~ubuntu-bionic_amd64.deb
wget https://download.docker.com/linux/ubuntu/dists/bionic/pool/stable/amd64/docker-ce_19.03.1~3-0~ubuntu-bionic_amd64.deb
```

#### install
* ダウンロードしたパッケージを以下のコマンドでインストール

```
sudo dpkg -i containerd.io_1.2.6-3_amd64.deb 
sudo dpkg -i docker-ce-cli_19.03.1~3-0~ubuntu-bionic_amd64.deb 
sudo dpkg -i docker-ce_19.03.1~3-0~ubuntu-bionic_amd64.deb 
```

#### 確認
```terminal
sudo docker --version
```

* 以下のようにダウンロードしたバージョンが表示されればインストール完了

```terminal:出力
Docker version 19.03.1, build 74b1e89
```

#### インストール後の設定
* [Post-installation steps for Linux | Docker Documentation](https://docs.docker.com/install/linux/linux-postinstall/)を参考に、```sudo```無しで`docker`を使えるようにする。
* ```docker```グループの作成はインストールすると作成されるようなので、割愛。

#### ユーザーを```docker```グループへ追加
```
sudo usermod -aG docker $USER
```

#### 一度ログアウト
```
gnome-session-quit --logout --no-prompt
```

#### 確認
* ログイン後、```sudo```無しでdockerを利用できるか確認する。

```
docker --version
```


### nvidia-dockerのインストール
* [Installation (Native GPU Support) · NVIDIA/nvidia-docker Wiki · GitHub](https://github.com/nvidia/nvidia-docker/wiki/Installation-(Native-GPU-Support))を参考に、aptでnvidia-dockerをインストールする

#### install
```
sudo apt install curl
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey |   sudo apt-key add -
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list |   sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt update
sudo apt-get install -y nvidia-container-toolkit
```

#### 確認とpull
```
docker run --gpus 1 nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04 nvidia-smi
```

## OpenCVのインストール
* Docker imageは`nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04`を使用
* ソースコードのダウンロードは省略
* ソースコードはホスト側に保存
  * OpenCVの保存先`/data/opencv-4.1.1`
  * contribの保存先`/data/opencv-4.1.1/opencv_contrib-4.1.1`

### containerの起動
* GUIを使えるようにオプションを指定

```
docker run --gpus 1 -it --rm --name opencv -e DISPLAY=$DISPLAY -v /tmp/.X11-unix/:/tmp/.X11-unix -v /data/:/data nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04
```

### (container内)依存パッケージ等のinstall
*  [Ubuntu 16.04のとき](https://qiita.com/nakasuke_/items/51664807bdd7794db0da)との変更点は以下
  * libjasperがなくなった。
  * pythonのバージョンアップ

```
apt update
apt install cmake libeigen3-dev libgtk-3-dev qt5-default freeglut3-dev \
libvtk6-qt-dev libtbb-dev ffmpeg libdc1394-22-dev libavcodec-dev libavformat-dev \
libswscale-dev libjpeg-dev libpng++-dev libtiff5-dev \
libopenexr-dev libwebp-dev libhdf5-dev libpython3.6-dev python3-numpy \
python3-scipy python3-matplotlib libopenblas-dev liblapacke-dev
```

### (container内)CMakeの実行
```
mkdir /data/opencv-4.1.1/build && cd /data/opencv-4.1.1/build
cmake -G "Unix Makefiles" --build . -D BUILD_CUDA_STUBS=OFF -D BUILD_DOCS=OFF \
-D BUILD_EXAMPLES=ON -D BUILD_JASPER=OFF -D BUILD_JPEG=OFF -D BUILD_OPENEXR=OFF \
-D BUILD_PACKAGE=ON -D BUILD_PERF_TESTS=OFF -D BUILD_PNG=OFF -D BUILD_SHARED_LIBS=ON \
-D BUILD_TBB=OFF -D BUILD_TESTS=OFF -D BUILD_TIFF=OFF -D BUILD_WITH_DEBUG_INFO=ON \
-D BUILD_ZLIB=OFF -D BUILD_WEBP=OFF -D BUILD_opencv_apps=ON -D BUILD_opencv_calib3d=ON \
-D BUILD_opencv_core=ON -D BUILD_opencv_cudaarithm=ON -D BUILD_opencv_cudabgsegm=ON \
-D BUILD_opencv_cudacodec=ON -D BUILD_opencv_cudafeatures2d=ON \
-D BUILD_opencv_cudafilters=ON -D BUILD_opencv_cudaimgproc=ON -D BUILD_opencv_cudalegacy=ON \
-D BUILD_opencv_cudaobjdetect=ON -D BUILD_opencv_cudaoptflow=ON \
-D BUILD_opencv_cudastereo=ON -D BUILD_opencv_cudawarping=ON -D BUILD_opencv_cudev=ON \
-D BUILD_opencv_features2d=ON -D BUILD_opencv_flann=ON -D BUILD_opencv_highgui=ON \
-D BUILD_opencv_imgcodecs=ON -D BUILD_opencv_imgproc=ON -D BUILD_opencv_java=OFF \
-D BUILD_opencv_ml=ON -D BUILD_opencv_objdetect=ON -D BUILD_opencv_photo=ON \
-D BUILD_opencv_python2=OFF -D BUILD_opencv_python3=ON -D BUILD_opencv_shape=ON \
-D BUILD_opencv_stitching=ON -D BUILD_opencv_superres=ON -D BUILD_opencv_ts=ON \
-D BUILD_opencv_video=ON -D BUILD_opencv_videoio=ON -D BUILD_opencv_videostab=ON \
-D BUILD_opencv_viz=OFF -D BUILD_opencv_world=OFF -D CMAKE_BUILD_TYPE=RELEASE \
-D WITH_1394=ON -D WITH_CUBLAS=ON -D WITH_CUDA=ON -D WITH_CUFFT=OFF -D WITH_EIGEN=ON \
-D WITH_FFMPEG=ON -D WITH_GDAL=OFF -D WITH_GPHOTO2=OFF -D WITH_GIGEAPI=OFF \
-D WITH_GSTREAMER=OFF -D WITH_GTK=ON -D WITH_INTELPERC=OFF -D WITH_IPP=ON -D WITH_IPP_A=OFF \
-D WITH_JASPER=ON -D WITH_JPEG=ON -D WITH_LIBV4L=ON -D WITH_OPENCL=ON \
-D WITH_OPENCLAMDBLAS=OFF -D WITH_OPENCLAMDFFT=OFF -D WITH_OPENCL_SVM=OFF \
-D WITH_OPENEXR=ON -D WITH_OPENGL=ON -D WITH_OPENMP=OFF -D WITH_OPENNI=OFF -D WITH_PNG=ON \
-D WITH_PTHREADS_PF=OFF -D WITH_PVAPI=OFF -D WITH_QT=ON -D WITH_TBB=ON -D WITH_TIFF=ON \
-D WITH_UNICAP=OFF -D WITH_V4L=OFF -D WITH_VTK=OFF -D WITH_WEBP=ON -D WITH_XIMEA=OFF \
-D WITH_XINE=OFF -D WITH_LAPACKE=ON -D WITH_MATLAB=OFF -D EIGEN_INCLUDE_PATH=/usr/include/eigen3 \
-D OPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.1.1/modules/ ..
```

### (container内)build
```
make -j4
sudo make install
```

### (container内)確認
```
python3 -c 'import cv2;print(cv2.__version__)'
```

* 以下のように表示されれば完了

```text:出力
4.1.1
```

### commit
* デタッチしてcommit

```
docker commit opencv test/opencv:4.1.1-ubuntu1804
```

### commitの確認
* `docker images`で確認する。

```text:出力
REPOSITORY          TAG                             IMAGE ID            CREATED             SIZE
nvidia/cuda         10.1-cudnn7-devel-ubuntu18.04   1dc5cbc98312        4 weeks ago         3.6GB
test/opencv         4.1.1-ubuntu1804                ************        *                   *GB
```