OpenCVインストール構成の変遷（OpenCV 3.4.3，3.4.4，4.0.0）

## はじめに
* この記事は[OpenCV Advent Calendar 2018](http://qiita.com/advent-calendar/2018/opencv)の1日目の記事です．
* 他の記事は[目次](https://qiita.com/advent-calendar/2018/opencv)にまとめられています．

みんなが心待ちにしていたOpenCV 4.0が先日リリースされましたね．また，ほぼ同タイミングでOpenCV 3.4.4もリリースされました．これらのバージョンでこれまでとOpenCVのインストール構成が変わっていることに~~たまたま~~気付いたので情報共有も兼ねて記事にしたいと思います．

## 動作確認環境
筆者は以下の環境で動作確認しました．

### OS
- Ubuntu 18.04 64bit

### CMake
- 3.10.2

### コンパイラ
- gcc 7.3.0

### OpenCV
- [OpenCV 3.4.3](https://github.com/opencv/opencv/releases/tag/3.4.3)
- [OpenCV 3.4.4](https://github.com/opencv/opencv/releases/tag/3.4.4)
- [OpenCV 4.0.0](https://github.com/opencv/opencv/releases/tag/4.0.0)

## インストール構成の違い
以降は`CMAKE_INSTALL_PREFIX`がデフォルト（`/usr/local`）のままであることを前提に説明します．

### OpenCV 3.4.3 vs OpenCV 3.4.4
OpenCV 3.4.3，OpenCV 3.4.4での各種インストール構成を下表にまとめます（**太字**の箇所が変更点）．  

| |OpenCV 3.4.3 | OpenCV 3.4.4 |
|---|---|---|
| インクルードパス | `/usr/local/include/opencv`<br>`/usr/local/include/opencv2` | `/usr/local/include/opencv`<br>`/usr/local/include/opencv2` |
| ライブラリパス | `/usr/local/lib` | `/usr/local/lib` |
| Pythonライブラリパス| `/usr/local/lib/python3.6/dist-packages` | **`/usr/local/python/cv2/python-3.6`** |
| バイナリ（アプリ） | `/usr/local/bin` | `/usr/local/bin` |
| `OpenCV_DIR` | `/usr/local/share/OpenCV` | `/usr/local/share/OpenCV` |

あー，3.4.4からPythonライブラリパスが謎の場所に移動しているので`PYTHONPATH`を通す必要があるわけですね（初見殺しなのでやめて）．

気付かないと漏れなくこういうことになります．  
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">python bindingでimport cv2が失敗するな？🤔と思ったら/usr/local/python/cv2/python-3.5/にcv2.cpython-35m-x86_64-linux-gnu.soが配置されている（けどパスを通していない）せいだった・・・</p>&mdash; dandelion (@dandelion1124) <a href="https://twitter.com/dandelion1124/status/1064165729556029442?ref_src=twsrc%5Etfw">2018年11月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

### OpenCV 3.4.4 vs OpenCV 4.0.0
OpenCV 3.4.4，OpenCV 4.0.0での各種インストール構成を下表にまとめます（**太字**の箇所が変更点）．  

| |OpenCV 3.4.4 | OpenCV 4.0.0 |
|---|---|---|
| インクルードパス | `/usr/local/include/opencv`<br>`/usr/local/include/opencv2` | **`/usr/local/include/opencv4/opencv2`** |
| ライブラリパス | `/usr/local/lib` | `/usr/local/lib` |
| Pythonライブラリパス| `/usr/local/python/cv2/python-3.6` | `/usr/local/python/cv2/python-3.6` |
| バイナリ（アプリ） | `/usr/local/bin` | `/usr/local/bin` |
| `OpenCV_DIR` | `/usr/local/share/OpenCV` | **`/usr/local/lib/cmake/opencv4/`** |

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">インストール後のヘッダファイルがあるディレクトリが/usr/local/include/opencv4/opencv2/という「おまえは何を言っているんだ」という感じになっているのは一体・・・</p>&mdash; dandelion (@dandelion1124) <a href="https://twitter.com/dandelion1124/status/1064166647081054214?ref_src=twsrc%5Etfw">2018年11月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

という感想が出てもおかしくない大変歪なディレクトリ構成になっていることがわかります（OpenCV 2.xのタイミングでインクルードディレクトリを`opencv2`としてしまった罪は重い・・・）．また，OpenCV 4.0.0からC APIが削除されたので`/usr/local/include/opencv`がなくなっています．

さらにOpenCV 4.0.0から`OpenCV_DIR`も変わっているのでCMakeで`find_package(OpenCV)`としたときにちゃんと検出してくれるのか不安で眠れなくなる読者もいるかもしれません．結論から述べると`CMAKE_INSTALL_PREFIX`がデフォルト（`/usr/local`）のままであればこんな感じで特に問題無く検出してくれます（やったね！）．

```shell

-- Found OpenCV: /usr/local (found version "4.0.0")
```

ただし，OpenCVのビルド時に`CMAKE_INSTALL_PREFIX`をカスタマイズした場合，OpenCVを使ったプログラムのCMake実行時に以下のオプションを付与する必要があります（最初，`OpenCVConfig.cmake`がどこに配置されているのかわからなくて混乱した・・・）．

```shell
-D OpenCV_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/opencv4
```

## おまけ（OpenCV 3系，OpenCV 4系両対応）
[Transition guide](https://docs.opencv.org/3.4/db/dfa/tutorial_transition_guide.html#tutorial_transition_both)にはOpenCV 2.4系，OpenCV 3系の両バージョンに対応する方法が記載されています．

OpenCV 3系はこれからもしばらく使われることが予想されるのでOpenCV 3系，OpenCV 4系両対応をこれまでと同じようにできるか不安で眠れなくなる読者もいるかもしれません．結論から述べるとこれまでと同様の対応で大丈夫です．以下にソースコード，CMakeレベルでの対応方法を示します．

### ソースコード
```cpp
#include <opencv2/core/version.hpp>

#if CV_MAJOR_VERSION == 3
// OpenCV 3系の処理を書く
#elif CV_MAJOR_VERSION == 4
// OpenCV 4系の処理を書く
#endif
```

### CMake
```cmake
find_package(OpenCV REQUIRED)

if(OpenCV_VERSION VERSION_LESS "4.0")
# use 3.x modules
else()
# use 4.x modules
endif()
```

## おわりに
この記事ではOpenCV 3.4.3，3.4.4，4.0.0でのバージョン間のインストール構成の差異について紹介しました．この記事がOpenCV 4系へのスムーズな移行の助けになれば幸いです．  
明日は[tomoaki_teshima](https://twitter.com/tomoaki_teshima)さんの記事で，タイトルは<b>「cv::waitKeyは遅いよね」</b>となっています．とてつもなくテクい話が読めそうなのですごく楽しみです！！