DEV Community

Cover image for How I compile OpenCV on Linux with lots of bells and whistles (CuDNN, CUDA, OpenGL, Qt, TrueType, Video CODECs)

Posted on

How I compile OpenCV on Linux with lots of bells and whistles (CuDNN, CUDA, OpenGL, Qt, TrueType, Video CODECs)

Em português.

OpenCV is a beast of a library. It's huge. But it's also super flexible. You typically choose what your binary will contain by providing optional dependencies but sometimes you have to nudge it to the direction you need.

In this guide I'll show you how I compile it with the longest cmake line you'll ever see (hopefully) and I'll also add comments so you know what you need to compile it successfully.

Let's get started.


You need two projects in order to build OpenCV: the OpenCV source code and OpenCV contrib.

You can either download the latest versions as as zip/tar ball or you can clone them and checkout the version (aka tag) you need.

Whatever way you choose, for the purpose of this tutorial all you need is both projects to be sitting next to each other on the same folder:

Alt Text


If you install all the depencies I explain bellow you'll have:

--   OpenCV modules:
--     To be built:                 aruco bgsegm bioinspired calib3d ccalib core cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev cvv datasets dnn dnn_objdetect dnn_superres dpm face features2d flann freetype fuzzy gapi hfs highgui img_hash imgcodecs imgproc intensity_transform line_descriptor mcc ml objdetect optflow phase_unwrapping photo plot python3 quality rapid reg rgbd saliency shape stereo stitching structured_light superres surface_matching text tracking video videoio videostab xfeatures2d ximgproc xobjdetect xphoto
--     Disabled:                    world
--     Disabled by dependency:      -
--     Unavailable:                 alphamat cnn_3dobj hdf java julia matlab ovis python2 sfm ts viz
Enter fullscreen mode Exit fullscreen mode

This is what you'll need:

  • python3 + numpy - I generally install it globally, outside of any venv/virtualenv sandboxes. Having OpenCV installed globally I can reference it on the venv sandboxes when needed. You'll see a similar cmake output: Alt Text
  • python3-pyqt5.qtopengl - it's enough to bring in the dependencies in order to detect Qt + OpenGL. Why is OpenGL so important, you may ask? Hardware accelerated frame rates. You'll see a similar cmake output: Alt Text
  • ffmpeg + gstreamer - if you want to load different video encodings: Alt Text
  • libfreetype-dev + libharfbuzz-dev - if you want support for truetype fonts
  • CUDA + CuDNN - this one deserves a more detailed explanation bellow.


CUDA (and CuDNN) are usually installed under the same directory. And this directory is typically /usr/local/cuda-<version>. But this is not a rule. I use PopOS and it gets installed in /usr/lib/cuda-<version>. It can also have as many versions as you want installed in parallel:


As you can see above, even though CUDA-11.2 was installed automatically (it's the current version as of today), CuDNN is only available up until 11.1 so I was forced to install CUDA-11.1 as well in order to have both CUDA and CuDNN installed on the same tree structure.

In order for cmake to find CUDA and CuDNN all you need is add <your CUDA root>/bin to your path.

You can check like this:

Alt Text

Super easy right? 🤣

Let's build it then!

Check for dependencies

In order to compile you need to create a build folder inside your opencv library root folder (cd opencv; mkdir build; cd build).

Now take a deep breath and enjoy the largest command line I've ever written for a single command:

cmake -D CMAKE_CXX_COMPILER=/usr/bin/g++ \
-D CUDA_NVCC_FLAGS=--expt-relaxed-constexpr \
-D CUDNN_INCLUDE_DIR=/usr/lib/cuda-11.1/include \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
-D BUILD_opencv_python3=ON \
-D PYTHON3_EXECUTABLE=$(which python3) \
-D PYTHON_INCLUDE_DIR=$(python2 -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") \
-D PYTHON3_INCLUDE_DIR=$(python3 -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") \
-D PYTHON3_LIBRARY=$(python3 -c "from distutils.sysconfig import get_config_var;from os.path import dirname,join ; print(join(dirname(get_config_var('LIBPC')),get_config_var('LDLIBRARY')))") \
-D PYTHON3_NUMPY_INCLUDE_DIRS=$(python3 -c "import numpy; print(numpy.get_include())") \
-D PYTHON3_PACKAGES_PATH=$(python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") \
Enter fullscreen mode Exit fullscreen mode

Don't miss the double dots at the end!

Some configurations worth explaining:

  • CMAKE_CXX_COMPILER - to compile c++ files
  • CUDA_HOST_COMPILER:FILEPATH - to compile cuda files - During system76-cudnn package installation I noticed it installed gcc-9. Very deterministic (not), I know.
  • CUDA_NVCC_FLAGS - needed some day, may remove eventually
  • CUDNN_INCLUDE_DIR - check your cuda home folder
  • CUDA_ARCH_BIN - the architecture of your GPU. Check it here
  • OPENCV_EXTRA_MODULES_PATH - relative or absolute path to opencv_contrib folder

In order to validate if all your dependencies are ok, read the line Unavailable: ... in the beginning of the previous section and check for differences with yours.

If you need to rerun cmake, leave the build folder, destroy it, recreate it, change back to it, only then rerun cmake... It's a tedious process but there's no shortcut here unfortunately.


This step is the easiest. Given all the dependencies are met all you have to do is run the make command:

make -j<number of processes>
Enter fullscreen mode Exit fullscreen mode

I highly recommend using the -j flag in order to cut compilation time. If you want to keep using your machine while the compilation is running, I recommend using $(nproc)-2.

For your reference, using -j60 + nvme, the compilation process takes 5m30s here.

If anything goes wrong don't be afraid to scroll up (or search for error:) and check what happened.


If everything went fine and dandy:

Alt Text

💯% baby!

All you need to do is:

sudo make install
Enter fullscreen mode Exit fullscreen mode

That's the only time you need to invoke root's super powers in order to write files on /usr/local.


To test your achievement:

$ python3
>>> import cv2
>>> print(cv2.getBuildInformation())
Enter fullscreen mode Exit fullscreen mode

You should see the same output as cmake's.


In order to use OpenCV with a venv (you can read more about venv here) use the flags:

python -mvenv --system-site-packages venv 
Enter fullscreen mode Exit fullscreen mode

This will create a sub-folder named venv with a sandbox that comes with "system wide packages", such as ... you know it.


If you read until here, congrats, you are a very determined person 🤣

If you need any help just leave a comment!

Good luck.

Top comments (0)