Compiling OpenCV with CUDA
OpenCV is the most popular and widely used Computer Vision libraries with a host of algorithms. Many of these algorithms have GPU accelerated versions based on the equally popular NVIDIA CUDA libarary. If you are starting Computer Vision projects using Deep learning or Machine Learning you will come across the need to install OpenCV with CUDA as you may need to use OpenCV GStreamer or FFMPEG based libraries to decode the video into image frames or resize the images and create the image matrix data structure cv::Mat or cv::cuda::GpuMat for futher processing by Tensorflow.
There are basically two ways to go about this.
Easiest way is to build inside a Docker container and use that container for your development; Yes you can export also the GUI using X11
OR Build in your machine.
For both you need a laptop or server with a NVDIA GPU and preferably a stable Ubuntu version; The below should work in other Linux versions changing the package manager commands.
Step 1. Install NVIDIA Driver
Never ever install directly from NVIDIAs .run file as there is a high chance that it mess with the display — lightdm and causes instability.(So unless you are an OS expert, please don’t; or if you are brave enough, try basically installing without opengl option --no-opengl-file
); and if you still mess with display there are enough threads to help you)
Simpler way
sudo apt-get install build-essential
sudo apt-add-repository ppa:graphics-drivers/ppa
sudo apt-get update
sudo apt-get install nvidia-3xxsudo modeporbe nvidia (also ran this before restart)
Please see detailed instruction here
https://medium.com/techlogs/install-the-right-nvidia-driver-for-cuda-in-ubuntu-2d9ade437dec
Check — Step 1 : Check install status via nvidia-smi command
+ — — — — — — — — — — —— — — — — — — — — — — — — — -+
| NVIDIA-SMI 375.39 Driver Version: 375.39 |
| — — — — — — — — — — — — — + — — — — — — — — — — — +
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|================+======================+======================|
| 0 GeForce GT 720M Off | 0000:01:00.0 N/A | N/A |
| N/A 51C P0 N/A / N/A | 271MiB / 1985MiB | N/A Default |
+ — — — — -+ — — — — — — — — — — — + — — — — — — — — — — — +
There are two options now; one is to install CUDA in your machine and then compile OpenCV. The other simpler option is to use nvidia-cuda docker container and install OpenCV in that.
Step 2: Using nvidia-cuda Docker Container and install OpenCV in it
Download OpenCV 3.4 source and un zip it; Example I put it in my home folder.
Do docker volume mapping with nvidia-cuda docker container.
docker run --net=host --runtime=nvidia -it -v /home/alex/coding:/coding nvidia/cuda /bin/bash
Install OpenCV relevant packages in the container; only these are needed. Not that this is to compile OpenCV with FFMPEG. The -dev versions are needed for compilation. You don’t however need this for build. You can use the Docker multi-stage build to create a build directory from this dev.
apt-get -y update
apt-get install -y cmake pkg-config \
zlib1g-dev ffmpeg libwebp-dev \
libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev \
libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
If you want to export display from the Docker image install X packages also
apt-get install x11-apps
Create a directory named ‘build’ and cd to that. Run cmake with the following options. Change CUDA_TOOLKIT_ROOT_DIR and CUDA_ARCH_BIN=6.0 6.1 7.0 appropriately.
cmake -D CMAKE_BUILD_TYPE=Release -D BUILD_PNG=OFF -D BUILD_TIFF=OFF -D BUILD_TBB=OFF -D BUILD_JPEG=OFF -D BUILD_JASPER=OFF -D BUILD_ZLIB=OFF -D BUILD_EXAMPLES=OFF -D BUILD_opencv_java=OFF -D BUILD_opencv_python2=ON -D BUILD_opencv_python3=OFF -D ENABLE_NEON=ON -D WITH_OPENCL=OFF -D WITH_OPENMP=OFF -D WITH_FFMPEG=ON -D WITH_GSTREAMER=OFF -D WITH_GSTREAMER_0_10=OFF -D WITH_CUDA=ON -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-9.0 -D WITH_GTK=ON -D WITH_VTK=OFF -D WITH_TBB=ON -D WITH_1394=OFF -D WITH_OPENEXR=OFF -D CUDA_ARCH_BIN=6.0 6.1 7.0 -D CUDA_ARCH_PTX="" -D INSTALL_C_EXAMPLES=OFF -D INSTALL_TESTS=OFF ..
Make sure that it has detected CUDA ; Note the CUDA_TOOLKIT_ROOT_DIR path. This should change with different CUDA versios
CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-9.0
After this make install
make install
This should install OpenCV with headers in the Docker container. Now quit the container without killing it-https://stackoverflow.com/questions/25267372/correct-way-to-detach-from-a-container-without-stopping-it
Ctrl+p, Ctrl+q
Save the container
docker ps (and see the commit id of the container you just paused and exited say c1d0beb84729)docker commit -m "with opencv3.4" c1d0beb84729 alexcpn/nvidia-cuda9-opencv34:1.0
You can docker attach and kill the previous container.
Here is the Dockerfile for the same, if you just need OpenCV and no other tools for dev. Not that in the below file I am compiling OpenCV with GStreamer instead of FFMPEG as shown above.
FROM nvidia/cuda# This is a dev image, needed to compile OpenCV with CUDA# Install Gstreamer and OpenCV Pre-requisite libsRUN apt-get update -y && apt-get install -y \
libgstreamer1.0-0 \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
gstreamer1.0-doc \
gstreamer1.0-tools \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-devRUN apt-get update -y && apt-get install -y pkg-config \
zlib1g-dev libwebp-dev \
libtbb2 libtbb-dev \
libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev \
cmakeRUN apt-get install -y \
autoconf \
autotools-dev \
build-essential \
gcc \
gitENV OPENCV_RELEASE_TAG 3.4.5RUN git clone https://github.com/opencv/opencv.git /var/local/git/opencv
RUN cd /var/local/git/opencv && \
git checkout tags/${OPENCV_RELEASE_TAG}
RUN mkdir -p /var/local/git/opencv/build && \
cd /var/local/git/opencv/build $$ && \
cmake -D CMAKE_BUILD_TYPE=Release -D BUILD_PNG=OFF -D \
BUILD_TIFF=OFF -D BUILD_TBB=OFF -D BUILD_JPEG=ON \
-D BUILD_JASPER=OFF -D BUILD_ZLIB=ON -D BUILD_EXAMPLES=OFF \
-D BUILD_opencv_java=OFF -D BUILD_opencv_python2=ON \
-D BUILD_opencv_python3=OFF -D ENABLE_NEON=OFF -D WITH_OPENCL=OFF \
-D WITH_OPENMP=OFF -D WITH_FFMPEG=OFF -D WITH_GSTREAMER=ON -D WITH_GSTREAMER_0_10=OFF \
-D WITH_CUDA=ON -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda/ -D WITH_GTK=ON \
-D WITH_VTK=OFF -D WITH_TBB=ON -D WITH_1394=OFF -D WITH_OPENEXR=OFF \
-D CUDA_ARCH_BIN=6.0 6.1 7.0 -D CUDA_ARCH_PTX="" -D INSTALL_C_EXAMPLES=OFF -D INSTALL_TESTS=OFF ..RUN cd /var/local/git/opencv/build && \
make install# Install other tools you need for development
Note that we are using nvidia/cuda which is a fat image and is needed for the build. But nvidia/cuda-runtime can be used for runtime.
Now you can do docker volume mapping and work inside this Docker image for compiling and other development activities.
docker run --net=host --runtime=nvidia -it -v /home/alex/coding:/coding dockerimagename
If you need to have display; You can run the following command first in the host.
sudo xhost +
--output --> access control disabled, clients can connect from any host
And then run the container.
docker run --net=host --env DISPLAY=unix$DISPLAY --privileged --volume $XAUTH:/root/.Xauthority --volume /tmp/.X11-unix:/tmp/.X11-unix --rm --runtime=nvidia --rm -it -v /home/alex/coding:/coding alexcpn/nvidia-cuda-grpc:1.1 bash
If you need to Dockerise your application; you can create a much leaner image than the development image above. For that you can use Docker mutli-stage build concept to create a runtime Docker container.
FROM alexcpn/cuda9-grpc-opencv34-gstreamer:latest as buildFROM nvidia/cuda:9.0-runtime# Copy the compiled libs of OpenCV, GRPC and Protobuf from buildCOPY --from=build /usr/lib/lib* /usr/local/lib/
COPY --from=build /usr/local/lib/* /usr/local/lib/
COPY --from=build /usr/local/include/* /usr/local/include/
COPY --from=build /usr/lib/x86_64-linux-gnu/ /usr/lib/x86_64-linux-gnu/# Install GStreamer related libs - just copying libs wont help wih h264 decode
RUN apt-get update -y && apt-get install -y \
libgstreamer1.0-0 \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-libav
RUN apt-get install -y gstreamer1.0-tools# Do the rest what you need
The other option of compiling OpenCV with CUDA is to install CUDA in your machine and install OpenCV
Download and install CUDA, currently CUDA 8, but without installing the drivers; There is a --driver=no
option in command line; But follow the installation dialog and prompt no when asked.
Check the installation via nvccc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2016 NVIDIA Corporation
Built on Tue_Jan_10_13:22:03_CST_2017
Cuda compilation tools, release 8.0, V8.0.61
Note :- If you get a perl5 missing error in Ubuntu 17 , please see this https://devtalk.nvidia.com/default/topic/968656/cuda-8-0-on-debian/
Now on-to compiling OpenCV with CUDA; Most of the CNN based frameworks use OpenCV for image pre-processing; OpenCV also uses ffmpeg/gstreamer and some other libraries in the back-end; so step 1 here is 3. -Install all pre-requisites
sudo apt-get -y update
sudo apt-get -y upgrade
sudo apt-get -y autoremovesudo apt-get install -y cmake pkg-config \
zlib1g-dev ffmpeg libwebp-dev \
libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev \
libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
4. Then Download OpenCV; I used OpenCV 3.0 and OpenCV 3.3.0 and also OpenCV 3.4.
There are two option also here; One configure CMake graphically using cmake-gui listed below; or use a command line to configure
Install via CMake command line
mkdir build
inside opencv** extracted folder. Set the CUDA Path and Lib path in case CMake complains like
OpenCV is not able to find/configure CUDA SDK (required by WITH_CUDA).CUDA support will be disabled in OpenCV build.
cd build
sudo ldconfig /usr/local/cuda/lib64 or say for running darknetexport PATH=$PATH:/usr/local/cuda/bin
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64cmake -D CMAKE_BUILD_TYPE=Release -D BUILD_PNG=OFF -D BUILD_TIFF=OFF -D BUILD_TBB=OFF -D BUILD_JPEG=OFF -D BUILD_JASPER=OFF -D BUILD_ZLIB=OFF -D BUILD_EXAMPLES=OFF -D BUILD_opencv_java=OFF -D BUILD_opencv_python2=ON -D BUILD_opencv_python3=OFF -D ENABLE_NEON=ON -D WITH_OPENCL=OFF -D WITH_OPENMP=OFF -D WITH_FFMPEG=ON -D WITH_GSTREAMER=OFF -D WITH_GSTREAMER_0_10=OFF -D WITH_CUDA=ON -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-8.0 -D WITH_GTK=ON -D WITH_VTK=OFF -D WITH_TBB=ON -D WITH_1394=OFF -D WITH_OPENEXR=OFF -D CUDA_ARCH_BIN=6.0 6.1 7.0 -D CUDA_ARCH_PTX="" -D INSTALL_C_EXAMPLES=OFF -D INSTALL_TESTS=OFF .. -DCUDA_CUDART_LIBRARY=/usr/local/cuda/lib64/libcudart.so
If all dependencies are present cmake configuration will be successful and you should be able to make opencv. Not the options marked in bold. Change for your CUDA version and also only the needed CUDA_ARC_BIN. It will make compilation go much faster
sudo make install
That’s it.
In the beginning it may be easier for you to see all the OpenCV options via a GUI tools. You can configure CMake options graphically via CMake GUI. Follow the steps below
Install via CMake-GUI
mkdir build
inside opencv** extracted folder
cd build
cmake ..
This will create intial CMakeCache.txt and also the make file; Now we do not need a lot of libraries and architectures; So removing unwanted and limiting the rest, we can reduce the compile time significantly.
Easy to do via cmake-gui
sudo apt-get install cmake-qt-gui
Change these configuration, by running cmake-gui in the build folder
cmake-gui
Note the CUDA_ARCH_BIN selected by default CMake, You need to set the architecture for only the architecture that your card supports -https://developer.nvidia.com/cuda-gpus#collapse4
You can see that for GTX 1070 it supports compute capability 6.1 and from the same source there is a hyperlink to the card Architecure — it is Pascal here
Setting just the needed CUDA_ARCH_BIN and CUDA_GENERATION will speed up the compile time
If you are using CUDA, you don’t need OpenCL; Actually very few CNN libs (if any, maybe some from Intel) use OpenCL now; Also you do not need OpenBLAS, CUDA has a BLAS library
Check the WITH configurations, we need CUDA, we also need ffmpeg and other libs for working with pictures of different formats , videos etc
When this is done Run Configure
and if there are no errors run Generate
to gernerate the Make file
Now run sudo make install
Compilation takes about half an hour on my Core i7 machine;
P.S- If after installing tensorflow-gpu , you are getting errors regarding Cuda lib linkage please run sudo ldconfig /usr/local/cuda/lib64
or say for running darknet
export PATH=$PATH:/usr/local/cuda/bin
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64
That’s it. The preferred method now is the first. Use nvidia-docker for building OpenCV inside Docker container and use Docker volume mapping for development.