LoginSignup
2

More than 3 years have passed since last update.

(続)Jetson NanoでDockerでコンパイルしたOpenCV 4.1.0を使う

Last updated at Posted at 2019-06-17

はじめに

Jetson NanoのDockerでOpenCV 4.1.0をコンパイルする」ではDockerを使ってOpenCV 4.1.0を無事コンパイルすることができた。しかしこのままではDockerを抜けた環境で使うことはできない。そこで、このコンパイルしたバイナリをどうしたらDockerを抜けた環境で、もっとも簡単に利用できるか考えてみる。

結論はgithubに反映した。
https://github.com/yamamo-to/jetson_nano/tree/master/opencv4_compile

ターゲット言語はPython

C/C++からは単にリンクすれば利用できるので、これからメインで使うであろうPythonから呼び出すことを考える。すなわち

import cv2
print(cv2.__version__)

で4.1.0が返ってくるような、最も簡単な方法を探ろうという試みである。

ディスク容量

コンパイル時に必要なディスク容量

コンパイル環境はDockerイメージだけで1GBある。

ターミナル
docyamamo-to@jetson-nano:~$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
opencv4_build       latest              9710cbd87862        21 hours ago        1.01GB
ubuntu              18.04               9f020c638543        4 weeks ago         63.3MB

さらにソースコードとビルド後のサイズ含めると追加で6.7GBである。

ターミナル
yamamo-to@jetson-nano:~/Documents/jetson_nano/opencv4_compile/home$ du -s -h build
6.7G    build

つまり、コンパイルには最低約8GB必要である。

実行時に必要なディスク容量

一方で実行環境と言えば

ターミナル
yamamo-to@jetson-nano:~/Documents/jetson_nano/opencv4_compile/home$ du -s -h dist/
199M    dist/

たったの約200MBである。これからやりたいことは、この200MBだけをDockerの環境から持ち出して、普通の環境でOpenCV 4.1.0を使えるようにしたい、ということである。

Pythonモジュールの仕組み

例えばPythonで書かれたソースコードと同じディレクトリにhogeのようなディレクトリがあり、その中に空のファイル__init__.pyが存在するとimport hogeを行うことができる。同じディレクトリでなくともサーチパス(sys.pathで見られる)が通っていれば探してくれる。

Jetpack4.2(OpenCV3.1.1)
yamamo-to@jetson-nano:~$ python3
Python 3.6.8 (default, Jan 14 2019, 11:02:34) 
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/home/yamamo-to/.local/lib/python3.6/site-packages', '/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages', '/usr/lib/python3.6/dist-packages']
>>> 

OpenCVのモジュール名

Docker内でインストールされたパスがどこにあるのかを確認する。

Dockerコンテナ内(OpenCV4.1.0)
foo@e6ba62eb25b4:~$ python3
Python 3.6.8 (default, Jan 14 2019, 11:02:34) 
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__file__
'/usr/local/lib/python3.6/dist-packages/cv2/python-3.6/cv2.cpython-36m-aarch64-linux-gnu.so'
>>> 

この結果から/usr/local/lib/python3.6/dist-packagesがサーチパスに含まれていれば良いことが分かる。

またJetPack4.2のOpenCVをPythonから呼び出すためにインストールするpython3-opencvは次の通りである。

Jetpack4.2(OpenCV3.1.1)
yamamo-to@jetson-nano:~$ apt-file -F show python3-opencv
python3-opencv: /usr/lib/python3/dist-packages/cv2.cpython-36m-aarch64-linux-gnu.so
python3-opencv: /usr/share/doc/python3-opencv/changelog.Debian.gz
python3-opencv: /usr/share/doc/python3-opencv/copyright

ファイル名cv2.cpython-36m-aarch64-linux-gnu.soは全く同じでディレクトリが/usr/local/libか/usr/libの違いだけである。サーチパスの優先順位の高いところにOpenCV 4.1.0のモジュールが呼ばれるように配置すれば良さそうだ。

サーチパスの追加

/usr/local以下を/opt/opencv-4.1.0にコピーした上で、PYTHONPATHにパスを通して呼び出せるか試してみる。

ターミナル
yamamo-to@jetson-nano:~/Documents/jetson_nano/opencv4_compile$ sudo cp -a  home/dist/usr/local /opt/opencv-4.1.0
export PYTHONPATH=/opt/opencv-4.1.0/lib/python3.6/dist-packages:$PYTHONPATH

実行すると

ターミナル
$ pipenv run python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/opencv-4.1.0/lib/python3.6/dist-packages/cv2/__init__.py", line 89, in <module>
    bootstrap()
  File "/opt/opencv-4.1.0/lib/python3.6/dist-packages/cv2/__init__.py", line 79, in bootstrap
    import cv2
ImportError: libopencv_hdf.so.4.1: cannot open shared object file: No such file or directory
>>> 

libopencv_hdf.so.4.1が見つからないというエラーがでた。このファイル自身は/opt/opencv-4.1.0/lib/libopencv_hdf.so.4.1にあるので、これはLD_LIBRARY_PATHを通せば良い。

ターミナル
export LD_LIBRARY_PATH=/opt/opencv-4.1.0/lib:$LD_LIBRARY_PATH

では改めて。

ターミナル
$ pipenv run python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'4.1.0'
>>> 

呼び出すことに成功した!それならば最初からインストール先が/usr/localではなく/opt/opencv-4.1.0となるようにCMAKE_INSTALL_PREFIXを変更すれば良さそうだ。

依存ライブラリ

opencvが呼び出せることと、呼び出したプログラムが正常に動くことは別である。依存ライブラリがない場合、それを必要としたライブラリが読み込まれた時点でエラーとなる。少なくとも今回/opt/opencv-4.1.0で作成したパッケージを使うためには、下記のライブラリ群がインストールされていることが必要である。

ターミナル
sudo apt install cuda-cublas-10-0 cuda-cufft-10-0 cuda-npp-10-0 libavcodec57 libavformat57 libdc1394-22 libglib2.0-dev libgstreamer-plugins-base1.0-0 libgtk2.0-0 libhdf5-100 libjpeg-turbo8 libswscale4

SquashFS

存在を忘れつつあったSquashFSでディレクトリごと圧縮してファイル一つにする。

ターミナル
mksquashfs /opt/opencv-4.1.0 $HOME/opencv-4.1.0.sfs -b 1048576 -comp xz -Xdict-size 100%

ファイルサイズは

ターミナル
yamamo-to@jetson-nano:~/Documents/jetson_nano/opencv4_compile$ ls -lh home/opencv-4.1.0.sfs
-rw-r--r-- 1 yamamo-to yamamo-to 29M  6月 18 07:10 home/opencv-4.1.0.sfs

29MBになった。これを/opt/opencv-4.1.0にマウントすれば使えるようになる。

まとめ

Dockerでコンパイルして作成されたディレクトリを圧縮した29MBのファイルopencv-4.1.0.sfsを持ち出して/opt/opencv-4.1.0にマウントする。

sudo mkdir /opt/opencv-4.1.0
sudo mount -o loop opencv-4.1.0.sfs /opt/opencv-4.1.0

次に環境変数PYTHONPATHLD_LIBRARY_PATHを設定する。

export PYTHONPATH=/opt/opencv-4.1.0/lib/python3.6/dist-packages:$PYTHONPATH
export LD_LIBRARY_PATH=/opt/opencv-4.1.0/lib:$LD_LIBRARY_PATH

aptで関連ライブラリをインストールする。

ターミナル
sudo apt install libatlas3-base libhdf5-100

これでOpenCV 4.1.0が動作するようになる。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2