自从发了上一期在Ubuntu20.04上配置深度学习环境的视频之后,我收到了很多小伙伴的反馈,其中有不少同学私信我表示“能不能教我怎么编译OpenCV呢”。但其实在Ubuntu上编译的教程网上已经有很多了,因此今天我们加亿点点难度,完成在Ubuntu20.04上完成OpenCV+CUDA的编译。这样后续使用OpenCV的时候,不管是传统算法也好,使用DNN模块推理深度学习算法也罢,都可以调用CUDA进行加速。
首先介绍下前置知识,如果看过我的上一期视频,那么我们已经安装过了CUDA,cuDNN和Anaconda,其路径分别为/usr/local/cuda
,/usr/local/cuda
,~/anaconda3/
。明确之后我们就可以开始今天的教程了。
下载OpenCV源码
如果没有使用一些特殊手段,那么不出意外的下载速度会非常慢,可以选择通过中国镜像进行下载。
下载OpenCV Contrib源码
local_install
,然后把库全部放在里面,方便统一管理,也方便备份。直接执行下述命令去安装相应的库即可:
sudo apt update
sudo apt upgrade
sudo apt install build-essential cmake unzip pkg-config
sudo apt install libjpeg-dev libpng-dev libtiff-dev
sudo apt install libavcodec-dev libavformat-dev libswscale-dev
sudo apt install libv4l-dev libxvidcore-dev libx264-dev
sudo apt install libgtk-3-dev
sudo apt install libblas-dev liblapack-dev gfortran
sudo apt install python3-dev
注意,如果有些库没有安装,那么OpenCV在编译到某个功能模块的时候,如果当前功能模块对没有安装的库存在依赖关系,就不会编译这个模块,可能在调用这个API的时候就会报一些奇奇怪怪的bug,比如:
error: (-2) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function cvNamedWindow
使用unzip或者tar命令解压opencv和opencv_contrib的源码,准备进行编译;
cd进入opencv文件夹,使用mkdir命令创建一个叫做build
的文件夹,然后再cd进build
文件夹。
mkdir build
cd build
需要执行的CMake命令:
cmake \
-D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D BUILD_opencv_python2=OFF \
-D OPENCV_PYTHON3_VERSION=3.9 \
-D PYTHON_EXECUTABLE=/home/ubuntu/anaconda3/envs/pt/bin/python3 \
-D PYTHON_DEFAULT_EXECUTABLE=/home/ubuntu/anaconda3/envs/pt/bin/python3 \
-D PYTHON3_EXECUTABLE=/home/ubuntu/anaconda3/envs/pt/bin/python3 \
-D PYTHON3_INCLUDE_DIR=/home/ubuntu/anaconda3/envs/pt/include/python3.9m \
-D PYTHON3_LIBRARY=/home/ubuntu/anaconda3/envs/pt/lib/libpython3.9.so \
-D PYTHON3_NUMPY_INCLUDE_DIRS=/home/ubuntu/anaconda3/envs/pt/lib/python3.9/site-packages/numpy/core/include \
-D PYTHON3_PACKAGES_PATH=/home/ubuntu/anaconda3/envs/pt/lib/python3.9/site-packages \
-D INSTALL_PYTHON_EXAMPLES=ON \
-D INSTALL_C_EXAMPLES=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D BUILD_TIFF=ON \
-D OPENCV_EXTRA_MODULES_PATH=/home/ubuntu/local_install/opencv_contrib/modules \
-D BUILD_EXAMPLES=ON \
-D WITH_CUDA=ON \
-D WITH_CUDNN=ON \
-D OPENCV_DNN_CUDA=ON \
-D WITH_CUBLAS=ON \
-D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda \
-D OpenCL_LIBRARY=/usr/local/cuda/lib64/libOpenCL.so \
-D OpenCL_INCLUDE_DIR=/usr/local/cuda/include/ \
.. # 表示CMakeLists.txt文件在上一级目录中
先提一个容易出问题的点,此处家目录不能写~
,解析不了,而是要写全(如/home/ubuntu
)。接下来我们对其中较为重要的变量进行解释,其中的路径需要按照自己机器的情况自行更改:
设置Python的可执行文件路径为Anaconda中虚拟环境(envs)下的pt环境下的Python的可执行文件(二进制文件,一般放在bin
(binary)文件夹下,Linux下的二进制文件(或可执行文件)类似于Windows下的.exe
文件,能够直接运行);
PYTHON_EXECUTABLE=/home/ubuntu/anaconda3/envs/pt/bin/python3
PYTHON_DEFAULT_EXECUTABLE=/home/ubuntu/anaconda3/envs/pt/bin/python3 \
PYTHON3_EXECUTABLE=/home/ubuntu/anaconda3/envs/pt/bin/python3 \
以上部分如果是跟着上一个教程配置的Anaconda的环境,只需要改下家目录中的用户名就可以直接使用了。
设置Python环境中的include文件夹路径、Python的动态库路径、Python环境中NumPy环境的include文件夹路径和Python环境下的第三方库安装路径;
PYTHON3_INCLUDE_DIR=/home/ubuntu/anaconda3/envs/pt/include/python3.9m \
PYTHON3_LIBRARY=/home/ubuntu/anaconda3/envs/pt/lib/libpython3.9.so \
PYTHON3_NUMPY_INCLUDE_DIRS=/home/ubuntu/anaconda3/envs/pt/lib/python3.9/site-packages/numpy/core/include \
PYTHON3_PACKAGES_PATH=/home/ubuntu/anaconda3/envs/pt/lib/python3.9/site-packages \
同上,如果是跟着上一个教程配置的Anaconda的环境,更改家目录中的用户名和Python的版本即可使用。
设置opencv_contrib的路径;
OPENCV_EXTRA_MODULES_PATH=/home/ubuntu/local_install/opencv_contrib/modules \
设置带上CUDA、cuDNN进行编译,并设置CUDA的路径(此处CUDA的路径一般不需要更改);
WITH_CUDA=ON \
WITH_CUDNN=ON \
OPENCV_DNN_CUDA=ON \
WITH_CUBLAS=ON \
CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda \
OpenCL_LIBRARY=/usr/local/cuda/lib64/libOpenCL.so \
OpenCL_INCLUDE_DIR=/usr/local/cuda/include/ \
此处提出一个小技巧,如果我们直接复制了上述CMake的命令,并在终端中Ctrl+v,并在终端里面修改这些变量中的路径不是那么方便。我的建议是,先在build
文件夹中创建一个shell脚本,比如命名为build.sh
,可以先用自己擅长的编辑器如vim之类的修改CMake命令中的变量,再在终端内sh ./build.sh
运行这个脚本。
假如CMake最后出现了如下的信息,则说明在安装了Anaconda之后,它的环境遮挡住了系统的环境,编译的时候也会报各种各样稀奇古怪的问题,此时需要在对应的终端的配置文件里面将Anaconda的环境覆盖掉。覆盖的方法就是在对应的终端配置文件之中注释掉Anaconda的环境。
CMake Warning at cmake/OpenCVUtils.cmake:1547 (add_library):
Cannot generate a safe runtime search path for target opencv_highgui
because files in some directories may conflict with libraries in implicit
directories:
runtime library [libpangocairo-1.0.so.0] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
runtime library [libpango-1.0.so.0] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
runtime library [libharfbuzz.so.0] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
runtime library [libcairo-gobject.so.2] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
runtime library [libcairo.so.2] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
runtime library [libgio-2.0.so.0] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
runtime library [libgobject-2.0.so.0] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
runtime library [libgthread-2.0.so.0] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
runtime library [libglib-2.0.so.0] in /usr/lib/x86_64-linux-gnu may be hidden by files in:
/home/ubuntu/anaconda3/lib
Some of these libraries may not be found correctly
执行make进行编译
make -j12 # 编译,-j表示调用12个线程进行编译
sudo make install # 把编译后的头文件和库写入到指定文件夹中
sudo ldconfig # 令动态链接库能够为系统所共享
我们首先验证下C++环境是否有正常编译并安装。我们创建一个叫做test的文件夹,然后我们创建一个main.cpp
的文件,尝试是否能够正常引入OpenCV的头文件。
#include
int main()
{
return 0;
}
然后我们再创建个CMakeLists.txt
的文件来写CMake:
cmake_minimum_required(VERSION 3.16)
project(opencv_test)
set(CMAKE_CXX_STANDARD 14)
find_package(OpenCV REQUIRED)
add_executable(opencv_test main.cpp)
target_link_libraries(opencv_test ${OpenCV_LIBS})
同样为了方便管理CMake配置的编译规则以及编译过程中产生的中间文件,我们创建一个build
文件夹,cd进去后执行cmake命令即可配置编译规则,生成一个MakeFile
文件;
mkdir build
cd build
cmake .. # 执行cmake,..表示CMakeLists.txt在上一层路径中