How I compile OpenCV on Linux with lots of bells and whistles (CuDNN, CUDA, OpenGL, Qt, TrueType, Video CODECs)
Tags: opencv, python, cuda
Published: 2021-02-16 02:09:32

---
title: How I compile OpenCV on Linux with lots of bells and whistles (CuDNN, CUDA, OpenGL, Qt, TrueType, Video CODECs)
published: true
description: Compiling OpenCV with many optional features enabled.
tags: opencv,python,cuda
cover_image: https://upload.wikimedia.org/wikipedia/commons/5/53/OpenCV_Logo_with_text.png
---

Em [português](https://monique.dev/post/opencv/).

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.

# Downloading

You need two projects in order to build OpenCV: the [OpenCV](https://github.com/opencv/opencv) source code and OpenCV [contrib](https://github.com/opencv/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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9j200ku8p9m40i4yci2p.png)

# Dependencies

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

```console
--   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
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkf4fj56cwg7joh5c0pj.png)
* `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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ri1jx1v2xq8c6aahwfw3.png)
* `ffmpeg + gstreamer` - if you want to load different video encodings:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kv61j50z5xf9yp5zbuyy.png)
* `libfreetype-dev + libharfbuzz-dev` - if you want support for truetype fonts
* `CUDA + CuDNN` - this one deserves a more detailed explanation bellow.

## CUDA + CuDNN

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:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61phl56afoj4ziabwrry.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tdsyvs01m2wx9ad387an.png)

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:

```bash
cmake -D CMAKE_CXX_COMPILER=/usr/bin/g++ \
-D CUDA_HOST_COMPILER:FILEPATH=/usr/bin/gcc-9 \
-D CUDA_NVCC_FLAGS=--expt-relaxed-constexpr \
-D WITH_CUDA=ON \
-D WITH_CUDNN=ON \
-D CUDNN_INCLUDE_DIR=/usr/lib/cuda-11.1/include \
-D OPENCV_DNN_CUDA=ON \
-D ENABLE_FAST_MATH=1 \
-D CUDA_FAST_MATH=1 \
-D CUDA_ARCH_BIN=8.6 \
-D WITH_CUBLAS=1 \
-D WITH_TBB=ON \
-D WITH_OPENMP=ON \
-D WITH_IPP=ON \
-D CMAKE_BUILD_TYPE=RELEASE \
-D WITH_CSTRIPES=ON \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
-D CMAKE_INSTALL_PREFIX=/usr/local/ \
-D WITH_QT=ON \
-D WITH_OPENGL=ON \
-D BUILD_EXAMPLES=OFF \
-D BUILD_DOCS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D BUILD_TESTS=OFF \
-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())") \
..
```
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 https://developer.nvidia.com/cuda-gpus
* `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.

# Compiling

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

```bash
make -j<number of processes>
```

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.

# Installing

If everything went fine and dandy:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dmme6y95n7525ca9qf8.png)

💯% baby!

All you need to do is:

```bash
sudo make install
```

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

# Validating

To test your achievement:

```console
$ python3
>>> import cv2
>>> print(cv2.getBuildInformation())
```

You should see the same output as cmake's.

# Using

In order to use OpenCV with a venv (you can read more about venv [here](https://dev.to/moniquelive/autocompletion-globally-installed-opencv-with-pycharm-308a)) use the flags:

```bash
python -mvenv --system-site-packages venv 
```

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

# Closing

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

If you need any help just leave a comment!

Good luck.