想像以上に手間取りました。かたりぃなです。
OpenCVのバージョンだけなら大した問題ではなかったのですが、バージョンアップに追従してC++も新しいものにしていこうという動きがあるみたいです。 (実際OpenCV3の世代でCインターフェースはレガシーなものとして切り捨てられましたし。)
さらに4.0になってからはOpenCV自体をビルドするCMakeも要求バージョンが上がっていて、これもビルドしなおす必要があります。
CMakeもビルド自体は簡単なのですが、CMakeをビルドするためには新しいlibcが必要になっています。
新しいlibcが必要ということはgcc自体のアップデートが必要になるということです。
私がよく使うCentOSはgccがかなり古いバージョンしか入っていないので、gccからビルドしなおす必要があるということです。
ついにこの時が来てしまったかといった感じですね。。。
というわけで、次の順にやっていきます。
- gcc8.1のビルドとインストール
- CMake3.13のビルドとインストール
- OpenCV4.0のビルドとインストール
なんか大変なことになってしまいましたが、gcc8までいくとC++20も多少は使えるようになるので、未来志向で前向きにいきたいと思います。
環境はいつものです
- Windows10Pro
- Docker for windows
- centos7ベース
躓いたポイント
cmake/opencvとも、いつものようにビルドすればいいのですが一点だけ注意。
cmakeが参照するcurlがhttps対応してない問題というのがあるらしいです。
要約すると、opencvのビルド時に追加で必要なファイルをダウンロードしてきたりしているところで面倒な問題があるようです。
追加ライブラリののダウンロードにcurlが使われるのですが、cmakeはシステム組み込みのcurlではなくcmake自信が持っているcurlを使うようになっています。(デフォルトの動作)
これだけなら大したことないのですが、cmakeが持っているcurlと不随するライブラリが古いらしく、httpsサイトからのダウンロードに失敗します。(SSLの一部をサポートしていないため)
これがopencvのbuild時に発覚するので、ビルド時間の長さも相まって手戻りが半端なかったです。
環境構築のためのdockerfileはベタ書きしたので、他の環境でやるときも手順書の代わりになるかと思うので、次回以降はビルドやり直しの手間は減るかなと思います。
docker-file
まずは答えから。
インストールするものをまとめてコンテナ化するdockerfileになります。
ひたすらコマンドを実行するだけのものです。
RUN yum groupinstall -y 'Development tools' RUN yum install -y git wget cmake RUN yum install -y sudo # cmakeのためにlibcとgccを入れる(C++最新を使いたい) RUN wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-8.1.0/gcc-8.1.0.tar.gz RUN tar zxvf gcc-8.1.0.tar.gz RUN cd gcc-8.1.0; ./contrib/download_prerequisites; mkdir build RUN cd gcc-8.1.0; ./configure --enable-languages=c,c++ --prefix=/usr/local --disable-bootstrap --disable-multilib; make; RUN cd gcc-8.1.0; make install RUN cp gcc-8.1.0/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.25 /usr/lib64/ # libcのバックアップとインストール RUN mv /usr/lib64/libstdc++.so.6 /usr/lib64/libstdc++.so.6.backup RUN ln -s /usr/lib64/libstdc++.so.6.0.25 /usr/lib64/libstdc++.so.6 RUN rm gcc-8.1.0.tar.gz # opencv4のためにcmake 3.5以上が欲しい RUN yum install -y git wget cmake RUN yum install -y sudo curl-devel zlib-devel RUN wget https://gitlab.kitware.com/cmake/cmake/-/archive/v3.13.4/cmake-v3.13.4.tar.gz RUN tar zxvf cmake-v3.13.4.tar.gz RUN cd cmake-v3.13.4; ./bootstrap --system-curl && make && make install RUN mv /bin/cmake /bin/cmake.backup RUN ln -s /usr/local/bin/cmake /bin/cmake RUN rm cmake-v3.13.4.tar.gz # c++ opencv RUN git clone https://github.com/opencv/opencv.git /root/opencv; cd /root/opencv/; git checkout -b 4.0.0 4.0.0 ; # contrib入れると大きすぎてdockerのデフォルト容量をオーバーして失敗することがあるので、一旦除外 #RUN git clone https://github.com/opencv/opencv_contrib.git /root/opencv_contrib; cd /root/opencv_contrib; git checkout -b 4.0.0 4.0.0 ; #RUN mkdir /root/opencv/build; cd /root/opencv/build; cmake -D OPENCV_EXTRA_MODULES_PATH=/root/opencv_contrib/modules .. RUN mkdir /root/opencv/build; cd /root/opencv/build; cmake .. RUN cd /root/opencv/build; make; make install;
このdockerfileの注意点として、OpenCVのcontribはつけてません。
contribはやたら大きいので、手元の環境ではdocker desktop for windowsのコンテナサイズを超えてしまいました。 なので、一旦contribなしでいきました。
各パッケージのinstall後でファイルを削除しているのも同様の理由です。
動作確認
適当にコード書きます。
OpenCVのビルド情報を表示するだけのものです。
#include <iostream> #include <opencv2/opencv.hpp> int main(int argc, char*argv[]) { auto buildinfo = cv::getBuildInformation(); std::cout << buildinfo; return 0; }
ビルドします。ここでも注意点が1つ。
OpenCV4.0ではpkg-configのサポートを終わらせるかどうか議論しているようです。
(自分でビルドとインストールするならパスは分かっているので気にしなくていいのですが、cmake使わない人=パッケージマネージャな人?だとどうするんだとか)
https://github.com/opencv/opencv/issues/13154
どうやらcmakeのオプションにpkgconfig使うように指定すれば、pcファイル吐いてくれるので、それを使えばよさそうです。
今回は自分でビルドしてインストールパスもわかっているので、直接指定します。たとえばこんな感じで。
g++ test.cpp -I/usr/local/include/opencv4/ -L/usr/local/lib64/ -lopencv_core
動かしてみる
ここでもpkg-configがsoを探してくれないので、ちょっとばかり対応が必要です。
出来上がった実行ファイルをそのまま実行すると、soが見つからないっていわれます。
[root@ce33ad34d4ba src]# ./a.out error while loading shared libraries: libopencv_core.so.4.0: cannot open shared object file: No such file or directory
新しいライブラリ入れるとよくある現象ですね。soを参照できているか見てみます。
[root@ce33ad34d4ba src]# ldd a.out linux-vdso.so.1 => (0x00007fffd5d80000) libopencv_core.so.4.0 => not found libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f51622b6000) libm.so.6 => /lib64/libm.so.6 (0x00007f5161fb4000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f5161d9e000) libc.so.6 => /lib64/libc.so.6 (0x00007f51619d1000) /lib64/ld-linux-x86-64.so.2 (0x00007f5162639000) [root@ce33ad34d4ba src]# ./a.out
確かにopencvがnot found.ですね。ここでもパスは分かっているので、環境変数を指定して実行します。
LD_LIBRARY_PATH環境変数にopencv*.soの置かれているパスを入れて実行。
[root@ce33ad34d4ba src]# LD_LIBRARY_PATH=/usr/local/lib64/ ./a.out General configuration for OpenCV 4.0.0 ===================================== Version control: 4.0.0 (略)
やったね。
トラブルシューティング
libcのバージョンが古いときは、共有ライブラリの中を確認する必要があります。
strings /usr/lib64/libstdc++.so.6 | grep GLIBCXX
これで該当するバージョンが入っているかどうか調べることができます。
gccとlibcのバージョンアップではこちらのサイトを参考にさせていただきました。
https://www.saintsouth.net/blog/update-libstdcpp-on-centos6/
感想と今後の展望
サーバ側のOpenCVは最新にすることができました。これでOpenCVのONNIXが利用できるようになります。
ONNNIXはDeepLearningの各種フレームワーク間でデータを受け渡せるようにするフォーマットで、今後はサーバ側はC++/OpenCVだけでいけるかもしれません。
とはいえサーバ側をすべてC++で書くのは骨が折れるので、PythonバインディングのOpenCV叩いたほうが早い気がしなくもないです。
あとはC++が最新版になったので、いろいろと使いたい機能が使えるようになりました。
C++も20になって関数型言語っぽい香りが本格的になってきたので、時間をとっていろいろ試したいと思います。
それでは今回はこれくらいで。