OpenCVをGPU対応でビルドする[CUDA12.4][Windows10]

## はじめに
pipからもってきたOpenCVではCUDAに関する設定が制限されているようで、
GPUを使うには自前でビルドする必要があります。


卒業研究で、Pupil coreから受信したフレームをCRNNで推論しながら描画する必要があり、試行錯誤して実装できたので、書き残しておきます。

## 環境
windows10
GTX1660ti Laptop
CUDA 12.4
cuDNN v8.9.7
Python 3.10.11
OpenCV 4.10.0
OpenCV Contrib 4.10.0
Cmake
Visual Studio 2022

## 手順
* Python,Git,Cmakeのインストール
* Visual Studioのインストール
* NVIDIA ドライバーのインストール
* CUDA Toolkitのインストール
* cuDNNのインストール
* OpenCV+Contribのクローン
* Cmakeでビルド

## 詳細
### Python,Git,Cmakeのインストール
細かい解説は省きますが、
コマンドプロンプトを管理者権限で実行 
(win+R→"cmd"→Ctrl+Shift+Enter)、
以下のコマンドを入力でOKです

```
winget install --scope machine Python.Python.3.10
winget install --scope machine Git.Git
winget install --scope machine Kitware.CMake
powershell -command "$oldpath = [System.Environment]::GetEnvironmentVariable(\"Path\", \"Machine\"); $oldpath += \";c:\Program Files\Git\cmd\"; [System.Environment]::SetEnvironmentVariable(\"Path\", $oldpath, \"Machine\")"
```



### Visual Studioのインストール

今回はVisual Studio 2022を使いました。
インストーラーを起動して、
『C++ によるデスクトップ開発』から、『v143 ビルドツール用 C++/CLI サポート（最新）』をチェックしてインストールします。

https://visualstudio.microsoft.com/ja/vs/

### NVIDIA ドライバのインストール

搭載しているグラフィックボードに対応するドライバをインストールします。

https://www.nvidia.com/ja-jp/drivers/

### CUDA Toolkitのインストール

グラフィックボードによって対応するCUDAのバージョンが決まってるようですが、
11.8でビルドを行った際、12.0以上が必要とエラーが出たので、
無視してPyTorchの対応している12.4でビルドしています。
問題なく動いているので多分大丈夫です。


ダウンロードはここから

https://developer.nvidia.com/cuda-12-4-0-download-archive?target_os=Windows

:::note warn
CUDA ToolkitのインストールにはVisual Studioがインストールされている必要があります。
見つからない場合、リンク付きのタブが表示されるので、既にあるVisual Studioをアンイストールして、そこからもう一度インストールしましょう。
:::
インストールが完了したら、環境変数を設定するために、コマンドプロンプトで以下のコマンドを実行します。

```mkdir C:\TEMP
powershell -command "[System.Environment]::SetEnvironmentVariable(\"TEMP\", \"C:\TEMP\", \"User\")
```
基本的に何かをインストールするごとにPCを再起動しましょう
環境変数にPATHを通した場合、再起動しないと適応されない場合があるようです。

参考

https://zenn.dev/yumizz/articles/73d6c7d1085d2f

### cuDNNのインストール

CUDAのインストールが完了したらcuDNNをインストールします
ここから、12.xを選んでダウンロードします

https://developer.nvidia.com/rdp/cudnn-archive

ダウンロードしたものを、
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.4
に展開します

その後、システム環境変数→新規からパスを通します
ついでにCUDA_PATH,CUDA_PATH_V12_4ができているか、一緒に確認しておきましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779219/82179fe4-0b43-ad61-2eef-8754969e2c35.png)


### OpenCV+Contribのクローン


```
cd /d c:%HOMEPATH%
git clone --recursive https://github.com/opencv/opencv.git
git clone --recursive https://github.com/opencv/opencv_contrib.git
```

pythonがインストールされていない場合、インストールします。
今回は3.10.11を使用しています。

pipでopencvをインストールしている場合、アンインストールしておきましょう。
ついでにnumpyなどもインストールしておきます。

```
python -m pip install -U pip setuptools
python -m pip install -U numpy pylint flake8
python -m pip uninstall -y opencv-python
python -m pip uninstall -y opencv-python-headless
python -m pip uninstall -y opencv-contrib-python
```

### Cmakeでビルド
まずGPUのCompute Capabilityを調べます。
以下のサイトにグラフィックボードに対応する番号が記載されています。
CUDA-Enabled Geforce and TITAN Productsタブに一般的なグラボがあります。
GTX 1660tiの場合は7.5です。

https://developer.nvidia.com/cuda-gpus

このCompute CapabilityはCmakeのオプションで

-DCUDA_ARCH_BIN=7.5
-DOPENCV_CUDA_ARCH_BIN=7.5
にて指定します。

また、pythonのバージョンによってオプションを書き換えてください
Python310→Python311,Python39など
実際に自分でファイルを検索して確認してください

-DPYTHON_DEFAULT_EXECUTABLE=C:/Program Files/Python310/python.exe
-DPYTHON3_EXECUTABLE=C:/Program Files/Python310/python.exe
-DPYTHON3_INCLUDE_DIR=C:/Program Files/Python310/include
-DPYTHON3_LIBRARY=C:/Program Files/Python310/libs/python310.lib
-DPYTHON3_NUMPY_INCLUDE_DIRS=C:/Program Files/Python310/lib/site-packages/numpy/_core/include


```
cd /d c:%HOMEPATH%
cd opencv
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -A x64 -T host=x64 ^
-DCMAKE_BUILD_TYPE=RELEASE ^
-DBUILD_SHARED_LIBS=ON ^
-DWITH_CUDA=ON ^
-DCUDA_NVCC_FLAGS="-allow-unsupported-compiler" ^
-DCUDA_ARCH_BIN=7.5 -DCUDA_ARCH_PTX="" ^
-DOPENCV_CUDA_ARCH_BIN=7.5 ^
-DWITH_NVCUVID=OFF -DWITH_NVCUVENC=OFF ^
-DBUILD_opencv_world=ON ^
-DBUILD_opencv_apps=ON ^
-DBUILD_opencv_sfm=OFF ^
-DOPENCV_EXTRA_MODULES_PATH=C:%HOMEPATH%\opencv_contrib\modules ^
-DWITH_PYTHON=ON ^
-DBUILD_opencv_python2=OFF ^
-DPYTHON_DEFAULT_EXECUTABLE="C:/Program Files/Python310/python.exe" ^
-DBUILD_opencv_python3=ON ^
-DPYTHON3_EXECUTABLE="C:/Program Files/Python310/python.exe" ^
-DPYTHON3_INCLUDE_DIR="C:/Program Files/Python310/include" ^
-DPYTHON3_LIBRARY="C:/Program Files/Python310/libs/python310.lib" ^
-DPYTHON3_NUMPY_INCLUDE_DIRS="C:/Program Files/Python310/lib/site-packages/numpy/_core/include" ^
-DBUILD_EXAMPLES=ON ^
-DWITH_OPENGL=ON ^
-DOPENCV_ENABLE_NONFREE=OFF ^
-DCMAKE_INSTALL_PREFIX="C:/opencv" ^
-DBLAS_openblas_LIBRARY="%OpenBLAS_ROOT%\lib\openblas.lib" ^
-DGlog_DIR="%GLOG_ROOT%" ^
-DGLOG_LIBRARY="%GLOG_ROOT%\lib\glog.lib" ^
-DGLOG_INCLUDE_DIR="%GLOG_ROOT%\include" ^
-DGflags_DIR="%GFLAGS_ROOT%" ^
-DCeres_DIR="%CERES_ROOT%" ^
-DMETIS_INCLUDE_DIR="%SUITESPARSE_ROOT%\include" ^
-DCXSparse_INCLUDE_DIR="%SUITESPARSE_ROOT%\include\suitesparse" ^
-DCXSparse_LIBRARY="%SUITESPARSE_ROOT%\lib\libcxsparse.lib" ^
-DSuiteSparse_AMD_INCLUDE_DIR="%SUITESPARSE_ROOT%\include\suitesparse" ^
-DSuiteSparse_CAMD_INCLUDE_DIR="%SUITESPARSE_ROOT%\include\suitesparse" ^
-DSuiteSparse_CCOLAMD_INCLUDE_DIR="%SUITESPARSE_ROOT%\include\suitesparse" ^
-DSuiteSparse_CHOLMOD_INCLUDE_DIR="%SUITESPARSE_ROOT%\include\suitesparse" ^
-DSuiteSparse_COLAMD_INCLUDE_DIR="%SUITESPARSE_ROOT%\include\suitesparse" ^
-DSuiteSparse_Config_INCLUDE_DIR="%SUITESPARSE_ROOT%\include\suitesparse" ^
-DSuiteSparse_SPQR_INCLUDE_DIR="%SUITESPARSE_ROOT%\include\suitesparse" ^
-DSuiteSparse_AMD_LIBRARY="%SUITESPARSE_ROOT%\lib\libamd.lib" ^
-DSuiteSparse_CAMD_LIBRARY="%SUITESPARSE_ROOT%\lib\libcamd.lib" ^
-DSuiteSparse_CCOLAMD_LIBRARY="%SUITESPARSE_ROOT%\lib\libccolamd.lib" ^
-DSuiteSparse_CHOLMOD_LIBRARY="%SUITESPARSE_ROOT%\lib\libcholmod.lib" ^
-DSuiteSparse_COLAMD_LIBRARY="%SUITESPARSE_ROOT%\lib\libcolamd.lib" ^
-DSuiteSparse_Config_LIBRARY="%SUITESPARSE_ROOT%\lib\suitesparseconfig.lib" ^
-DSuiteSparse_SPQR_LIBRARY="%SUITESPARSE_ROOT%\lib\libspqr.lib" ^
-DINSTALL_TESTS=ON ^
-DINSTALL_C_EXAMPLES=ON ^
-DINSTALL_BIN_EXAMPLES=ON ^
-DINSTALL_PYTHON_EXAMPLES=ON ^
-DCUDA_FAST_MATH=ON ^
-DWITH_CUBLAS=ON ^
-DWITH_CUDNN=ON ^
-DWITH_NVCUVID=ON ^
-DOPENCV_DNN_CUDA=ON 
```

その後、ビルドを行ってインストールします
ビルドに1~2時間はかかったので、気長に待ちます

```
cmake --build . --config RELEASE
cmake --build . --config RELEASE --target INSTALL
```


ビルドが完了したら環境変数に追加します
管理者モードのコマンドプロンプトで実行

```
powershell -command "$oldpath = [System.Environment]::GetEnvironmentVariable(\"Path\", \"Machine\"); $oldpath += \";C:\opencv\x64\vc17\bin\"; [System.Environment]::SetEnvironmentVariable(\"Path\", $oldpath, \"Machine\")"
powershell -command "$oldpath = [System.Environment]::GetEnvironmentVariable(\"Path\", \"Machine\"); $oldpath += \";C:\opencv\bin\"; [System.Environment]::SetEnvironmentVariable(\"Path\", $oldpath, \"Machine\")"
powershell -command "$oldpath = [System.Environment]::GetEnvironmentVariable(\"LIB\", \"Machine\"); $oldpath += \";C:\opencv\x64\vc17\lib\"; [System.Environment]::SetEnvironmentVariable(\"LIB\", $oldpath, \"Machine\")"
powershell -command "[System.Environment]::SetEnvironmentVariable(\"OPENCV_ROOT\", \"c:\opencv\", \"Machine\")"
```
以下のコマンドを実行し、画像のような表示が出たら成功です
ファイルが存在しない場合、ビルドが失敗している可能性があります

```
dir "C:\Program Files\Python310\lib\site-packages\cv2"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779219/36ae3aa9-267f-394e-4412-d92c53841dc8.png)

pythonで以下のコマンドを実行すると、4.10.0-devが返ってくるはずです
```
import cv2
print( cv2.__version__ )
```

## 参考

細かい手順はこちらに書かれていますので、うまくいかない場合は参照してください。

https://www.kkaneko.jp/tools/win/windows_opencv.html