Make OpenCV2 work again

A battle with OpenCV2 compilation.

Cecilia Zhang ☕

Today I spent hours to finally compile OpenCV2 from source with CUDA 9.0. Although people mostly use OpenCV3+ these days, there are older software and libraries that are only compatible with OpenCV2. For others' convenience, and also for my own record, I write this OpenCV2 'memoir' and hopefully it saves some others people's time. I probably have gone through all possible troubles you could and could not imagine to make OpenCV2 work, and it is surprising that the solution for each comes from a different online source.

My system is Debian, CUDA 9.0, and I compiled OpenCV2.4.13.5 with CMake. If you encounter similar problems, or just are curious what makes a seemingly trivial task this complicated. Keep reading and hopefully it answers your questions.


To get started, this is how I get the source files: wget https://github.com/opencv/opencv/archive/2.4.13.5.zip -O opencv-2.4.13.5.zip Most online instructions would ask you to do a simple mkdir build && cd build and then cmake .. && make. Then that's it? No, it never works out of the box when you have to deal with CUDA.

Unsupported gpu architecture 'compute_20'

Example error message: Unsupported gpu architecture 'compute_20'
FIX: Pass the following CMake flag when you do cmake:

						-D CUDA_GENERATION=Auto
					
Make sure CUDA NVCC target flags doesn't have compute_20 in it.

Error in building opencv with ffmpeg

Example error message: "cap_ffmpeg_impl.hpp:1484:21: error: ‘CODEC_FLAG_GLOBAL_HEADER’ was not declared"
FIX: In side ./modules/highgui/src/cap_ffmpeg_api.hpp, copy the following lines and paste to the top of the file:

						#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
						#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
						#define AVFMT_RAWPICTURE 0x0020
					
source

CUDA library NOTFOUND

Example error message: "CMake Error: Variables are set to NOTFOUND"
FIX: Change in ./opencv/cmake/FindCUDA.cmake and ./opencv/cmake/OpenCVDetectCUDA.cmake. This involves two steps of changes, quite significant so I'd leave the link to the solution below. The main idea is to split the nppi library into multiple ones. And comment out all __cuda_arch_bin followed by a version lower than 3.0 (or remove all the version numbers that are lower than 3.0).

				
source

Private and public CUDA header

Example error message: "private.cuda.hpp: No such file or directory"
FIX: Add conditional include of cuda_fp16.h to file: modules/cudev/include/opencv2/cudev/util/saturate_cast.hpp, right after #include "../common.hpp"

					#if __CUDACC_VER_MAJOR__ >= 9
					#include 
					#endif
				
source

Unsupported GNU version

Example error message: "gcc versions later than 6 are not supported!"
FIX: This is an easy fix. Specify the version of gcc and g++ in your CMake flags (any version that higher than 6, don't forget the hyphen before the number):

					-D CMAKE_CXX_COMPILER=/usr/bin/g++-6 CMAKE_C_COMPILER=/usr/bin/gcc-6
				
Also add -D CUDA_NVCC_FLAGS="-ccbin gcc-6" at the back of your CMake flags.

Error in functions with incompatible execution space

Example error message: "error: calling a constexpr __host__ function"
FIX: Add --expt-relaxed-constexpr to CMake flag -D CUDA_NVCC_FLAGS. Combined with the previous "gcc" flag, set the nvcc flag to:

						-D CUDA_NVCC_FLAGS="-ccbin gcc-6;--expt-relaxed-constexpr"
					
source


Finally, this is the CMake flags I used to generate Makefile and then compile:
				cmake -G "Unix Makefiles" -DCUDA_GENERATION=Auto -DCMAKE_CXX_COMPILER=/usr/bin/g++-6 CMAKE_C_COMPILER=/usr/bin/gcc-6 -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=/usr/local -DWITH_TBB=ON -DBUILD_NEW_PYTHON_SUPPORT=ON -DWITH_V4L=ON -DWITH_QT=ON -DWITH_OPENGL=ON -DBUILD_FAT_JAVA_LIB=ON -DINSTALL_TO_MANGLED_PATHS=ON -DINSTALL_CREATE_DISTRIB=ON -DINSTALL_TESTS=ON -DENABLE_FAST_MATH=ON -DWITH_IMAGEIO=ON -DBUILD_SHARED_LIBS=OFF -DWITH_GSTREAMER=ON -DCUDA_NVCC_FLAGS="-ccbin gcc-6;--expt-relaxed-constexpr" ..
				

It definitely takes minutes to compile, you can turn off the example compilations to save some time. And don't forget to clear the CMake cache whenever you re-compile! Usually I just delete the entire build directory and re-create one.
Finally, be patient and it's all worth it when the "long-time-no-see" 100% shows up in green.