## Overview

If you’re here, you’ve probably discovered that the versions of opencv available on the Anaconda cloud (via the conda package manager) don’t have ffmpeg codecs compiled within them. This means that you can’t read or write videos using these versions of opencv. There is no easy way around this as far as I know, so here I’m going to cover how to go about building opencv from source. We’ll set up our build config to that opencv links with our version of python bundled within anaconda in addition to enabling ffmpeg integration so we can read/write videos.

I’ve tried to generalize my code as much as possible so that you can use this with any version of opencv and anaconda, so watch out for steps where I’m explicitly asking you to type in your opencv and python versions.

The following represents a streamlined version of this guide.

## Dependancies

As always, when building on linux I take a shotgun approach to dependancies. I’m just running a single call to apt covering all dependancies I’ve seen mentioned on other guides, or have figured out myself from build errors.

1. First, lets cover our build tools.

 sudo apt update

sudo apt install build-essential cmake pkg-config git

2. Now lets cover any libraries we might need.

 sudo apt install libjpeg8-dev libtiff5-dev libjasper-dev libpng12-dev \
libavcodec-dev libavformat-dev libswscale-dev libv4l-dev \
libxvidcore-dev libx264-dev libgtk-3-dev libatlas-base-dev gfortran


Some of these libraries may be specific to ubuntu 16.04, so dont worry if your using a different linux distro and some packages are missing. If you run into dependancy issues later on, you can use the error logs to figure out which packages you need. Now lets grab the relevant source code!

## Get the source code

Here, I’m going to be building from the latest stable release, which is 3.4.3 in my case. We’ll use git to grab the code and checkout version we need.

1. Clone the opencv git repository and checkout the version 3.4.3

 git clone https://github.com/opencv/opencv.git
cd opencv
git checkout 3.4.3
cd ..

2. Now that we have the opencv source, we’ll also need to clone another repo which covers installing the extra features we need, like ffmpeg integration of video codecs. Here, its important that we select the same version of both opencv and opencv_contrib.

 git clone https://github.com/opencv/opencv_contrib.git
cd opencv_contrib
git checkout 3.4.3
cd ..


## If you build it… they will come

After, you should have two folders in your current directory: opencv and opencv_contrib. Its important that you use the same version for both repos as they will depend on eachother for the build later.

1. Now lets set up a build directory. Its always a good idea to keep your builds seperate from your source files.

 cd opencv
mkdir build
cd build

2. Now we’ll setup our build configuration. First, we’ll have to manually specify the location of the anaconda install and the python version bundled with it. The following code should work if you copy and paste it as a single block into your terminal.

Using the values you provide at the top of the code block, the script will generate paths where it expects to find libraries relevant to the build. The latter part of the code block just checks that these generated paths do in fact exist. If the paths you provide are incorrect, it’ll throw some warning messages.

 ##########################################################
## Specify directories of anaconda and python libraries ##
##########################################################

anaconda="/home/james/anaconda3"
pythonVersion="3.7"

#################################################
## Check that user specified directories exist ##
#################################################
pass=true
############# Check Exec
pyExec="${anaconda}/bin/python" if [ ! -e "${pyExec}" ]; then
echo "${pyExec}/bin/python does not exist" pass=false fi ############# Check Lib pyLib="${anaconda}/lib/libpython${pythonVersion}m.so" if [ ! -e "${pyLib}" ]; then
echo "${pyLib} does not exist" pass=false fi ############# Check Dir pyDir="${anaconda}/include/python${pythonVersion}m" if [ ! -d "${pyDir}" ]; then
echo "${pyDir} does not exist" pass=false fi ############# Check Path pyPath="${anaconda}/lib/python${pythonVersion}" if [ ! -d "${pyPath}" ]; then
echo "${pyPath} does not exist" pass=false fi ############# Check Path pyNumpy=${anaconda}/lib/python${pythonVersion}/site-packages/numpy/core/include if [ ! -d "${pyNumpy}" ]; then
echo "${pyNumpy} does not exist" pass=false fi if [ "$pass" = true ]; then
echo "Paths verified, you can go ahead and configure the build"
fi


If you recieved the message Paths verified, you can go ahead and configure the build!, continue to the next step. Otherwise, double check that the anaconda path and python version you supplied in lines 2-3 are correct.

The path variables saved in this code block will be used in the next block, thus it’s important that you are using a single terminal session for all these steps (i.e. Do not close and reopen the terminal executing these code blocks).

Before proceeding, double check that you are in the build directory we made, and that your directory structure looks like this.

 ├── opencv
│   └── build
└── opencv_contrib


This is important, as I’ve coded in relative paths in the next code block which assume this structure.

Now lets run the build configuration. It’ll only run if the values you gave earlier were correct.

 #### Run configuration if direcotries exist
if [ "$pass" = true ]; then echo "Running configuration..." cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D INSTALL_C_EXAMPLES=OFF \ -D INSTALL_PYTHON_EXAMPLES=OFF \ -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \ -D BUILD_EXAMPLES=OFF \ -D BUILD_opencv_python2=OFF \ -D BUILD_opencv_python3=ON \ -D BUILD_TIFF=ON \ -D WITH_FFMPEG=1 \ -D WITH_CUDA=OFF \ -D ENABLE_FAST_MATH=1 \ -D PYTHON3_EXECUTABLE="${pyExec}" \
-D PYTHON3_INCLUDE_DIR="${pyDir}" \ -D PYTHON3_LIBRARY="${pyLib}" \
-D PYTHON3_PACKAGES_PATH="${pyPath}" \ -D WITH_LAPACK=OFF \ -D PYTHON3_NUMPY_INCLUDE_DIRS="${pyNumpy}" \
..
fi


When finished, you should see some output like below. Do a quick check to verify that FFMPEG is set to yes and that the Python 3 section points to the correct libraries within anaconda (as opposed to your systems default bin directory).

 --   GUI:
--     GTK+:                        YES (ver 3.18.9)
--       GThread :                  YES (ver 2.48.2)
--       GtkGlExt:                  NO
--     VTK support:                 NO
--
--   Media I/O:
--     ZLib:                        /home/james/anaconda3/lib/libz.so (ver 1.2.11)
--     JPEG:                        /home/james/anaconda3/lib/libjpeg.so (ver 90)
--     WEBP:                        /usr/lib/x86_64-linux-gnu/libwebp.so (ver encoder: 0x0202)
--     PNG:                         /home/james/anaconda3/lib/libpng.so (ver 1.6.34)
--     TIFF:                        build (ver 42 - 4.0.9)
--     JPEG 2000:                   /usr/lib/x86_64-linux-gnu/libjasper.so (ver 1.900.1)
--     OpenEXR:                     build (ver 1.7.1)
--     HDR:                         YES
--     SUNRASTER:                   YES
--     PXM:                         YES
--
--   Video I/O:
--     DC1394:                      NO
--     FFMPEG:                      YES
--       avcodec:                   YES (ver 57.107.100)
--       avformat:                  YES (ver 57.83.100)
--       avutil:                    YES (ver 55.78.100)
--       swscale:                   YES (ver 4.8.100)
--       avresample:                NO
--     GStreamer:
--       base:                      YES (ver 1.8.3)
--       video:                     YES (ver 1.8.3)
--       app:                       YES (ver 1.8.3)
--       riff:                      YES (ver 1.8.3)
--       pbutils:                   YES (ver 1.8.3)
--     libv4l/libv4l2:              NO
--     v4l/v4l2:                    linux/videodev2.h
--
--
--   Trace:                         YES (with Intel ITT)
--
--   Other third-party libraries:
--     Intel IPP:                   2017.0.3 [2017.0.3]
--            at:                   /home/james/opencv/build/3rdparty/ippicv/ippicv_lnx
--     Intel IPP IW:                sources (2017.0.3)
--               at:                /home/james/opencv/build/3rdparty/ippicv/ippiw_lnx
--     Eigen:                       NO
--     Custom HAL:                  NO
--     Protobuf:                    build (3.5.1)
--
--   NVIDIA CUDA:                   NO
--
--   OpenCL:                        YES (no extra features)
--     Include path:                /home/james/opencv/3rdparty/include/opencl/1.2
--
--   Python 3:
--     Interpreter:                 /home/james/anaconda3/bin/python3 (ver 3.7)
--     Libraries:                   /home/james/anaconda3/lib/lib3.7m.so (ver 3.7.0)
--     numpy:                       /home/james/anaconda3/lib/python3.7/site-packages/numpy/core/include (ver 1.15.1)
--     packages path:               /home/james/anaconda3/lib/python3.7
--
--   Python (for build):            /home/james/anaconda3/bin/python
--
--   Java:
--     ant:                         NO
--     JNI:                         NO
--     Java wrappers:               NO
--     Java tests:                  NO
--
--   Matlab:                        NO
--
--   Install to:                    /usr/local
-- -----------------------------------------------------------------
--
-- Configuring done
-- Generating done
-- Build files have been written to: /home/james/opencv/build
-- Configuring done
-- Generating done


If you find you accidentally set a wrong path during the configuration, I strongly suggest deleting the contents of the build directory before rerunning the configuration again with new parameters. It’s a known issue that cached values in the configuration step can linger and cause problem even when you rerun the configuration with new values.

3. Now we’ll build the library. We should still be in the build folder at this point, and you can use the option -j<n-cores> to specity how many cores you want to give opencv access to. Note that this build can take quite some time, so expect to wait over 20 minutes for this to complete.

If you run into any errors at this step, you’ll have to look through the error messages and see if you can pinpoint a specific library thats causing problems. Once you found it, you can typically resolve the issue by either installing the missing library with apt or changing your build configuration. In my case, I kept on getting errors when building the examples. The simple solution to this was just to add -D BUILD_EXAMPLES=OFF as a build option. Whatever the problem is, make sure to nuke your build direcory and rerun the build configuration before trying to compile again.

 make -j4


Finally, copy the compiled libraries the the correct destinations by calling the install recepie.

 sudo make install
sudo ldconfig

4. Finally, lets validate that opencv is linked to anaconda. Open spyder (or any python console in anaconda), and enter:

 import cv2
cv2.__version__


Your output should be 3.4.3, which matches the version we just installed.

## Final Thoughts

### Font library errors when importing opencv library

I first ran this install script on Elementary os (based on Ubuntu 16.04) and it worked like a charm! The second time I ran this I was using Ubuntu 18.04 and after a sucessfull build I ran into the error: libfontconfig.so.1: undefined symbol: FT_Done_MM_Var when trying to import cv2. The strange thing is that this error did not appear when I was using ipython in spyder, but did appear in all other python IDEs I tried running (like VS Code), even though they were all running the same python binary file (in anaconda3/bin). As far as I can tell, this seems to be related to differently defined paths between the python IDEs I tried. The solution is simple and has been described here.

Delete the problematic libraries from anaconda3/lib which are mentioned in the error message. After you delete one, an error message for the next library should appear when you try to import opencv again.

• <...>/anaconda3/lib/libfontconfig.so
• <...>/anaconda3/lib/libfontconfig.so.1
• <...>/anaconda3/lib/libfontconfig.so.1.11.1
• <...>/anaconda3/lib/libpangoft2-1.0.so.0
• <...>/anaconda3/lib/libpangoft2-1.0.so.0.4200.4

After deleting these libraries, I was able to import and run opencv apps without issue. My assumption is that some of these current anaconda3 libraries are incompatable with Ubuntu 18.04 and deleteing them causes Anaconda to revert to the system default libraries which work fine.

Updated on: 2018-11-06