在Ubuntu 18.04LTS上部署OpenPose+CUDA+CuDNN

由于毕业设计的缘故,需要在linux平台安装OpenPose这个姿态识别库。它可以通过神经网络,利用开发团队事先训练好的模型进行姿态、手部、面部识别,具有很好的效果,但是官方只提供Windows下编译好的二进制文件,在linux平台需要手动编译安装。下面记录一下我踩过的坑,为了方便自己,也为了方便别人。

首先,OpenPose使用caffe作为其神经网络框架。只要用到神经网络,就离不开速度这个永恒不变的话题。这个项目支持使用CUDA以及CuDNN来进行加速。CUDA是NVIDIA推出的一种并行异构计算平台,CuDNN是NVIDIA推出的配合CUDA使用的DNN(深度神经网络)加速库。根据官方的wiki,在720P分辨率下,不使用CuDNN需要占用12G显存,使用后可以降低到2.8G。

通过使用Windows下的demo实测,在我的老爷机(i5-4200H + GTX850M 4G)上,使用640*480的图片分辨率以及相同的神经网络分辨率,使用CPU可以达到10秒1帧,使用GPU (CUDA + CuDNN)可以达到每秒2帧左右。降低网络精度之后,使用GPU可以达到10帧左右,基本算是满足了近期的调试需求。可以看出,使用显卡进行加速的提升巨大,我们没有理由不使用GPU。

在Windows下安装NVIDIA驱动是安装操作系统的时候就完成的事情,demo中的CUDA也是直接打包进去的二进制文件。但是在linux下,我们要做的第一件事就是安装显卡驱动、CUDA框架以及CuDNN加速库。如果网络不好,可以在文末的连接中下载。

一、安装显卡驱动及CUDA、CuDNN

在安装CUDA中和CuDNN中,我踩了了相当多的坑。其中之一就是编译之后运行的时候,CuDNN初始化错误。经过了大量的资料查找以及尝试之后,我发现了对于这种框架和库性质的东西,并不是版本越高越好,找到一个和源代码兼容的版本非常重要。通过查看提供的Windows版demo中官方打包提供的两个库文件的版本,我最终选择了CUDA10.0和CuDNN7.3.1,实测编译截止文章完成之日的源码,可以运行成功,与demo效果一致。

官方提供demo包中dll的版本

由于我们使用Ubuntu,它自带了一个驱动安装器,因此我们可以偷个懒,让系统自动帮我们安装一下显卡驱动。刚装好系统的时候,用的是nouvaeu开源驱动,我们要装NVIDIA官方的闭源驱动,才能够正常配合CUDA运行。我使用的CUDA版本自带的驱动版本是410,所以理论上这个版本之上的显卡驱动都是可以兼容的,但是经过实测410的驱动会让系统崩溃,因此我选择了430驱动,实测可以正常安装并兼容CUDA。值得一提的是,在点开这个附加驱动的选项卡之前,请一定要在Ubuntu软件选项卡中选择阿里源或者清华源这类国内的软件源(不要被中国的服务器给骗了,否则会慢出奇迹)并勾上设备的专有驱动。

记得改国内源!
Ubuntu软件与更新中的附加驱动

安装好驱动之后,重启系统,在终端中输入 nvidia-smi,检查安装是否成功。如果成功了,我们就可以接着进行下面的操作了。其中显示的CUDA版本直接无视即可,这个版本显示的是和这个驱动打包发布的CUDA的版本,但是这个版本无法配合OpenPose运行,因此我们后期还需要安装老版本的。

查看驱动安装情况

我们将下载好的 cuda_10.0.130_410.48_linux.run 以及 cudnn-10.0-linux-x64-v7.3.1.20.tgz两个文件放到 ~/archive/cuda10_0/ 目录中(从官网或者我提供的连接),然后打开终端:

cd cuda
chmod +x cuda_10.0.130_410.48_linux.run

进入目录,并赋予可执行权限。之后运行cuda安装脚本。

sudo ./cuda_10.0.130_410.48_linux.run

即可进入安装界面。安装程序首先会要求我们阅读用户协议,直接按 q 退出,并输入 accept 接受即可。接下来,安装程序会问我们要不要安装显卡驱动。正如前文所说,经过实测,这个版本CUDA安装包自带的显卡驱动与Ubuntu18.04貌似有点兼容性问题,硬装上不但会卸载之前系统帮我们装的驱动,还会导致 nvidia-smi 命令都无法运行。因此,我们选择不安装显卡驱动。

安装程序

接下来我们选择Install the CUDA 10.0 Toolkit,选择默认路径(直接回车),并选择Install a symbolic link来创建符号链接。后面的一些选项按照自己的实际需求来选择就好了,接下来让它慢慢安装。

安装完毕之后,我们输入(需要创建符号链接才会有这个目录,这个目录是连接到 cuda-10.0 的)

cd /usr/local/cuda/

进入刚安装好的CUDA目录中,接下来输入

bin/nvcc --version

查看安装好的CUDA编译器版本,若显示正确的版本,即为安装成功。

显示正确的NVCC版本

接下来我们安装CuDNN。CuDNN其实就是两个库文件和一个头文件。我们只需要解压之后复制到对应的文件夹之中即可。

cd ~/archive/cuda10_0
tar zxvf cudnn-10.0-linux-x64-v7.3.1.20.tgz
sudo cp cuda/lib64/libcudnn.so.7.3.1 /usr/local/cuda/lib64/
sudo cp cuda/lib64/libcudnn_static.a /usr/local/cuda/lib64/
sudo cp cuda/include/cudnn.h /usr/local/cuda/include/
sudo ln -s /usr/local/cuda/lib64/libcudnn.so.7.3.1 /usr/local/cuda/lib64/libcudnn.so.7
sudo ln -s /usr/local/cuda/lib64/libcudnn.so.7.3.1 /usr/local/cuda/lib64/libcudnn.so

要注意不能直接复制文件夹,否则软连接会出问题。到此为止,我们的驱动安装工作就全部完成了。

二、编译安装OpenCV

OpenPose依赖OpenCV作为其绘图库,我们首先要安装OpenCV。值得注意的是,在我踩坑的过程中,我发现最新版的OpenCV(到文章完成之日是4.2.0)中的一些宏的名字改变了,导致依赖它的caffe和OpenPose都无法正常编译,因此我找到了和CUDA10.0推出时间差不多的OpenCV3.4.7,实测可以正常使用。

由于apt中没有我们需要的这个3.4.7版本,因此编译安装是逃不过的。

在系统自带的Ubuntu软件中搜索Cmake来下载Cmake GUI,并从GitHub下载OpenCV3.4.7的源码包并解压。安装好上述软件之后,我们来安装依赖:

sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg-dev libtiff5-dev libswscale-dev libopenexr-dev libdc1394-22-dev libgtkglext1-dev
sudo apt-get install python3 python3-pip python python-pip python-dev python3-dev
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple

在CMake配置的时候,我们需要注意勾选 BUILD_STATIC_LIBS 来生成OpenPose需要的静态库。同时,还需要勾上 WITH_GTK_2_X ,这是增加OpenCV的图形支持,如果不勾选这个会导致 cv2.namedWindow() 这类依赖GUI的函数没法使用。此外,如果需要python支持,还可以勾选上 BUILD_opencv_python2 和 BUILD_opencv_python3

在配置的过程中,可能会遇见下载一个70多M的压缩包的过程。由于众所周知的原因,下载速度会慢出奇迹。这个文件在下载完成之前就会超时退出。这个时候可以在终端里输入

export http_proxy=127.0.0.1:1080
export https_proxy=127.0.0.1:1080

cmake-gui

来使用本地代理连接(前提是要搭建好代理客户端)。即可完成下载。如果没有代理,也可以下载文末连接中的 c0bd78adb4156bbf552c1dfe90599607-ippicv_2019_lnx_intel64_general_20180723.tgz

文件,放置到 opencv-3.4.7/.cache/ippicv 来跳过下载。

如果提示Configure done的话,点击Generate生成MakeFile文件。然后进入到 opencv-3.4.7/build 文件夹下,执行

make -j4 && sudo make install

如果可以顺利完成,我们就完成了OpenCV的编译过程。安装完成之后可以在终端输入

python3 -c "import cv2"

指令,如果没有任何回显则说明安装成功。

编译OpenCV

三、编译安装OpenPose

OpenPose依赖caffe,但是caffe默认是和OpenPose一起编译安装的,因此我们不需要单独去配置caffe,OpenPose的编译脚本会帮我们配置好的。

找到你存放代码的文件夹,执行

git clone --recursive https://github.com/CMU-Perceptual-Computing-Lab/openpose

来下载OpenPose以及其依赖的caffe源码。如果下载缓慢,可以下载我在文后链接中提供的截至文章发布时版本的压缩包。值得注意的是,CMake在第一次配置的时候默认会下载很多模型文件,也会出现像前面一样下载超时的问题。你可以选择使用代理,或者将我给出连接中的 models 文件夹复制到程序源码目录,即可避免下载。

然后,我们在终端中输入

sudo apt-get install libprotobuf-dev libgoogle-glog-dev libboost-dev libboost-thread-dev  libboost-filesystem-dev protobuf-compiler libhdf5-dev libatlas-base-dev

来安装依赖。

接下来,我们使用Cmake GUI 来配置。由于我要使用python的wrapper,因此我勾选 BUILD_PYTHON 。同时,要注意是否勾选 USE_CUDA 和 USE_CUDNN 。都配置好后,我们点击Configure,若无错误,点击Generate,然后进入文件夹开始编译。

CMake 配置OpenPose
cd ~/code/openpose/build
make -j4 && sudo make install

编译成功后,我们可以运行一下自带的例子,来测试编译是否成功。如果CUDA和CuDNN的版本对应有错误,一般是可以完成编译的,但是运行的时候就会报错。在运行的时候,使用 --net-resolution "320x240" 来降低网络分辨率,提高速度。

cd examples/openpose
cp -r ../../models/ ./
./openpose.bin --net-resolution "320x240"
程序成功运行!

如果demo运行正常,恭喜你,成功编译了OpenPose。

由于我们同时安装了python的接口,因此我们也可以测试一下python接口是否安装成功。默认情况下python的模块是安装到 /usr/local/python 下,这个目录并不在系统的path中。因此我们打开python,输入以下代码来验证:

import sys
sys.path.append('/usr/local/python')
from openpose import pyopenpose as op

如果执行过程中没有报错,说明python接口也已安装成功。

文中提到的文件可以在此下载(提取码w1go)

1+

留下评论