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 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:
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
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:
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:
ffmpeg + gstreamer- if you want to load different video encodings:
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:
Super easy right? 🤣
Let's build it then!
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_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-cudnnpackage 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.
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>
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
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:
All you need to do is:
sudo make install
That's the only time you need to invoke root's super powers in order to write files on
To test your achievement:
$ python3 >>> import cv2 >>> print(cv2.getBuildInformation())
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
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!