#XavierNX/JetsonNANOでBACKEND_CUDAなOpenCV4.3
##はじめに
XavierNX開発キッとは、画像処理をするにあたって、安価にハードウェアアクセラレータが使える環境の一つです。
NvidiaはXavierNX開発キットでのDokcerのサポートを強化しています。NGC
などから、イメージをダウンロードしコンテナとして実行が可能です。
#概要
OpenCV4.3で、DNN_CUDAの使えるコンテナを作成しました。
#手順
- dokcer build時に --runtime nvidia の指定
-
runtime=nvidiaを有効してdocker buildする
を参考に/etc/docker/daemon.json を変更 - OpenCVをビルドするDockerfileの作成
-
Jetson Nano に OpenCV 4.1.2 をインストールするを参考に
Machine Learning for Jetson/L4T をベースとするDockerfileを作成 - BACKEND_CUDAをイネーブルに
- cmakeに-D OPENCV_DNN_CUDA=ONの追加
- Could NOT find CUDNN (missing: CUDNN_INCLUDE_DIR) (Required is at least version "7.5")
への対応 - includeをhostからコピー
- Could NOT find CUDNN: Found unsuitable version "..", but required is at least "7.5" (found /usr/lib/aarch64-linux-gnu/libcudnn.so)への対応
- cudnn.hではなく、cudnn_version.hを参照するように変更
#BACKEND_CUDAをイネーブルに
cmakeに-D OPENCV_DNN_CUDA=ONの追加
XavierではJetpackとよばれる開発環境をNvidiaが提供しています。
これを使うと、OpenCVをそのまま利用することが可能です。
問題は、OpenCV4.2より前のバージョンではDNNモジュールが使えない点にあります。
OpenCVでDNNをつかうには、4.2以上をビルドする必要がありますが、Nvidiaはこれに関する情報を”いまのところ”公開していません。ってーか、OpenCVには非常につめたいです。
DNNモジュールのイネーブルには、cmakeに-D OPENCV_DNN_CUDA=ON を追加する必要があります。
#Could NOT find CUDNN (missing: CUDNN_INCLUDE_DIR) (Required is at least version "7.5") へ対応
-D OPENCV_DNN_CUDA=ONを追加し、docker build すると今度は、
そもそもNvidiaが提供するイメージには、cudnn.h が入ってないので、そのままだとdockerでビルドすることが出来ません。
仕方ないので、Dockerfile内で/usr/include/*とアーキテクチャ毎に振り分けてる/etc/alternativeの中身をcontainer内に全コピー
なんでヘッダだけいれてないのか、、きっとなんか崇高な理由があるはずですが、よっぱらってて面倒くさいので力業で解決することにします。 5/28 /etc/alternativeを全部コピーしてたんですが、怪しげなのでcudnn関連のリンクをコピーするようにしました。これで少なくともalternativeは既存のファイルは上書きされません。/usr/includeはhostからコピーなんでままいいかなと。。
#Could NOT find CUDNN: Found unsuitable version "..", but required is at least "7.5" (found /usr/lib/aarch64-linux-gnu/libcudnn.so) へ対応
JetPack4.4ではCUDNNのバージョンは8.0で
バージョン番号は、cudnn_version.hにかかれています。
一方で、opencv4.3のCMAKEでは
file(READ "${CUDNN_INCLUDE_DIR}/cudnn.h" CUDNN_H_CONTENTS)
string(REGEX MATCH "define CUDNN_MAJOR ([0-9]+)" _ "${CUDNN_H_CONTENTS}")
set(CUDNN_MAJOR_VERSION ${CMAKE_MATCH_1} CACHE INTERNAL "")
string(REGEX MATCH "define CUDNN_MINOR ([0-9]+)" _ "${CUDNN_H_CONTENTS}")
set(CUDNN_MINOR_VERSION ${CMAKE_MATCH_1} CACHE INTERNAL "")
string(REGEX MATCH "define CUDNN_PATCHLEVEL ([0-9]+)" _ "${CUDNN_H_CONTENTS}")
set(CUDNN_PATCH_VERSION ${CMAKE_MATCH_1} CACHE INTERNAL "")
なんて書いてあって、cudnn.hにバージョンがかかれていることを期待しています。
仕方ないので、Dockerfile内でパッチをあてることにしました。
sed -i 's/{CUDNN_INCLUDE_DIR}\/cudnn.h/{CUDNN_INCLUDE_DIR}\/cudnn_version.h/g' cmake/FindCUDNN.cmake
5/27 Update
nano_build_opencvを確認したら、こんなことしなくてもCUDNN_VERSION='8.0'を足すと動くらしい。。。
そもそもnano_build_opencvでCUDNNがイネーブルになるならDockerの中でnano_build_opencvを実行した方がはやい気がします。5/28 Update
動作するのを確認したので、DockerfileをCUDNN_VERSION='8.0'を使うようにアップデートしてsedでのパッチ当てをなくしました。
成果物
Python2のサポートはいれてません。。
5/28
githubにコードをアップロードしました。
git clone https://github.com/sowd0726/Jetson_docker.git
こっちはスクリプト実行でNANO用もつくれるようにしてあります。
FROM nvcr.io/nvidia/l4t-base:r32.4.2
COPY include /usr/include
COPY alternatives /etc/alternatives
RUN mkdir /root/opencv430
RUN user="nvidia"
RUN passwd="nvidia"
RUN echo "** Remove other OpenCV first"
RUN cd /root
RUN echo "** Install requirement"
RUN sudo apt-get update
RUN sudo apt-get install -y zip
RUN sudo apt-get install -y build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
RUN sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
RUN sudo apt-get install -y python3.6-dev python3-numpy
RUN sudo apt-get install -y libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev
RUN sudo apt-get install -y libv4l-dev v4l-utils qv4l2 v4l2ucp
RUN sudo apt-get install -y curl
RUN sudo apt-get update
RUN echo "** Download opencv-4.3.0"
RUN cd /root/opencv430 && \
curl -L https://github.com/opencv/opencv/archive/4.3.0.zip -o opencv-4.3.0.zip && \
curl -L https://github.com/opencv/opencv_contrib/archive/4.3.0.zip -o opencv_contrib-4.3.0.zip
RUN cd /root/opencv430 && \
unzip opencv-4.3.0.zip && \
unzip opencv_contrib-4.3.0.zip && \
cd opencv-4.3.0 && \
echo "** Apply patch" && \
# sed -i 's/{CUDNN_INCLUDE_DIR}\/cudnn.h/{CUDNN_INCLUDE_DIR}\/cudnn_version.h/g' cmake/FindCUDNN.cmake && \
mkdir release
RUN cd /root/opencv430/opencv-4.3.0/release && \
cmake -D CUDNN_VERSION='8.0' -D WITH_CUDA=ON -D CUDA_FAST_MATH=ON -D WITH_CUBLAS=ON -D WITH_CUDNN=ON -D CUDA_ARCH_BIN=7.2 -D CUDA_ARCH_PTX=7.2 -D CUDA_ARCH_PTX="" -D OPENCV_DNN_CUDA=ON -D OPENCV_GENERATE_PKGCONFIG=ON -D CUDNN_INCLUDE_DIR=/usr/include -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.3.0/modules -D WITH_GSTREAMER=ON -D WITH_LIBV4L=ON -D BUILD_opencv_python3=ON -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local .. ; exit 0
RUN bash
RUN cd /root/opencv430/opencv-4.3.0/release && \
make -j4 && \
sudo make install && \
echo 'export PYTHONPATH=$PYTHONPATH:'$PWD'/python_loader/' >> ~/.bashrc
RUN echo "** Install opencv-4.3 successfully" && \
echo "** Bye :)"
CMD ["/bin/bash"]
5/27 Update
Darknetをビルドしようとしたら
Package opencv was not found in the pkg-config search path
っていわれした。
pkgconfigをつくっとかないといけないらしく、
-D OPENCV_GENERATE_PKGCONFIG=ON
を追記しました。5/28 Update
Jetson NANOで動かすには、GPUのARCHITECTUREが7.2になっている部分を5.3にするだけでOKです。# 確認ずみ github にはいれてあります。
mkdir include
cp -apd /usr/include/*cudnn* include
mkdir include/aarch64-linux-gnu
cp -apd /usr/include/aarch64-linux-gnu/*cudnn* include/aarch64-linux-gnu
mkdir alternatives
cp -apd /etc/alternatives/*cudnn* alternatives
sudo docker build -t opencv430:104 .
5/28 Update
上記でイメージがopencv430:103というタグで作成されます。
/etc/alternativesから盛大にコピーしたのを比較的Gentleに変更しました。必要なリンクだけになった予定です。
git 上では/etc/nv_tegra_releaseでJetson NANOとXavierNXを区別してます。
5/23-2
git上のスクリプトのハードウェア判定がバグってたのでなおしました。
なんかpip3 install v4l2captureするとうまくいかないので、余計なfileの上書きをしないようにしました。タグがopencv430:104になりました。依然としてv4l2captureはうまく入らないですが、あきらめよう。。
dockerはあんまりつかったことないので、無茶してますが、とりあえずこれでDNNがイネーブルのOpenCV4.3をDockerで使えました
これでOpenCVのバージョンがあげ放題。。。の予定