Unusual Subroutines


The blog and musings of Christopher Allen-Poole

How to Install OpenCV with MacPorts

This post is extremely technical, and I'm guessing that it won't be much use to anyone who isn't trying to install OpenCV on macos. Of course, if you happen to be one such person, then I hope this saves you the two dozen or so hours that it cost me to figure it out. I'm going to start out by assuming you've already created a virtualenv, cloned/downloaded the OpenCV core library to ~/opencv/ and the contrib library to ~/opencv_contrib, created the /opencv/build directory and cd'd into it.

Oh, but before we get going, you might want to check out ../CMakeLists.txt. This gives you documentation of all of the valid compiler flags. It would have saved me a headache (that I'll describe below).

Replace XXX and YYY

Recently tried to install OpenCV based on this tutorial, but somehow the difference between the MacPorts and the Homebrew libs caused some severe compiler problems.

I started with the provided compiler instructions. Obviously, this path is completely wrong: /usr/local/Cellar/python3/3.*/Frameworks/Python.framework/Versions/3.5/lib/python3.5/config-3.5m/libpython3.5.dylib. I'm working in Python 3.6 for the first part, and I don't have a Cellar directory either. Basically, I was looking for the Python install libraries, so my first guess was just the __file__ attribute of a core package.

I tried python -c 'import os; print(os.__file__)'. This gave me: /opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/os.py. From there it was easy to get to the libpython3.6.dylib file: it's in the parent directory. Then I used find with a wildcard (like his ls trick): find /opt/local/Library/Frameworks/Python.framework/Versions/ -type d -name py'*'3.*m. This gave me: /opt/local/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m

This gave me a cmake command that looked a bit like this:

~/opencv/build/ > workon cv2
(cv2) ~/opencv/build/ > cmake -D CMAKE_BUILD_TYPE=RELEASE     \
            -D CMAKE_INSTALL_PREFIX=/usr/local     \
            -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules     \
            -D PYTHON3_LIBRARY=/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/libpython3.6.dylib     \
            -D PYTHON3_INCLUDE_DIR=/opt/local/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m/      \
            -D PYTHON3_EXECUTABLE=$VIRTUAL_ENV/bin/python     \
            -D BUILD_opencv_python2=OFF     \
            -D BUILD_opencv_python3=ON     \
            -D INSTALL_PYTHON_EXAMPLES=ON     \
            -D INSTALL_C_EXAMPLES=OFF     \
            -D BUILD_EXAMPLES=ON ..

Notice that I am using the $VIRTUAL_ENV. You may need to replace $VIRTUAL_ENV/bin/python with the value from `which python`.

Missing FreeType

The make command requires that you have "freetype". Unfortunately, there are several different libraries:

(cv2) ~/opencv/build/ > pip search freetype
Freetype (Milestone1)  - Freetype 2 library bindings
freetype-py (1.0.2)    - Freetype python bindings
freetypy (0.1)         - Fast and modern wrappers for FreeType

Here, you want the freetype-py library. I installed the headers through sudo port install freetype and then followd by pip install freetype-py. Thought all would be good, but nope:

(cv2) > python -c 'import freetype'

Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'freetype'

Maybe I made a mistake? I tried re-installing freetype-py

(cv2) ~/opencv/build/ > pip install freetype-py
Requirement already satisfied: freetype-py in /Users/christopherallen-poole/.virtualenvs/rogue/lib/python3.6/site-packages

It looks like this is a Python install problem. It looks for the headers files (libfreetype.dylib) in a different directory from the one MacPorts uses. MacPorts puts everthing under the /opt/local/lib/ directory but Python was looking under /usr/local/lib. Once I figured that out, I was able to resolve with a judicious symlink:

(cv2) ~/opencv/build/ > sudo mkdir -p /usr/local/lib # you may need to create the directory, too
(cv2) ~/opencv/build/ > sudo ln -s /opt/local/lib/libfreetype.dylib /usr/local/lib/
(cv2) ~/opencv/build/ > sudo ln -s /opt/local/include/freetype2/freetype /usr/local/include/
(cv2) ~/opencv/build/ > python -c "import freetype"
(cv2) ~/opencv/build/ > # SUCCESS!

Missing Harfbuzz

Seriously? What sort of hidden requirements? Arggg… At least now that we've solved FreeType, Harfbuzz is a lot easier.

(cv2) ~/opencv/build/ > sudo port install harfbuzz
(cv2) ~/opencv/build/ > sudo port install harfbuzz-icu # not sure if this is needed
(cv2) ~/opencv/build/ > sudo ln -s /opt/local/lib/libharfbuzz.dylib /usr/local/lib/ # Same as FreeType 

Missing Eigen

Ah! Well, this is just a case of… sudo port install, right? Wait a minute. Maybe not.

I couldn't find the eigen directory under /opt/local/lib. make would not recognize eigen3 directory either. Eventually a Stack Overflow question pointed me in the right direction. I added a compiler flag to include the path: -D EIGEN_INCLUDE_PATH=/opt/local/include/eigen3.

Final Cmake -> make -> install Commands

(cv2) ~/opencv/build/ > cmake -D CMAKE_BUILD_TYPE=RELEASE \
     -D CMAKE_INSTALL_PREFIX=/usr/local \
     -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
     -D PYTHON3_LIBRARY=/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/libpython3.6.dylib \
     -D PYTHON3_INCLUDE_DIR=/opt/local/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m/ \
     -D PYTHON3_EXECUTABLE=$VIRTUAL_ENV/bin/python \
     -D BUILD_opencv_python2=OFF \
     -D BUILD_opencv_python3=ON \
     -D INSTALL_PYTHON_EXAMPLES=ON \
     -D INSTALL_C_EXAMPLES=OFF \
     -D BUILD_EXAMPLES=ON 
     -D EIGEN_INCLUDE_PATH=/opt/local/include/eigen3 ..

So far so good.

(cv2) ~/opencv/build/ > make # I didn't try any multi-core work here. It broke more than once
# lots of stuff happens. Go get a bite to eat.
(cv2) ~/opencv/build/ > # SUCCESS!!!

Holy cow it worked. Now it's time to install. Remember to use sudo.

(cv2) ~/opencv/build/ > sudo make install

This will move the .so file into the global site-packages folder. In this case, it's roughly the same as Mr. Rosebrock's.

(cv2) ~/opencv/build/ > sudo ln -s /usr/local/lib/python3.6/site-packages/cv2.cpython-36m-darwin.so /usr/local/lib/python3.6/site-packages/cv2.so
(cv2) ~/opencv/build/ > cd $VIRTUAL_ENV/lib/python3.6/
(cv2) ~/opencv/build/ > ln -s /usr/local/lib/python3.6/site-packages/cv2.cpython-36m-darwin.so ./cv2.so
(cv2) ~/opencv/build/ > python -c 'import cv2'
(cv2) ~/opencv/build/ > 

Congratulations! If you don't have an error on that last line, you win!

blog comments powered by Disqus