OpenCV 4とOpenCV 5の共存はメンドクサイ（できるけど）

この記事は[OpenCV Advent Calendar 2020](https://qiita.com/advent-calendar/2020/opencv)の16日目の代打記事です．

時空列がゆがんでいますが、まあ気にせず！！

# TL;DR
- OpenCV4 と OpenCV5の共存はめんどくさいです。
    - `CMAKE_INSTALL_PREFIX`でインストール先をずらす。
    - `export PKG_CONFIG_PATH=/usr/local_opencv5/lib/pkgconfig` でpkg-configにopencv5.pcの場所を教える。
    - `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local_opencv5/lib` で実行時にshared libraryの場所を教える。

以上です！

## pkg-configが使えるオプションを有効化しています（ポイント★）

昔ながらの人なので、pkg-configでコンパイル時指定をやってます。そういう人向けの説明ですね……

## cmake 派の方は…

@dandelion1124 先生から、CMakeを使っている方は、CMAKE_INSTALL_PREFIXを変える＋OpenCV_DIRの指定切り替えでやると良いとのことです！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ありがとうございました！（Qiitaの謎ルールが明らかになった）記事のやつはCMake使っているのであればCMAKE_INSTALL_PREFIXでインストール先を変えて、OpenCV使う側ではOpenCV_DIRで所望のOpenCVバージョンのパスを指定するのでもよさそうです。</p>&mdash; dandelion (@dandelion1124) <a href="https://twitter.com/dandelion1124/status/1340162506573062147?ref_src=twsrc%5Etfw">December 19, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# はじめに

「OpenCVのputText()関数が、next branch(OpenCV5)でどうやらTrueTypeになるらしい！」と聞いたので、
さっそく画像をだしてみようと思いました。

なのですが、同じタイミングで、OpenCV4とOpenCV5それぞれをリンクした実行ファイルの結果が同じになってしまった」ので、なんだこれーと調査をしました。

# 最初の状態

OpenCVがインストールされていない環境を用意します。

```bash
kmtr@ubuntu2010:~/work$ pkg-config --list-all | grep open
caf-openmpi                    CAF - Co-Array Fortran support
hdf5                           HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
hdf5-mpi                       HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
hdf5-openmpi                   HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
libevent_openssl               libevent_openssl - libevent_openssl adds openssl-based TLS support to libevent
libopenjp2                     openjp2 - JPEG2000 library (Part 1 and 2)
libopenjp3d                    openjp3d - JPEG2000 Extensions for three-dimensional data (Part 10)
libopenjpip                    openjpip - JPEG2000 Interactivity tools, APIs and protocols (Part 9)
opengl                         OpenGL - OpenGL (without GLX) library and headers.
openssl                        OpenSSL - Secure Sockets Layer and cryptography libraries and tools
```

# OpenCV 4.5.0 をインストールしてみる。

```bash
kmtr@ubuntu2010:~/work/opencv-4.5.0/build$ pkg-config --list-all | grep open
caf-openmpi                    CAF - Co-Array Fortran support
hdf5                           HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
hdf5-mpi                       HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
hdf5-openmpi                   HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
libevent_openssl               libevent_openssl - libevent_openssl adds openssl-based TLS support to libevent
libopenjp2                     openjp2 - JPEG2000 library (Part 1 and 2)
libopenjp3d                    openjp3d - JPEG2000 Extensions for three-dimensional data (Part 10)
libopenjpip                    openjpip - JPEG2000 Interactivity tools, APIs and protocols (Part 9)
opencv4                        OpenCV - Open Source Computer Vision Library
opengl                         OpenGL - OpenGL (without GLX) library and headers.
openssl                        OpenSSL - Secure Sockets Layer and cryptography libraries and tools
```

```
kmtr@ubuntu2010:~/work/opencv-4.5.0/build$ pkg-config opencv4 --cflags --libs
-I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core
```

# 4.5.0がはいったまま、nextを入れてみる。

おお、pkg-configを見ると両方が入った！

インクルードパスも分かれている！こりゃ共存できる・・・？

```
kmtr@ubuntu2010:~/work/opencv_next/build$ pkg-config --list-all | grep open
caf-openmpi                    CAF - Co-Array Fortran support
hdf5                           HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
hdf5-mpi                       HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
hdf5-openmpi                   HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
libevent_openssl               libevent_openssl - libevent_openssl adds openssl-based TLS support to libevent
libopenjp2                     openjp2 - JPEG2000 library (Part 1 and 2)
libopenjp3d                    openjp3d - JPEG2000 Extensions for three-dimensional data (Part 10)
libopenjpip                    openjpip - JPEG2000 Interactivity tools, APIs and protocols (Part 9)
opencv4                        OpenCV - Open Source Computer Vision Library
opencv5                        OpenCV - Open Source Computer Vision Library
opengl                         OpenGL - OpenGL (without GLX) library and headers.
openssl                        OpenSSL - Secure Sockets Layer and cryptography libraries and tools
kmtr@ubuntu2010:~/work/opencv_next/build$ pkg-config opencv4 --cflags --libs
-I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core
kmtr@ubuntu2010:~/work/opencv_next/build$ pkg-config opencv5 --cflags --libs
-I/usr/local/include/opencv5 -L/usr/local/lib -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_dnn -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core
```

# ダメです、（そのままだと）共存できていません。

お気づきでしょうか……

確かに `-I/usr/local/include/opencv4`と`-I/usr/local/include/opencv5` となっているのでヘッダファイルは分かれている。

でも、`/usr/local/lib`なので、ライブラリは…？

```
kmtr@ubuntu2010:~/work/opencv_next/build$ ls /usr/local/lib/libopen* -al | sort -k 9 | head -10
lrwxrwxrwx 1 root root       24 12月 19 13:13 /usr/local/lib/libopencv_calib3d.so -> libopencv_calib3d.so.5.0
lrwxrwxrwx 1 root root       26 12月 19 13:10 /usr/local/lib/libopencv_calib3d.so.4.5 -> libopencv_calib3d.so.4.5.0
-rw-r--r-- 1 root root 81930880 11月 10 19:33 /usr/local/lib/libopencv_calib3d.so.4.5.0
lrwxrwxrwx 1 root root       26 12月 19 13:13 /usr/local/lib/libopencv_calib3d.so.5.0 -> libopencv_calib3d.so.5.0.0
-rw-r--r-- 1 root root  2739928 12月  2 05:15 /usr/local/lib/libopencv_calib3d.so.5.0.0
lrwxrwxrwx 1 root root       21 12月 19 13:13 /usr/local/lib/libopencv_core.so -> libopencv_core.so.5.0
lrwxrwxrwx 1 root root       23 12月 19 13:10 /usr/local/lib/libopencv_core.so.4.5 -> libopencv_core.so.4.5.0
-rw-r--r-- 1 root root 57626288 11月 10 19:33 /usr/local/lib/libopencv_core.so.4.5.0
lrwxrwxrwx 1 root root       23 12月 19 13:13 /usr/local/lib/libopencv_core.so.5.0 -> libopencv_core.so.5.0.0
-rw-r--r-- 1 root root 17690544 12月  2 05:11 /usr/local/lib/libopencv_core.so.5.0.0
```

つまり、あとからインストールしたnext(OpenCV5)の設定の方が勝ってしまっていますね……

まあ、使うときに毎回、`sudo make install`して、`libopencv_XXX.so`の参照先を書き換えればいいんですが、めどい。

```
-lopencv_core
　⇒ /usr/local/lib/libopencv_core.so
　　⇒ /usr/local/lib/libopencv_core.so.5.0
　　　⇒ /usr/local/lib/libopencv_core.so.5.0.0

　　　 /usr/local/lib/libopencv_core.so.4.5
　　　⇒ /usr/local/lib/libopencv_core.so.4.5.0
```

# じゃあどうすれば共存できるの？（かなり強引な解決策）

CMAKE_INSTALL_PREFIXを書き換えてみると行けるかなー

例えばこの例では、`/usr/local_opencv5` という謎prefixをインストール先に指定してみている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89434/9a5021b0-ce75-667f-9f54-0db66e1a437e.png)

この場合、特殊なprefixを付けたので、pkg-configが困らないように場所を追加してあげる必要がある。

```bash
export PKG_CONFIG_PATH=/usr/local_opencv5/lib/pkgconfig 
```

## インストールも無事にできた。

```
kmtr@ubuntu2010:~/work/opencv_next/build$ pkg-config --list-all | grep open
caf-openmpi                    CAF - Co-Array Fortran support
hdf5                           HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
hdf5-mpi                       HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
hdf5-openmpi                   HDF5 - Hierarchical Data Format 5 (HDF5) - openmpi version
libevent_openssl               libevent_openssl - libevent_openssl adds openssl-based TLS support to libevent
libopenjp2                     openjp2 - JPEG2000 library (Part 1 and 2)
libopenjp3d                    openjp3d - JPEG2000 Extensions for three-dimensional data (Part 10)
libopenjpip                    openjpip - JPEG2000 Interactivity tools, APIs and protocols (Part 9)
opencv4                        OpenCV - Open Source Computer Vision Library
opencv5                        OpenCV - Open Source Computer Vision Library
opengl                         OpenGL - OpenGL (without GLX) library and headers.
openssl                        OpenSSL - Secure Sockets Layer and cryptography libraries and tools
```

## ライブラリの配置もばっちり

```bash
kmtr@ubuntu2010:~/work/opencv_next/build$ ls /usr/local/lib/libopen* -al | sort -k 9 | head -10
lrwxrwxrwx 1 root root       24 12月 19 13:23 /usr/local/lib/libopencv_calib3d.so -> libopencv_calib3d.so.4.5
lrwxrwxrwx 1 root root       26 12月 19 13:10 /usr/local/lib/libopencv_calib3d.so.4.5 -> libopencv_calib3d.so.4.5.0
-rw-r--r-- 1 root root 81930880 11月 10 19:33 /usr/local/lib/libopencv_calib3d.so.4.5.0
lrwxrwxrwx 1 root root       21 12月 19 13:23 /usr/local/lib/libopencv_core.so -> libopencv_core.so.4.5
lrwxrwxrwx 1 root root       23 12月 19 13:10 /usr/local/lib/libopencv_core.so.4.5 -> libopencv_core.so.4.5.0
-rw-r--r-- 1 root root 57626288 11月 10 19:33 /usr/local/lib/libopencv_core.so.4.5.0
lrwxrwxrwx 1 root root       22 11月  9 22:01 /usr/local/lib/libopencv_dnn.so.4.5 -> libopencv_dnn.so.4.5.0
-rw-r--r-- 1 root root 45255184 11月 10 06:02 /usr/local/lib/libopencv_dnn.so.4.5.0
lrwxrwxrwx 1 root root       27 12月 19 13:23 /usr/local/lib/libopencv_features2d.so -> libopencv_features2d.so.4.5
lrwxrwxrwx 1 root root       29 12月 19 13:10 /usr/local/lib/libopencv_features2d.so.4.5 -> libopencv_features2d.so.4.5.0
kmtr@ubuntu2010:~/work/opencv_next/build$ ls /usr/local_opencv5/lib/libopen* -al | sort -k 9 | head -10
lrwxrwxrwx 1 root root       24 12月 19 13:27 /usr/local_opencv5/lib/libopencv_calib3d.so -> libopencv_calib3d.so.5.0
lrwxrwxrwx 1 root root       26 12月 19 13:27 /usr/local_opencv5/lib/libopencv_calib3d.so.5.0 -> libopencv_calib3d.so.5.0.0
-rw-r--r-- 1 root root  2739928 12月 19 13:26 /usr/local_opencv5/lib/libopencv_calib3d.so.5.0.0
lrwxrwxrwx 1 root root       21 12月 19 13:27 /usr/local_opencv5/lib/libopencv_core.so -> libopencv_core.so.5.0
lrwxrwxrwx 1 root root       23 12月 19 13:27 /usr/local_opencv5/lib/libopencv_core.so.5.0 -> libopencv_core.so.5.0.0
-rw-r--r-- 1 root root 17690544 12月 19 13:26 /usr/local_opencv5/lib/libopencv_core.so.5.0.0
lrwxrwxrwx 1 root root       20 12月 19 13:27 /usr/local_opencv5/lib/libopencv_dnn.so -> libopencv_dnn.so.5.0
lrwxrwxrwx 1 root root       22 12月 19 13:27 /usr/local_opencv5/lib/libopencv_dnn.so.5.0 -> libopencv_dnn.so.5.0.0
-rw-r--r-- 1 root root  5969384 12月 19 13:26 /usr/local_opencv5/lib/libopencv_dnn.so.5.0.0
lrwxrwxrwx 1 root root       27 12月 19 13:27 /usr/local_opencv5/lib/libopencv_features2d.so -> libopencv_features2d.so.5.0
```

## pkg-configの指定先もオッケー

```
kmtr@ubuntu2010:~/work/opencv_next/build$ pkg-config opencv4 --cflags --libs
-I/usr/local/include/opencv4 -L/usr/local/lib -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core
kmtr@ubuntu2010:~/work/opencv_next/build$ pkg-config opencv5 --cflags --libs
-I/usr/local_opencv5/include/opencv5 -L/usr/local_opencv5/lib -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_dnn -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core

```

## shared libraryのサーチパスも追加すればオッケー

```
kmtr@ubuntu2010:~/work/stb$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local_opencv5/lib
kmtr@ubuntu2010:~/work/stb$ ldd ./a_next.out
        linux-vdso.so.1 (0x00007ffc5a7c4000)
        libopencv_imgcodecs.so.5.0 => /usr/local_opencv5/lib/libopencv_imgcodecs.so.5.0 (0x00007f44cb269000)
        libopencv_imgproc.so.5.0 => /usr/local_opencv5/lib/libopencv_imgproc.so.5.0 (0x00007f44c94fd000)
        libopencv_core.so.5.0 => /usr/local_opencv5/lib/libopencv_core.so.5.0 (0x00007f44c8566000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f44c8358000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f44c833d000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f44c8153000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f44c812f000)
        libjpeg.so.8 => /lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f44c80aa000)
        libwebp.so.6 => /lib/x86_64-linux-gnu/libwebp.so.6 (0x00007f44c7e41000)
        libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f44c7e08000)
        libtiff.so.5 => /lib/x86_64-linux-gnu/libtiff.so.5 (0x00007f44c7d87000)
        libopenjp2.so.7 => /lib/x86_64-linux-gnu/libopenjp2.so.7 (0x00007f44c7d31000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f44c7be0000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f44c7bc3000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f44cb43a000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f44c7bbd000)
        liblapack.so.3 => /lib/x86_64-linux-gnu/liblapack.so.3 (0x00007f44c751a000)
        libblas.so.3 => /lib/x86_64-linux-gnu/libblas.so.3 (0x00007f44c74ad000)
        libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x00007f44c73db000)
        liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f44c73b2000)
        libjbig.so.0 => /lib/x86_64-linux-gnu/libjbig.so.0 (0x00007f44c71a4000)
        libgfortran.so.5 => /lib/x86_64-linux-gnu/libgfortran.so.5 (0x00007f44c6edc000)
        libquadmath.so.0 => /lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007f44c6e92000)
```

## ちゃんと使うべきライブラリが指定されている。

### OpenCV 4
```
kmtr@ubuntu2010:~/work/stb$ strace ./a_45.out 2>&1 | grep openat | grep "opencv" | grep -v ENOENT
openat(AT_FDCWD, "/usr/local/lib/libopencv_imgcodecs.so.4.5", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/local/lib/libopencv_imgproc.so.4.5", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/local/lib/libopencv_core.so.4.5", O_RDONLY|O_CLOEXEC) = 3
```

### OpenCV 5

```
kmtr@ubuntu2010:~/work/stb$ strace ./a_next.out 2>&1 | grep openat | grep "opencv5" | grep -v ENOENT
openat(AT_FDCWD, "/usr/local_opencv5/lib/libopencv_imgcodecs.so.5.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/local_opencv5/lib/libopencv_imgproc.so.5.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/local_opencv5/lib/libopencv_core.so.5.0", O_RDONLY|O_CLOEXEC) = 3
```

# まとめ
- OpenCV4 と OpenCV5の共存はめんどくさいです。
    - `CMAKE_INSTALL_PREFIX`でインストール先をずらす。
    - `export PKG_CONFIG_PATH=/usr/local_opencv5/lib/pkgconfig` でpkg-configにopencv5.pcの場所を教える。
    - `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local_opencv5/lib` で実行時にshared libraryの場所を教える。

ご精読ありがとうございました！！ 以上となります。