(CMake)WSLに公式OpenCVをやさしくインストール (C/C++, Python2, Python3)

関連記事：[やさしいWindows Subsystem for Linux (WSL) のインストール手順](https://qiita.com/kekenonono/items/1ddbb5a1125d496c0010)
#はじめに
WSL(Windows Subsystem for Linux)のUbuntuに**公式リリースのOpenCV4.1.2をmakeインストール**したので備忘録として残しておきます。

ターゲットとしては**OpenCVをC++で使いたい人**向けです。
Python2, Python3でも使えるようにインストールしますが、Pythonだけで使いたい人は`opencv-python`を入れれば簡単らしいので。
また、途中に出てくるコマンドの説明なども可能な限りしていこうと思います。

**OpenCVの公式ページ**([Installation in Linux](https://docs.opencv.org/4.1.2/d7/d9f/tutorial_linux_install.html)) を参考に進めていきます。

###バージョン
今回作業した環境は以下の通りでした。参考までに。
Windows 10 Home Version 1809
Ubuntu 18.04.3 LTS
OpenCV4.1.2-dev
Python 2.7.15+
Python 3.6.8

###概要
- 1. パッケージのインストール
    - 1.1 必須のパッケージ
    - 1.2 Python-devとnumpy
    - 1.3 オプション
- 2. OpenCVソースコードの入手
- 3. CMakeによるmakefileの作成
- 4. makeインストール
- 5. 動作確認（バージョンの表示）
    - 5.1 Python2
    - 5.2 Python3
    - 5.3 C++
        - 5.3.1 cmakeを使ってビルド
        - 5.3.2 pkg-configを使ってビルド
[](\- 6. 動作確認（顔認識）
    \- 6.1 Python2
    \- 6.2 Python3
    \- 6.3 C++)
- 6. その他
- 7. 参考

なお、**4.** の作業は待ち時間（30分程度）がかかりますので時間があるときに行ってください。 


#1. パッケージのインストール
公式ページ([Introduction to OpenCV](https://docs.opencv.org/4.1.2/d7/d9f/tutorial_linux_install.html))の**Required Packages**に該当する部分を実行していきます。
　
<details><summary<>下記**1.1**から**1.3**まで一気にインストールしたい方はこちら</summary><div>

```bash
$ sudo apt install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev libvtk5-qt4-dev libqt4-dev libqt4-opengl-dev libgtkglext1 libgtkglext1-dev python-dev python-numpy python3-dev python3-numpy
```
</div></details>

###1.1 必須のパッケージ
とりあえずこれさえあれば**OpenCVのインストール**をし、**C++で使用**することができます。
以下のコマンドを実行してパッケージをインストールしてください。

```bash
$ sudo apt install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
```

**各パッケージの説明**
**[build-essential](https://packages.ubuntu.com/disco/build-essential):** *gcc, g++といったコンパイラやmakeなど*
**[cmake](https://cmake.org/):** 今回はmakeビルドを行う際のmakefileを作成する目的で使用します。動作確認**5.3.1**の際にも使用しますのでこちら(https://kamino.hatenablog.com/entry/cmake_tutorial1) など参考にしてみてください。
**[git](https://git-scm.com/):** 今回はOpenCVのソースコードを入手する際にのみ使用しますが、興味がある方は[こちら](https://qiita.com/jesus_isao/items/63557eba36819faa4ad9)を参考にしてください。
**[libgtk2.0-dev](https://packages.debian.org/ja/jessie/libgtk2.0-dev):** [GTK](https://www.gtk.org/)ライブラリ開発用のパッケージらしいんですが、多分OpenCVのGUIフレームワーク関係
**[pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/):** gcc, g++によるコンパイルを容易にします。動作確認**5.3.2**で簡単に説明します。
**libavcodec-dev, libavformat-dev, libswscale-dev:** FFmpegとLibavの開発用パッケージです。

###1.2 Python-devとnumpy
Python2とPython3、およびそれぞれに対応する[numpy](https://ja.wikipedia.org/wiki/NumPy)をインストールします。

```bash
$ sudo apt install python-dev python-numpy python3-dev python3-numpy
```

:warning:**注意：  pythonとpython-devは異なります。もうpythonは入れてあるよって方も上記コマンドを実行しておいてください！**
（[python-dev](https://packages.ubuntu.com/disco/python-dev)はpythonを含む開発者用パッケージです。重複してインストールしても問題ないです。）

<details><summary>Pythonのバージョン確認</summary><div>

```bash
#Python2のバージョン確認
$ python -V

#Python3のバージョン確認
$ python3 -V
```

</div>
numpyのバージョンは**5.1**, **5.2**同様に\_\_version__で確認できます。</details>

###1.3 オプション
下記パッケージをインストールしなくてもOpenCVを使うことはできます。
必要なものを選んでインストールしてください。
迷ったらとりあえずインストールしておきましょう。

```bash
$ sudo apt install libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev libvtk5-qt4-dev libqt4-dev libqt4-opengl-dev libgtkglext1 libgtkglext1-dev
```

**各パッケージの説明**
**libtbb2, libtbb-dev:** TBB(Threading Building Blocks)によって並列処理を行えるようにする
**libjpeg-dev, libpng-dev, libtiff-dev:** jpeg, png, tiff形式の画像ファイルを扱えるようにする 
**libdc1394-22-dev:** IEEE1394 デジタルカメラ用の高レベルなプログラミングインターフェース
**libvtk5-qt4-dev, libqt4-dev, libqt4-opengl-dev, libgtkglext1, libgtkglext1-dev:** QT, OpenGL, GTKといったGUI関連のパッケージ

#2. OpenCVソースコードの入手
[こちらのリポジトリ(OpenCV)](https://github.com/opencv/opencv)と[こちらのリポジトリ(OpenCV contrib)](https://github.com/opencv/opencv_contrib)から、OpenCVとOpenCV contribのソースコードをホームディレクトリ直下に入れていきます。
（参考）[opencv_contrib紹介](https://www.atmarkit.co.jp/ait/articles/1709/12/news135.html)

```bash
#ホームディレクトリへ移動
$ cd ~

#OpenCVソースコードを入手
$ git clone https://github.com/opencv/opencv.git

#OpenCV contribソースコードを入手
$ git clone https://github.com/opencv/opencv_contrib.git
```

branchを切り替えたい場合（インストールしたいOpenCVのバージョンを変えたい場合など）は~/opencv下で`git checkout 2.4.0` などしてください。

#3. CMakeによるmakefileの作成
###3.1 build用のディレクトリ作成
以下のコマンドを実行し、~/opencv直下にbuild用のディレクトリ（ここではbuildという名前のディレクトリ）を作成してください。

```bash
$ cd ~/opencv
$ mkdir build
$ cd build
```

###3.2 CMakeの実行
[CMakeLists.txt](https://github.com/opencv/opencv/blob/master/CMakeLists.txt)を参考にオプションを設定しながらCMake (makeビルドを行う際のmakefileを作成) します。
下記コマンドを実行してください。

```bash
$ cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D WITH_OPENGL=ON -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules -D OPENCV_GENERATE_PKGCONFIG=ON ..
```

:warning:**注意１：  CMakeコマンド最後のtwo dots ` ..`を忘れないようにして下さい！**
（これは現在のディレクトリのひとつ上の階層を表しています。cmake実行時に参照するCMakeListsの場所を指定するためのものです。）

:warning:**注意２：  もし上記コマンドがうまくいかない場合は`-DCMAKE_BUILD_TYPE=Release`のように-Dの後ろのスペースをすべて削除して再度試してみてください**
（-DはCMakeのオプションで、書き換えを意味します。）

**オプションの説明**
**CMAKE_BUILD_TYPE**: ビルド時のモードを指定
**CMAKE_INSTALL_PREFIX**: インストール先の指定
**OPENCV_EXTRA_MODULES_PATH**: OpenCV_contribのパスを指定
**OPENCV_GENERATE_PKGCONFIG**: pkgconfigに.pcファイルを作成（C++のコンパイル時に利用）
**WITH_TBB**: TBB（Threading Building Blocks）の利用（C++を並列処理で実行する）
**WITH_OPENGL**: OPENGLの利用
**WITH_VTK**: VTKの利用

<details><summary>CMake実行結果</summary><div>
ここまで上記手順通りに行うと、以下のような実行結果になると思います。

```bash
-- General configuration for OpenCV 4.1.2-dev =====================================
--   Version control:               4.1.2-121-g5dd3e6052e
--
--   Extra modules:
--     Location (extra):            /home/(ユーザー名)/opencv_contrib/modules
--     Version control (extra):     4.1.2-32-g61cbb445
--
--   Platform:
--     Timestamp:                   2019-11-10T16:00:51Z
--     Host:                        Linux 4.4.0-17763-Microsoft x86_64
--     CMake:                       3.10.2
--     CMake generator:             Unix Makefiles
--     CMake build tool:            /usr/bin/make
--     Configuration:               Release
--
--   CPU/HW features:
--     Baseline:                    SSE SSE2 SSE3
--       requested:                 SSE3
--     Dispatched code generation:  SSE4_1 SSE4_2 FP16 AVX AVX2 AVX512_SKX
--       requested:                 SSE4_1 SSE4_2 AVX FP16 AVX2 AVX512_SKX
--       SSE4_1 (16 files):         + SSSE3 SSE4_1
--       SSE4_2 (2 files):          + SSSE3 SSE4_1 POPCNT SSE4_2
--       FP16 (1 files):            + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 AVX
--       AVX (5 files):             + SSSE3 SSE4_1 POPCNT SSE4_2 AVX
--       AVX2 (29 files):           + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2
--       AVX512_SKX (6 files):      + SSSE3 SSE4_1 POPCNT SSE4_2 FP16 FMA3 AVX AVX2 AVX_512F AVX512_COMMON AVX512_SKX
--
--   C/C++:
--     Built as dynamic libs?:      YES
--     C++ Compiler:                /usr/bin/c++  (ver 7.4.0)
--     C++ flags (Release):         -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -msse -msse2 -msse3 -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG  -DNDEBUG
--     C++ flags (Debug):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-delete-non-virtual-dtor -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -msse -msse2 -msse3 -fvisibility=hidden -fvisibility-inlines-hidden -g  -O0 -DDEBUG -D_DEBUG
--     C Compiler:                  /usr/bin/cc
--     C flags (Release):           -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -msse -msse2 -msse3 -fvisibility=hidden -O3 -DNDEBUG  -DNDEBUG
--     C flags (Debug):             -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wuninitialized -Winit-self -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -Wno-long-long -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections  -msse -msse2 -msse3 -fvisibility=hidden -g  -O0 -DDEBUG -D_DEBUG
--     Linker flags (Release):      -Wl,--gc-sections
--     Linker flags (Debug):        -Wl,--gc-sections
--     ccache:                      NO
--     Precompiled headers:         NO
--     Extra dependencies:          dl m pthread rt /usr/lib/x86_64-linux-gnu/libGL.so /usr/lib/x86_64-linux-gnu/libGLU.so
--     3rdparty dependencies:
--
--   OpenCV modules:
--     To be built:                 aruco bgsegm bioinspired calib3d ccalib core datasets dnn dnn_objdetect dnn_superres dpm face features2d flann freetype fuzzy gapi hdf hfs highgui img_hash imgcodecs imgproc line_descriptor ml objdetect optflow phase_unwrapping photo plot python2 python3 quality reg rgbd saliency shape stereo stitching structured_light superres surface_matching text tracking ts video videoio videostab viz xfeatures2d ximgproc xobjdetect xphoto
--     Disabled:                    world
--     Disabled by dependency:      -
--     Unavailable:                 cnn_3dobj cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev cvv java js matlab ovis sfm
--     Applications:                tests perf_tests apps
--     Documentation:               NO
--     Non-free algorithms:         NO
--
--   GUI:
--     GTK+:                        YES (ver 2.24.32)
--       GThread :                  YES (ver 2.56.4)
--       GtkGlExt:                  YES (ver 1.2.0)
--     OpenGL support:              YES (/usr/lib/x86_64-linux-gnu/libGL.so /usr/lib/x86_64-linux-gnu/libGLU.so)
--     VTK support:                 YES (ver 7.1.1)
--
--   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:                         /usr/lib/x86_64-linux-gnu/libpng.so (ver 1.6.34)
--     TIFF:                        /usr/lib/x86_64-linux-gnu/libtiff.so (ver 42 / 4.0.9)
--     JPEG 2000:                   build (ver 1.900.1)
--     OpenEXR:                     build (ver 2.3.0)
--     HDR:                         YES
--     SUNRASTER:                   YES
--     PXM:                         YES
--     PFM:                         YES
--
--   Video I/O:
--     DC1394:                      YES (2.2.5)
--     FFMPEG:                      YES
--       avcodec:                   YES (57.107.100)
--       avformat:                  YES (57.83.100)
--       avutil:                    YES (55.78.100)
--       swscale:                   YES (4.8.100)
--       avresample:                NO
--     GStreamer:                   NO
--     v4l/v4l2:                    YES (linux/videodev2.h)
--
--   Parallel framework:            TBB (ver 2017.0 interface 9107)
--
--   Trace:                         YES (with Intel ITT)
--
--   Other third-party libraries:
--     Intel IPP:                   2019.0.0 Gold [2019.0.0]
--            at:                   /home/(ユーザー名)/opencv/build/3rdparty/ippicv/ippicv_lnx/icv
--     Intel IPP IW:                sources (2019.0.0)
--               at:                /home/(ユーザー名)/opencv/build/3rdparty/ippicv/ippicv_lnx/iw
--     Lapack:                      NO
--     Eigen:                       YES (ver 3.3.4)
--     Custom HAL:                  NO
--     Protobuf:                    build (3.5.1)
--
--   OpenCL:                        YES (no extra features)
--     Include path:                /home/(ユーザー名)/opencv/3rdparty/include/opencl/1.2
--     Link libraries:              Dynamic load
--
--   Python 2:
--     Interpreter:                 /usr/bin/python2.7 (ver 2.7.15)
--     Libraries:                   /usr/lib/x86_64-linux-gnu/libpython2.7.so (ver 2.7.15+)
--     numpy:                       /usr/lib/python2.7/dist-packages/numpy/core/include (ver 1.13.3)
--     install path:                lib/python2.7/dist-packages/cv2/python-2.7
--
--   Python 3:
--     Interpreter:                 /usr/bin/python3 (ver 3.6.8)
--     Libraries:                   /usr/lib/x86_64-linux-gnu/libpython3.6m.so (ver 3.6.8)
--     numpy:                       /usr/lib/python3/dist-packages/numpy/core/include (ver 1.13.3)
--     install path:                lib/python3.6/dist-packages/cv2/python-3.6
--
--   Python (for build):            /usr/bin/python2.7
--
--   Java:
--     ant:                         NO
--     JNI:                         NO
--     Java wrappers:               NO
--     Java tests:                  NO
--
--   Install to:                    /usr/local
-- -----------------------------------------------------------------
--
-- Configuring done
-- Generating done
-- Build files have been written to: /home/(ユーザー名)/opencv/build
```

</div>
</details>
**↑**を見るとpython2, python3それぞれの`dist-packages/`以下にcv2がインストールされているのがわかります。

#4. makeインストール
[make](https://qiita.com/chihiro/items/f270744d7e09c58a50a5)ビルドします。`-j*`はmakeコマンドのオプションで、makeビルドを並列処理します。
以下のコマンドを実行してください。30分くらいかかるかも。
（[公式ページ](https://docs.opencv.org/4.1.2/d7/d9f/tutorial_linux_install.html)に合わせて並列オプションは7に設定）

```bash
$ make -j7
```

続いてmake installです。
以下のコマンドを実行してください。

```bash
$ sudo make install
```

以上でインストール完了です！

#5. 動作確認（バージョンの表示）
Python2, Python3に関してはすでにパスが通っていると思うので簡単です。
C++に関してはCMakeでMakefileを作るかpkg-configでパスを通すかします。

以下はすべて`~/opencv`直下で実行することを前提とします。
`cd ~/opencv` でホームディレクトリに移動してください。

###5.1 Python2
コマンドラインからPythonを起動して対話モードでバージョンを表示させます。
([コマンドラインからのPython実行](https://web-camp.io/magazine/archives/15363))

まずPython2の対話モードを起動します。

```bash
$ python2 #対話モードの起動
```

つづいて対話モードでOpenCVをインポート、OpenCVのバージョンを表示させます。

```bash
>> import cv2 #OpenCVのインポート
>> print(cv2.__version__) #バージョンの表示
```

これでインストールしたOpenCVのバージョンが表示されたら動作確認完了です。対話モードを終了させます。

```bash
>> exit() #対話モードの終了
```

###5.2 Python3
**5.1** ``python2``の動作確認と全く同じことを`python3`で実行できればOKです。

###5.3 C++
CMakeを使う方法とpkg-configを使う方法を書いていたら意外と長くなってしまったので別記事に載せます。
[OpenCVを使ったC++コードをコンパイルする（CMake, GCC, pkg-config）](https://qiita.com/kekenonono/items/0fcf042bca2d3d17867a)


[](\#6. 動作確認（顔認識）
\###6.1 Python2
\###6.2 Python3
\###6.3 C++)

#6. その他
OpenCVを使えば画像認識などが捗ることはもちろん、様々な形式の画像ファイルを扱うのもとても簡単になるのが良いですよね。

本当は動作確認のためにバージョン表示に加えてもっとopencvっぽいことをしようとしたのですが、疲れたので今度にします

#7. 参考

パッケージの内容検索（https://packages.ubuntu.com/ja/）
CMakeの使い方 その１～３（https://qiita.com/shohirose/items/45fb49c6b429e8b204ac#_reference-27dce2bd429efef9488e）