Jetson Nano结合MediaPipe实现

文章目录

  • 前言
  • 安装MediaPipe
    • 安装Bazel
    • 安装OpenCV和FFMpeg
    • 安装GPU加速支持库——OpenGL ES
    • 配置TensorFlow的CUDA支持
  • 尝试编译运行GPU版Holistic案例

前言

Jetson Nano是NVIDIA出品的一款小型AI计算机,与Raspberry PI这种开发板相比,它上面安装了NVIDIA Maxwell GPU,显然更适合于运行计算机视觉方面的AI应用。根据我之前的一篇博客,也可以很轻松地配置好一台具有计算机视觉AI开发环境的Jetson Nano。

但Jetson Nano毕竟也只有信用卡大小,直接运行一些很成熟的CV模型,如YOLO、OpenPose等,都会遇到诸如too many resources requested for launch的问题。NVIDIA论坛上也有好多提问指出了类似的问题,有大佬指出这种嵌入式系统中的4G内存是不够用的,运行深度学习的模型也都必须是优化后的轻量级模型。

此时了解到Google前两年就推出了一款称为MediaPipe的开源机器学习框架,该框架主要就提供了处理视频流的跨平台深度学习优化功能。其核心使用C++开发,可以通过自定义计算图,实现数据预处理、后处理以及组合应用各种TensorFlow Lite模型进行推断等。使用MediaPipe框架运行计算图的同时,会自动进行合适的优化,使生成的应用能够最大化地利用各种计算资源,并运行在轻量级的设备上。同时MediaPipe官方已经提供了十几个常用的案例程序,如物体识别、手势识别、面部识别、身体姿态识别等。于是就尝试在Jetson Nano上安装运行MediaPipe的示例程序,记录在这篇博客中。

安装MediaPipe

首先克隆下来MediaPipe的GitHub库,之后按照官方的说明文档中的Installation部分安装配置MediaPipe运行所需要的环境。

安装Bazel

For Nvidia Jetson and Raspberry Pi devices with aarch64 Linux, Bazel needs to be built from source:

既然MediaPipe是Google开发的,那构建工具自然还是要用Google自家的——Bazel。谷歌应该也考虑到了Jetson玩家对MediaPipe的需求,安装说明中就指明了如果是Jetson和Raspberry Pi设备,其架构为ARM64位(aarch64),因此需要从源码编译安装。从GitHub上下载Bazel源码,然后依次运行如下命令:

# 安装依赖包
> sudo apt-get install build-essential openjdk-8-jdk zip unzip

# 解压源码
> mkdir $HOME/bazel-3.7.2
> cd $HOME/bazel-3.7.2
> unzip bazel-3.7.2-dist.zip

# 编译
> env EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk" bash ./compile.sh

# 将生成的bazel文件放在PATH目录中
> sudo cp output/bazel /usr/local/bin/

# 确认安装结果以及版本号
> bazel --version

安装OpenCV和FFMpeg

OpenCV和FFMpeg都已经在Jetson上安装过,由于MediaPipe是Bazel项目,因此重要的也就是将MediaPipe中第三方库的路径配置修改一下就好。在MediaPipe官网上说明只需要使用如下命令:

> sed -i "s/x86_64-linux-gnu/aarch64-linux-gnu/g" third_party/opencv_linux.BUILD
> sed -i "s/x86_64-linux-gnu/aarch64-linux-gnu/g" third_party/ffmpeg_linux.BUILD

也就是将third_party/opencv_linux.BUILDthird_party/ffmpeg_linux.BUILD文件中所有的x86_64-linux-gnu更换为aarch64-linux-gnu,即将OpenCV和FFMpeg的库路径定义在/usr/lib/aarch64-linux-gnu下。在我的Jetson上,FFMpeg的库已预装,在/usr/lib/aarch64-linux-gnu目录下确实都有相关的.so文件,运行上述命令的第二句就行。但OpenCV是从源码编译安装的,编译安装后的lib文件和头文件都拷贝至/usr/local下,因此需要结合修改WORKSPACE文件以及third_party/opencv_linux.BUILD两个文件以定位OpenCV库路径:

# WORKSPACE文件
new_local_repository(
    name = "linux_opencv",
    build_file = "@//third_party:opencv_linux.BUILD",
    path = "/usr/local",
)

# third_party/opencv_linux.BUILD文件
cc_library(
    name = "opencv",
    srcs = glob(
        [
            "lib/libopencv_core.so",
            "lib/libopencv_calib3d.so",
            "lib/libopencv_features2d.so",
            "lib/libopencv_highgui.so",
            "lib/libopencv_imgcodecs.so",
            "lib/libopencv_imgproc.so",
            "lib/libopencv_video.so",
            "lib/libopencv_videoio.so",
        ],
    ),
    hdrs = glob([
        # For OpenCV 3.x
        "include/opencv2/**/*.h*",
        # For OpenCV 4.x
        # "include/opencv4/opencv2/**/*.h*",
    ]),
    includes = [
        # For OpenCV 3.x
        "include/",
        # For OpenCV 4.x
        # "include/opencv4/",
    ],
    linkstatic = 1,
    visibility = ["//visibility:public"],
)

安装GPU加速支持库——OpenGL ES

> sudo apt-get install mesa-common-dev libegl1-mesa-dev libgles2-mesa-dev
> sudo apt-get install mesa-utils
# 检验安装情况
> glxinfo | grep -i opengl
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: NVIDIA Tegra X1 (nvgpu)/integrated
OpenGL core profile version string: 4.6.0 NVIDIA 32.4.4
OpenGL core profile shading language version string: 4.60 NVIDIA
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL ES profile version string: OpenGL ES 3.2 NVIDIA 32.4.4
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:

注意使用glxinfo检验OpenGL安装情况时,若通过ssh连接,则运行该命令时会报错libGL error: MESA-LOADER: failed to open swrast (search paths /usr/lib/aarch64-linux-gnu/dri:\$${ORIGIN}/dri:/usr/lib/dri),而通过直连Jetson的显示器运行该命令则不会有该错误。因此若之后通过ssh连接Jetson构建或运行出错,应该考虑通过直连显示器进行尝试。

之后在构建或运行时就需要将命令行中的参数--define MEDIAPIPE_DISABLE_GPU=1替换为--copt -DMESA_EGL_NO_X11_HEADERS --copt -DEGL_NO_X11。如下面尝试构建运行GPU版本的"Hello World":

> export GLOG_logtostderr=1
> bazel run --copt -DMESA_EGL_NO_X11_HEADERS --copt -DEGL_NO_X11 mediapipe/examples/desktop/hello_world:hello_world

配置TensorFlow的CUDA支持

首先确认各种库(CUPTI、CUDA、CUDNN、NVCC)的安装情况:

> ls /usr/local/cuda-10.2/targets/aarch64-linux/lib | grep libcupti*
libcupti.so
libcupti.so.10.2
libcupti.so.10.2.75

> ls /usr/local/cuda-10.2
bin  extras   lib64    nvml  nvvmx   samples  targets  version.txt
doc  include  LICENSE  nvvm  README  share    tools

> nvcc -V
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2019 NVIDIA Corporation
Built on Wed_Oct_23_21:14:42_PDT_2019
Cuda compilation tools, release 10.2, V10.2.89

>  ls /usr/lib/aarch64-linux-gnu/ | grep libcudnn.so
libcudnn.so
libcudnn.so.8
libcudnn.so.8.0.0

将CUDA库的路径通过环境变量TF_CUDA_PATHS配置给TensorFlow:

> vi /etc/profile
export TF_CUDA_PATHS=/usr/local/cuda-10.2,/usr/lib/aarch64-linux-gnu,/usr/include

为了让bazel编译时能找到CUDA,还需要将TensorFlow官方.bazelrc文件中的build:using_cudabuild:cuda部分添加到MediaPipe文件夹下的.bazelrc文件中:

# This config refers to building with CUDA available. It does not necessarily
# mean that we build CUDA op kernels.
build:using_cuda --define=using_cuda=true
build:using_cuda --action_env TF_NEED_CUDA=1
build:using_cuda --crosstool_top=@local_config_cuda//crosstool:toolchain

# This config refers to building CUDA op kernels with nvcc.
build:cuda --config=using_cuda
build:cuda --define=using_cuda_nvcc=true

最后在编译的时候,就要在命令中再加两个参数--config=cuda--spawn_strategy=local

尝试编译运行GPU版Holistic案例

在MediaPipe文件夹下,运行如下命令编译Holistic GPU版:

> bazel build -c opt --config=cuda --spawn_strategy=local --copt -DMESA_EGL_NO_X11_HEADERS --copt -DEGL_NO_X11 mediapipe/examples/desktop/holistic_tracking:holistic_tracking_gpu

编译过程中报错ERROR: /home/victor/mediapipe/mediapipe/framework/tool/BUILD:66:10: Linking of rule '//mediapipe/framework/tool:encode_as_c_string' failed (Exit 1),GitHub上有Issue提出类似问题,但解决方案貌似是需要修改一个中间文件。注意到有评论说目前MediaPipe用到CUDA的仅仅在Object Detection中,因此暂时放弃加上CUDA选项。修改编译命令重新编译:

> bazel build -c opt --copt -DMESA_EGL_NO_X11_HEADERS --copt -DEGL_NO_X11 mediapipe/examples/desktop/holistic_tracking:holistic_tracking_gpu

编译时间较长,花费了30多分钟,需要耐心等待。再运行如下命令运行生成的程序:

> export GLOG_logtostderr=1
> ./bazel-bin/mediapipe/examples/desktop/holistic_tracking/holistic_tracking_gpu --calculator_graph_config_file=mediapipe/graphs/holistic_tracking/holistic_tracking_gpu.pbtxt

运行状态较好,帧数较为稳定,CPU利用率在60%左右,GPU利用率在80-90%浮动,可见应该是成功利用到了GPU资源。注意连接CSI摄像头时,需要修改mediapipe\examples\desktop\demo_run_graph_main_gpu.cc中设置正确的GStream Pipeline,否则无法打开摄像头,连接USB摄像头则可以直接使用。

你可能感兴趣的:(深度学习,JetsonNano,CV)