【保存版】OpenCV Python with CUDAをAnaconda環境にインストールするレシピ

画像処理は多くの場合大規模な行列演算を実行して行われます。故に以前からOpenCVがGPU上で実行出来ればサイズの大きな画像の処理を高速化出来るのではないかと思っていました。この仮説検証は後程試すとして，まずはGPU上で実行出来るOpenCVをAnaconda上にインストールしました。その行程は気の遠くなるような行程でしたので，備忘録として残しておくことにします。(@jun0_0 の協力に感謝します)

# 構築環境
* Jupyter Notebook Server on Docker(Python3.9 with Anaconda)
    * ベースイメージ: jupyter/tensorflow-notebook
* コンテナ上のゲストOS: Ubuntu 20.04 LTS
* コンテナ上のCUDAバージョン: CUDA11.6
* コンテナ上のcuDNNのバージョン: cuDNN8.4.0.27
* ホストマシンのスペック
    * OS: Ubuntu 20.04 LTS
    * CPU: Core i9 10900K
    * DRAM: 64GB
    * GPU: NVIDIA Geforce RTX 2080 SUPER

# (参考) 通常版のインストール
参考までに通常版のOpenCV Pythonのインストール方法とインストールされるバージョンを記載します。

```bash
pip install opencv-python
```

```bash
$ pip list | grep opencv
opencv-python                 4.4.0.46
```

# cuDNNのインストール方法
[参考](https://qiita.com/y-vectorfield/items/8960c804441d2ebd605e)にaptを用いてcuDNNをインストールする方法を掲載していますが，aptでインストールした場合，少し古いバージョンがインストールされ，互換性等の問題で正常にビルド出来ない，動作しないなどのトラブルに見舞われる可能性が有ります．よって少々力業的な方法にはなりますが，cuDNN[^cudnn]をインストールする方法を記載しておきたいと思います。(以下の行程はGUIの画像が出ている部分についてはホストマシン上で実施しているものとします)

[^cudnn]: 説明画像は8.0.5 with CUDA10.1の画像を用いていますが，最新バージョンでも方法は同様です．

## NVIDIAのcuDNNダウンロードページにログインする
なぜか，cuDNNはNVIDIAに無料ユーザー登録しなければ利用出来ません。利用登録後にダウンロードページにログインします。ログイン出来たら`I Agree To the Terms of the cuDNN Software License Agreement`をチェックします。そしてcuDNNのCUDA10.1用のバージョンをクリックし，更にcuDNN Library for Linuxをクリックします。ダウンロードが開始されますが，これをキャンセルします。

![download cudnn](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/da01e01a-75cc-277d-53bd-47458e9dff70.png)

![cancel](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/4559eaeb-3ff8-8c59-2269-9b9c806cff97.png)

![show all](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/6ba373bd-9c7b-f823-0496-08663359faca.png)

![url copy](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469079/c5555d3f-8419-39c6-89a6-5e9107c3ae2d.png)

## cuDNNのソースをダウンロード@コンテナ上
先程コピーしたURLを元に以下のコマンドをコンテナ上で実行します。どうやら筆者の実験の結果，cuDNNのダウンロード用URLは毎回一時的に生成される物だと分かりました。故に実行する毎に変わります。以下は今回実験して得られた一例です。

```bash:コマンド例
$ wget https://developer.download.nvidia.com/compute/machine-learning/cudnn/secure/8.0.5/10.1_20201106/cudnn-10.1-linux-x64-v8.0.5.39.tgz?aETIwrQU2RxM4D_RJoUh5zjSiyOAY2-mOJHEHPYOUXEaHcRx-hfW3aT2yZVZeES5BP_xDT8WvHE8BPlYcfzhgKjyguMS55LYmVnTUbbRy-_uxiyNaLzfzyzE52wmfoyc7rR5z6mbNma5B5jSYS1zg_4XInwSc5tuqdsqxHqPI8I2axdqbdw5iqYLMiCl9SuNftkG-vrNbUNxLMk -O cudnn-10.1-linux-x64-v8.0.5.39.tgz
```

## ソースの解凍と格納
tgzファイルを解凍し，所定のディレクトリに格納します。解凍後cudaディレクトリが作成されます。

```bash
tar xvf cudnn-10.1-linux-x64-v8.0.5.39.tgz
```

<details><summary>cudaディレクトリの構成</summary><div>

```bash
cuda
├── include
│   ├── cudnn_adv_infer.h
│   ├── cudnn_adv_train.h
│   ├── cudnn_backend.h
│   ├── cudnn_cnn_infer.h
│   ├── cudnn_cnn_train.h
│   ├── cudnn.h
│   ├── cudnn_ops_infer.h
│   ├── cudnn_ops_train.h
│   └── cudnn_version.h
├── lib64
│   ├── libcudnn_adv_infer.so -> libcudnn_adv_infer.so.8
│   ├── libcudnn_adv_infer.so.8 -> libcudnn_adv_infer.so.8.0.5
│   ├── libcudnn_adv_infer.so.8.0.5
│   ├── libcudnn_adv_train.so -> libcudnn_adv_train.so.8
│   ├── libcudnn_adv_train.so.8 -> libcudnn_adv_train.so.8.0.5
│   ├── libcudnn_adv_train.so.8.0.5
│   ├── libcudnn_cnn_infer.so -> libcudnn_cnn_infer.so.8
│   ├── libcudnn_cnn_infer.so.8 -> libcudnn_cnn_infer.so.8.0.5
│   ├── libcudnn_cnn_infer.so.8.0.5
│   ├── libcudnn_cnn_train.so -> libcudnn_cnn_train.so.8
│   ├── libcudnn_cnn_train.so.8 -> libcudnn_cnn_train.so.8.0.5
│   ├── libcudnn_cnn_train.so.8.0.5
│   ├── libcudnn_ops_infer.so -> libcudnn_ops_infer.so.8
│   ├── libcudnn_ops_infer.so.8 -> libcudnn_ops_infer.so.8.0.5
│   ├── libcudnn_ops_infer.so.8.0.5
│   ├── libcudnn_ops_train.so -> libcudnn_ops_train.so.8
│   ├── libcudnn_ops_train.so.8 -> libcudnn_ops_train.so.8.0.5
│   ├── libcudnn_ops_train.so.8.0.5
│   ├── libcudnn.so -> libcudnn.so.8
│   ├── libcudnn.so.8 -> libcudnn.so.8.0.5
│   ├── libcudnn.so.8.0.5
│   └── libcudnn_static.a
└── NVIDIA_SLA_cuDNN_Support.txt

2 directories, 32 files
```

</div></details>

cuDNNのソースを所定のディレクトリにコピーします。libraryのコピー時は`-R`オプションを忘れないようにします．シンボリックリンクの情報が失われてしまいます．

```bash
sudo cp -R cuda/lib64/* /usr/local/cuda/lib64/
```

```bash
sudo cp cuda/include/* /usr/local/cuda/include/
```

# OpenCV Python with CUDAのビルド準備
それでは本題のOpenCV Python with CUDAをAnaconda環境のPythonから利用出来る様にまずはOpenCVのソースコードをビルドし，GPU上で利用出来る実行ファイルを生成します。

## ビルドに必要なアプリケーションのインストール
まずはビルドに必要となるアプリケーションをインストールします。

```bash
sudo apt update && sudo apt upgrade -y && \
sudo apt install -y wget git build-essential zlib1g-dev libcurl4-gnutls-dev \
make ccache qt5-qmake gcc-8 g++-8 libavcodec-dev libavformat-dev \
libavutil-dev libswscale-dev libjpeg-turbo8-dev libwebp-dev libtiff-dev
```

<details><summary>旧バージョンでの方法</summary><div>

## gcc-8, g++-8をデフォルトCコンパイラに設定(旧バージョンの場合)
Ubuntu 20.04ではgcc及びg++はバージョン9がデフォルトでインストールされます。しかし，この後ビルドする一部のソースはバージョン8までしか対応していない物が有るため，ダウングレードを行います。

<details><summary>デフォルトバージョンの確認</summary><div>

```bash:デフォルトではバージョン9がインストールされている
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-HskZEa/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-17ubuntu1~20.04' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-HskZEa/gcc-9-9.3.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)
```

</div></details>

```bash
sudo ln -fs /usr/bin/g++-8 /usr/bin/g++
```

```bash
sudo ln -fs /usr/bin/gcc-8 /usr/bin/gcc
```

<details><summary>設定後の確認</summary><div>

```bash:変更の確認
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 8.4.0-3ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 8.4.0 (Ubuntu 8.4.0-3ubuntu2)

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/8/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 8.4.0-3ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 8.4.0 (Ubuntu 8.4.0-3ubuntu2)
```

</div></details>

</div></details>

## Anacondaにインストールされているlibtiffをアンインストール
ビルド時に競合？するのかエラー終了してしまいます。(詳しくは[参考](https://github.com/BVLC/caffe/issues/1559)を参照)

```bash
conda uninstall libtiff
```

## CMakeのソースビルド及びインストール
CMakeはソースから最新版をビルドします。aptからインストール出来る安定版だとエラー終了する場合が有る様です。(詳しくは[参考](https://www.kkaneko.jp/tools/ubuntu/ubuntu_opencv_buildout.html)参照)

```bash
git clone --depth 1 https://github.com/Kitware/CMake.git
```

```bash
cd CMake
```

```bash
./configure --system-curl --system-zlib
```

<details><summary>(参考) 実行結果(一部抜粋)</summary><div>

```bash
$ ./configure --system-curl --system-zlib
---------------------------------------------
CMake 3.19.20201128, Copyright 2000-2020 Kitware, Inc. and Contributors
Found GNU toolchain
C compiler on this system is: gcc   
C++ compiler on this system is: g++    
Makefile processor on this system is: make
g++ has setenv
g++ has unsetenv
g++ does not have environ in stdlib.h
g++ has stl wstring
g++ has <ext/stdio_filebuf.h>
---------------------------------------------
...
...
...
---------------------------------------------
CMake has bootstrapped.  Now run make.
```

</div></details>

```bash
make
```

<details><summary>(参考) 実行結果(一部抜粋)</summary><div>

```bash
$ make
...
...
...
Scanning dependencies of target pseudo_iwyu
[ 99%] Building C object Tests/RunCMake/CMakeFiles/pseudo_iwyu.dir/pseudo_iwyu.c.o
[100%] Linking C executable pseudo_iwyu
[100%] Built target pseudo_iwyu
Scanning dependencies of target foo
[100%] Building CXX object Tests/FindPackageModeMakefileTest/CMakeFiles/foo.dir/foo.cpp.o
[100%] Linking CXX static library libfoo.a
[100%] Built target foo
```

</div></details>

```bash
sudo make install
```

<details><summary>(参考) 実行結果(一部抜粋)</summary><div>

```bash
$ sudo make install
...
-- Installing: /usr/local/share/bash-completion/completions/cmake
-- Installing: /usr/local/share/bash-completion/completions/cpack
-- Installing: /usr/local/share/bash-completion/completions/ctest
```

</div></details>

## Intel MKL, IPP, TBB, DAAL, MPIのインストール
高速化の為のIntel製ライブラリもインストールします。

```bash:ホームディレクトリに戻る
cd
```

```bash
wget -O - https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB | sudo apt-key add -
```

<details><summary>実行結果</summary><div>

```bash
$ wget -O - https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB | sudo apt-key add -
--2020-11-28 14:43:52--  https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB
Resolving apt.repos.intel.com (apt.repos.intel.com)... 23.33.53.192
Connecting to apt.repos.intel.com (apt.repos.intel.com)|23.33.53.192|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1914 (1.9K) [binary/octet-stream]
Saving to: ‘STDOUT’

-                                       100%[=============================================================================>]   1.87K  --.-KB/s    in 0s      

2020-11-28 14:43:52 (183 MB/s) - written to stdout [1914/1914]

OK
```

</div></details>

```bash
sudo wget https://apt.repos.intel.com/setup/intelproducts.list -O /etc/apt/sources.list.d/intelproducts.list
```
<details><summary>実行結果</summary><div>

```bash
$ sudo wget https://apt.repos.intel.com/setup/intelproducts.list -O /etc/apt/sources.list.d/intelproducts.list
--2020-11-28 14:45:36--  https://apt.repos.intel.com/setup/intelproducts.list
Resolving apt.repos.intel.com (apt.repos.intel.com)... 23.33.53.192
Connecting to apt.repos.intel.com (apt.repos.intel.com)|23.33.53.192|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 278 [binary/octet-stream]
Saving to: ‘/etc/apt/sources.list.d/intelproducts.list’

/etc/apt/sources.list.d/intelproducts.l 100%[=============================================================================>]     278  --.-KB/s    in 0s      

2020-11-28 14:45:37 (27.7 MB/s) - ‘/etc/apt/sources.list.d/intelproducts.list’ saved [278/278]
```

</div></details>

```bash
sudo apt update
```

#### 2020/12/12追記: コンフリクト警告が出た場合
以下の様な警告が出た場合(今回はIntel Pythonを利用しない想定のため，問題無い)

```bash
W: Conflicting distribution: https://apt.repos.intel.com/intelpython binary/ InRelease (expected binary/ but got )
```

```bash
sudo vim /etc/apt/sources.list.d/intelproducts.list
```

以下の様にコメントアウトして保存

```config
# deb https://apt.repos.intel.com/intelpython binary/
```

### インストール出来る最新版の確認

```bash
sudo apt install intel-mkl-64bit intel-ipp-64bit intel-tbb intel-daal-64bit intel-mpi
```

<details><summary>(参考) 実行結果</summary><div>

```bash
$ sudo apt install intel-mkl-64bit intel-ipp-64bit intel-tbb intel-daal-64bit intel-mpi
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Package intel-mkl-64bit is a virtual package provided by:
  intel-mkl-64bit-2020.4-912 2020.4-912
  intel-mkl-64bit-2020.3-111 2020.3-111
  intel-mkl-64bit-2020.2-108 2020.2-108
  intel-mkl-64bit-2020.1-102 2020.1-102
  intel-mkl-64bit-2020.0-088 2020.0-088
  intel-mkl-64bit-2019.5-075 2019.5-075
  intel-mkl-64bit-2019.4-070 2019.4-070
  intel-mkl-64bit-2019.3-062 2019.3-062
  intel-mkl-64bit-2019.2-057 2019.2-057
  intel-mkl-64bit-2019.1-053 2019.1-053
  intel-mkl-64bit-2019.0-045 2019.0-045
  intel-mkl-64bit-2018.4-057 2018.4-057
  intel-mkl-64bit-2018.3-051 2018.3-051
  intel-mkl-64bit-2018.2-046 2018.2-046
  intel-mkl-64bit-2018.1-038 2018.1-038
  intel-mkl-64bit-2018.0-033 2018.0-033
You should explicitly select one to install.

Package intel-ipp-64bit is a virtual package provided by:
  intel-ipp-64bit-2020.3-912 2020.3-912
  intel-ipp-64bit-2020.2-108 2020.2-108
  intel-ipp-64bit-2020.1-102 2020.1-102
  intel-ipp-64bit-2020.0-088 2020.0-088
  intel-ipp-64bit-2019.5-075 2019.5-075
  intel-ipp-64bit-2019.4-070 2019.4-070
  intel-ipp-64bit-2019.3-062 2019.3-062
  intel-ipp-64bit-2019.2-057 2019.2-057
  intel-ipp-64bit-2019.1-053 2019.1-053
  intel-ipp-64bit-2019.0-045 2019.0-045
  intel-ipp-64bit-2018.4-057 2018.4-057
  intel-ipp-64bit-2018.3-051 2018.3-051
  intel-ipp-64bit-2018.2-046 2018.2-046
  intel-ipp-64bit-2018.1-038 2018.1-038
  intel-ipp-64bit-2018.0-033 2018.0-033
You should explicitly select one to install.

Package intel-tbb is a virtual package provided by:
  intel-tbb-2020.3-912 2020.3-912
  intel-tbb-2020.3-108 2020.3-108
  intel-tbb-2020.2-102 2020.2-102
  intel-tbb-2020.0-088 2020.0-088
  intel-tbb-2019.8-075 2019.8-075
  intel-tbb-2019.6-070 2019.6-070
  intel-tbb-2019.4-062 2019.4-062
  intel-tbb-2019.2-057 2019.2-057
  intel-tbb-2019.2-053 2019.2-053
  intel-tbb-2019.0-045 2019.0-045
  intel-tbb-2018.6-057 2018.6-057
  intel-tbb-2018.4-051 2018.4-051
  intel-tbb-2018.2-046 2018.2-046
  intel-tbb-2018.0-033 2018.0-033
You should explicitly select one to install.

Package intel-daal-64bit is a virtual package provided by:
  intel-daal-64bit-2020.3-912 2020.3-912
  intel-daal-64bit-2020.2-108 2020.2-108
  intel-daal-64bit-2020.1-102 2020.1-102
  intel-daal-64bit-2020.0-088 2020.0-088
  intel-daal-64bit-2019.5-075 2019.5-075
  intel-daal-64bit-2019.4-070 2019.4-070
  intel-daal-64bit-2019.3-062 2019.3-062
  intel-daal-64bit-2019.2-057 2019.2-057
  intel-daal-64bit-2019.1-053 2019.1-053
  intel-daal-64bit-2019.0-045 2019.0-045
  intel-daal-64bit-2018.3-051 2018.3-051
  intel-daal-64bit-2018.2-046 2018.2-046
  intel-daal-64bit-2018.1-038 2018.1-038
  intel-daal-64bit-2018.0-033 2018.0-033
You should explicitly select one to install.

Package intel-mpi is a virtual package provided by:
  intel-mpi-2019.9-912 2019.9-912
  intel-mpi-2019.8-108 2019.8-108
  intel-mpi-2019.7-102 2019.7-102
  intel-mpi-2019.6-088 2019.6-088
  intel-mpi-2019.6-085 2019.6-085
  intel-mpi-2019.5-075 2019.5-075
  intel-mpi-2019.4-070 2019.4-070
  intel-mpi-2019.3-062 2019.3-062
  intel-mpi-2019.2-057 2019.2-057
  intel-mpi-2019.1-053 2019.1-053
  intel-mpi-2019.0-045 2019.0-045
  intel-mpi-2018.4-057 2018.4-057
  intel-mpi-2018.3-051 2018.3-051
  intel-mpi-2018.2-046 2018.2-046
You should explicitly select one to install.

E: Package 'intel-mkl-64bit' has no installation candidate
E: Package 'intel-ipp-64bit' has no installation candidate
E: Package 'intel-tbb' has no installation candidate
E: Package 'intel-daal-64bit' has no installation candidate
E: Package 'intel-mpi' has no installation candidate
```
</div></details>

```bash
sudo apt install -y intel-mkl-64bit-2020.4-912 intel-ipp-64bit-2020.3-912 intel-tbb-2020.3-912 intel-daal-64bit-2020.3-912 intel-mpi-2019.9-912
```

```bash
sudo vim /etc/ld.so.conf
```

以下の内容を追記します

```config
/opt/intel/daal/lib/intel64
/opt/intel/ipp/lib/intel64
/opt/intel/lib/intel64
/opt/intel/mkl/lib/intel64
/opt/intel/tbb/lib/intel64/gcc4.8
```

```bash
sudo /sbin/ldconfig
```

# OpenCVのソースビルド
OpenCVのソースをGitHubよりクローンし，ビルドを実行します。`--depth`オプションを使うとクローンに要する時間を短縮できます。([参考](https://kakakakakku.hatenablog.com/entry/2017/03/22/195640))

```bash
git clone --depth 1 https://github.com/opencv/opencv.git
```

```bash
git clone --depth 1 https://github.com/opencv/opencv_contrib.git
```

```bash
cd opencv
```

```bash
mkdir build
```

```bash
cd build/
```

以下の環境変数を宣言します。(これらはあくまで今回ビルドを行う環境での値です。実際にビルドを行う環境に合わせて修正して下さい。`ls /usr/local`でCUDAのディレクトリが確認出来ます。)

```bash
export CUDA_PATH="/usr/local/cuda" \
export CFLAGS="-I/usr/local/cuda/include -I/opt/intel/compilers_and_libraries_2020.4.304/linux/mkl/include" \
export LDFLAGS="-L/usr/local/cuda/lib64"
```

以下を実行します。これでビルドに必用なMakefileが生成されます。(これらのオプションはあくまで今回ビルドを行う環境に合わせた値です。`-D CUDA_ARCH_PTX=7.5`はRTX2000シリーズの値です。[参考](https://developer.nvidia.com/cuda-gpus))

* 2020/12/12オプションの微修正

```bash
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/opt/conda/lib \
-D OPENCV_EXTRA_MODULES_PATH=/home/jovyan/opencv_contrib/modules \
-D OpenBLAS_INCLUDE_DIR=/usr/include/x86_64-linux-gnu \
-D OpenBLAS_LIB=/usr/lib/x86_64-linux-gnu/libopenblas.so \
-D INSTALL_TESTS=ON \
-D INSTALL_C_EXAMPLES=ON \
-D WITH_PYTHON=ON \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D BUILD_opencv_python2=OFF \
-D BUILD_opencv_python3=ON \
-D PYTHON_DEFAULT_EXECUTABLE=/opt/conda/bin/python3 \
-D PYTHON_LIBRARY=/opt/conda/lib \
-D PYTHON_INCLUDE_DIR=/opt/conda/include \
-D PYTHON_PACKAGES_PATH=/opt/conda/lib/python3.8/site-packages \
-D PYTHON_NUMPY_INCLUDE_DIR=/opt/conda/pkgs/numpy-1.19.4-py38hf0fd68c_1/lib/python3.8/site-packages/numpy/core/include/ \
-D WITH_MKL=ON \
-D WITH_CUDA=ON \
-D CUDA_FAST_MATH=ON \
-D WITH_CUBLAS=ON \
-D WITH_CUDNN=ON \
-D WITH_NVCUVID=ON \
-D OPENCV_DNN_CUDA=ON \
-D BUILD_opencv_cudaimgproc=ON \
-D BUILD_EXAMPLES=ON .. \
-D CUDA_ARCH_PTX=7.5
```

<details><summary>(参考) 実行結果(一部抜粋)</summary><div>

```bash
...
...
...
--     Disabled:                    cudaimgproc world
--     Disabled by dependency:      cudaoptflow
--     Unavailable:                 alphamat cnn_3dobj cvv freetype hdf java js julia matlab ovis python2 sfm viz
--     Applications:                tests perf_tests examples apps
--     Documentation:               NO
--     Non-free algorithms:         NO
-- 
--   GUI: 
--     GTK+:                        NO
--     VTK support:                 NO
-- 
--   Media I/O: 
--     ZLib:                        /usr/lib/x86_64-linux-gnu/libz.so (ver 1.2.11)
--     JPEG:                        /usr/lib/x86_64-linux-gnu/libjpeg.so (ver 80)
--     WEBP:                        /usr/lib/x86_64-linux-gnu/libwebp.so (ver encoder: 0x020e)
--     PNG:                         build (ver 1.6.37)
--     TIFF:                        /usr/lib/x86_64-linux-gnu/libtiff.so (ver 42 / 4.1.0)
--     JPEG 2000:                   build (ver 2.3.1)
--     OpenEXR:                     build (ver 2.3.0)
--     HDR:                         YES
--     SUNRASTER:                   YES
--     PXM:                         YES
--     PFM:                         YES
-- 
--   Video I/O:
--     DC1394:                      NO
--     FFMPEG:                      YES
--       avcodec:                   YES (58.54.100)
--       avformat:                  YES (58.29.100)
--       avutil:                    YES (56.31.100)
--       swscale:                   YES (5.5.100)
--       avresample:                NO
--     GStreamer:                   NO
--     v4l/v4l2:                    YES (linux/videodev2.h)
-- 
--   Parallel framework:            pthreads
-- 
--   Trace:                         YES (with Intel ITT)
-- 
--   Other third-party libraries:
--     Intel IPP:                   2020.0.0 Gold [2020.0.0]
--            at:                   /home/jovyan/opencv/build/3rdparty/ippicv/ippicv_lnx/icv
--     Intel IPP IW:                sources (2020.0.0)
--               at:                /home/jovyan/opencv/build/3rdparty/ippicv/ippicv_lnx/iw
--     Lapack:                      YES (/opt/intel/mkl/lib/intel64/libmkl_intel_lp64.so /opt/intel/mkl/lib/intel64/libmkl_sequential.so /opt/intel/mkl/lib/intel64/libmkl_core.so /opt/intel/mkl/lib/intel64/libmkl_intel_lp64.so /opt/intel/mkl/lib/intel64/libmkl_sequential.so /opt/intel/mkl/lib/intel64/libmkl_core.so /opt/intel/mkl/lib/intel64/libmkl_intel_lp64.so /opt/intel/mkl/lib/intel64/libmkl_sequential.so /opt/intel/mkl/lib/intel64/libmkl_core.so -lpthread -lm -ldl)
--     Eigen:                       NO
--     Custom HAL:                  NO
--     Protobuf:                    build (3.5.1)
-- 
--   NVIDIA CUDA:                   YES (ver 10.1, CUFFT CUBLAS FAST_MATH)
--     NVIDIA GPU arch:             30 35 37 50 52 60 61 70 75
--     NVIDIA PTX archs:            75
-- 
--   cuDNN:                         NO
-- 
--   OpenCL:                        YES (no extra features)
--     Include path:                /home/jovyan/opencv/3rdparty/include/opencl/1.2
--     Link libraries:              Dynamic load
-- 
--   Python 3:
--     Interpreter:                 /opt/conda/bin/python3 (ver 3.8.6)
--     Libraries:                   /opt/conda/lib/libpython3.8.so (ver 3.8.6)
--     numpy:                       /opt/conda/lib/python3.8/site-packages/numpy/core/include (ver 1.19.4)
--     install path:                lib/python3.8/site-packages/cv2/python-3.8
-- 
--   Python (for build):            /opt/conda/bin/python3
-- 
--   Java:                          
--     ant:                         NO
--     JNI:                         NO
--     Java wrappers:               NO
--     Java tests:                  NO
-- 
--   Install to:                    /opt/conda/lib
-- -----------------------------------------------------------------
-- 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jovyan/opencv/build
```
</div></details>

ビルドを実行します。CPUコア数に応じてスレッド数をして出来ます。今回使用したマシンのCPU(Core i9 10900K)は10Core20Threadなので半分の10スレッドでビルドを実行することにします。CPUのコア数/スレッド数は`lscpu`コマンドで確認出来ます。


```bash
$ lscpu 
Architecture:                    x86_64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
Address sizes:                   39 bits physical, 48 bits virtual
CPU(s):                          20
On-line CPU(s) list:             0-19
Thread(s) per core:              2
Core(s) per socket:              10
...
...
...
```

```bash
make -j10
```

<details><summary>(参考) 実行結果</summary><div>

```bash
$ make -j10
...
...
...
[100%] Built target opencv_python3

```

</div></details>

最後にインストールします。設定した環境変数をroot権限でも引き継げる様に`-E`オプションを渡して`sudo`コマンドを実行します。

```bash
sudo -E make install
```

<details><summary>(参考) 実行結果(一部抜粋)</summary><div>

```bash

$ sudo -E make install
...
...
...
-- Installing: /opt/conda/lib/share/opencv4/samples/python/video_threaded.py
-- Installing: /opt/conda/lib/share/opencv4/samples/python/video_v4l2.py
-- Installing: /opt/conda/lib/share/opencv4/samples/python/watershed.py

```

</div></details>

```bash
sudo /sbin/ldconfig
```

最後にAnacondaのデフォルトsite-packagesディレクトリ上にシンボリックリンクを作成します。(何故かディレクトリ構造が二重になるため)これでPython上で`import cv2`でインポート出来る様になります。

```bash
sudo ln -s /opt/conda/lib/lib/python3.9/site-packages/cv2 /opt/conda/lib/python3.9/site-packages/cv2
```

# インストール完了をPythonで確認
以下のコマンドを実行し，OpenCV Python with CUDAが無事インストール出来たことを確認します。(通常のインストールより新しいバージョンがインストールされています)

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

```bash:実行結果
$ python -c "import cv2; print( cv2.__version__ )"
4.6.0-pre
```

# まとめ
Anaconda環境上でGPUを用いた画像処理が出来る様にOpenCV Python with CUDAのビルド/インストールを行いました。今後どれ程の高速化が実現可能か検証してみようと思います。

# Reference
* [OpenCV 4.3.0 (最新版) のビルドとインストール，CUDA 対応可能（ソースコードを使用）（Ubuntu 上）](https://www.kkaneko.jp/tools/ubuntu/ubuntu_opencv_buildout.html)
* [Intel MKL, IPP, TBB, DALL, MPI（Performance ライブラリ）のインストール（Ubuntu 上）](https://www.kkaneko.jp/tools/ubuntu/ubuntu_mkl.html)
* [pyenv環境へOpenCVをインストールする](https://zv-louis.hatenablog.com/entry/2018/05/08/063000)
* [UbuntuでCUDAを有効にしたOpenCVをビルド](https://qiita.com/Fal318/items/ef1bfe6e69622a563615)
* [OpenCVインストール（CUDA）（Ubuntu）](https://qiita.com/kc1210yone/items/4dcb731123f46a5f735d)
* [OpenCV-PythonのFedoraへのインストール](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_setup/py_setup_in_fedora/py_setup_in_fedora.html#install-opencv-python-in-fedora)
* [findコマンドの使い方](https://qiita.com/hana_shin/items/d1b420568d3c2223bd07)
* [cudacodecモジュールを使ってみよう](https://qiita.com/dandelion1124/items/fb12461e41e70ccc161e)