OpenCV Python bindings with MacPorts

Compiling OpenCV 2.0 with Python 2.6 (installed via MacPorts) bindings is not straight forward. The main problem, as Gregory Dudek noted, is that using a version of Python installed via MacPorts isn't automatically linked to by the OS X (Darwin) C complier. The matter becomes more complicated if you have 3 different version of Python on the same system.

Assumptions

I'm assuming you have MacPorts installed and have run sudo port selfupdate recently. Also its assumed you have installed python with MacPorts.

I had a version of Python in /usr/local which I installed awhile ago with brew and lost a day because CMake was linking to its dylib files instead of the ones in /opt/local used by MacPorts. I ended up just uninstalling the brew version and a lot of my woes disappeared.

Requirements

Before we begin we need a few tid-bits...

  • python_select utility to first select the version of Python I wanted to install OpenCv for. So install it via
    1. sudo port install python_select

    then for Python 2.6
    1. sudo python_select python26
  • FFMpeg is required if you want to get the video stuff happening with OpenCV, and lets face it, its one of the main reasons to use it, so...
    1. sudo port install ffmpeg

    OpenCV does seem to come with ffmpeg and I think it compiles it as part of the process. Can someone confirm?
  • SWIG is listed as optional on the install instructions, but my understanding is that its required for Python bindings. Unfortunatly teh MacPorts version of SWIG doesn't include the Python interface, so you'll have to
    1. download: http://sourceforge.net/projects/swig/files/swig/swig-1.3.40/swig-1.3.40....
    2. compile & install yourself. A lesson of another day.

Getting OpenCv

I'm going with the most current release can always be obtained with (from the Terminal):

svn co http s://code.ros.org/svn/opencv/trunk opencv-trunk

Note: you'll need to have SubVersion installed for this to work. Hint: easy with MacPorts ;)

Apples Framework convention

Gregory Dudek suggests a fix to the problem:

On OS X (or, in fact, the core operating system kernel, Darwin), many packages are installed using Frameworks. They group together libraries and headers. The C compiler on Darwin has been extended to take a -framework PATH flag, and by default this causes the linker to look in the system directories, but not user-installed directories. You need to provide an extra -F DIRECTORY flag to specific the location of your user-installed frameworks (e.g. "-F /opt/local/Library/Frameworks/").

I found that setting the PYTHON_INCLUDE_DIR option (see bellow) to point to the correct place seemed to work.

Building and installing OpenCV

sudo chmod 000 /System/Library/Frameworks/Python.framework/

I found that even if OpenCV did compile when I tried to import it in Python I would keep getting the error: "Fatal Python error: Interpreter not initialized (version mismatch?)". This is because, as Gregory Dudek suggests, the compiler is using the system version of Python to link against instead of the MacPorts version. This command makes the system version inaccessible to the compiler and forces it to keep looking and find the one we want. There migth be another way to tell the compiler but bugger me if I could find it or get help on the subject.

Following the official instructions for installing OpenCV with some hints from the Mac OS X guide:

mkdir opencv/build
cd opencv/build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/opt/local -D BUILD_PYTHON_SUPPORT=ON -D BUILD_SWIG_PYTHON_SUPPORT=OFF -D BUILD_NEW_PYTHON_SUPPORT=ON -D PYTHON_INCLUDE_DIR=/opt/local/Library/Frameworks/Python.framework/Headers -D CMAKE_CXX_COMPILER=/usr/bin/g++-4.2 -D CMAKE_C_COMPILER=/usr/bin/gcc-4.2 -D BUILD_SWIG_PYTHON_SUPPORT=ON ..
ccmake .

Hit 't' to toggle advanced options on. Make sure:

BUILD_SWIG_PYTHON_SUPPORT = ON
CMAKE_CXX_COMPILER = /usr/bin/g++-4.2
CMAKE_C_COMPILER = /usr/bin/gcc-4.2
PYTHON_INCLUDE_DIR = /opt/local/Library/Frameworks/Headers
SWIG_DIR = /usr/share/swig/1.3.31
SWIG_EXECUTABLE = /usr/bin/swig

Note: the last two SWIG options will be different depending o where you installed it and which version you got.

make -j8

The -j8 seems to make it compile faster.
sudo make install

This should dump everything somewhere inside '/opt/local'. Note that the Python/SWIG stuff gets put in '/opt/local/lib/python2.6/site-packages' which you will need in your PYTHONPATH environmental variable. I have the following in my ~/.profile file:
export PYTHONPATH=/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages:${PYTHONPATH}
export PYTHONPATH=/opt/local/lib/python2.6/site-packages:${PYTHONPATH}

Also, don't forget to turn the frameworks back on:
sudo chmod 755 /System/Library/Frameworks/Python.framework/

Else you might get weird things happening in the future.

unsetting DYLD_LIBRARY_PATH

Seems that DYLD_LIBRARY_PATH so needed if you install to a place that the dynamically linked libraries can't find. This might be necessary if your "make install" put everything into /usr/local, which is the default. I found I got the following error when I had:

export DYLD_LIBRARY_PATH=/opt/local/lib

in my ~/.profile file:
>>> import cv
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dlopen(/opt/local/lib/python2.6/site-packages/cv.so, 2): Library not loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
  Referenced from: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib
  Reason: Incompatible library version: vecLib requires version 1.0.0 or later, but libLAPACK.dylib provides version 0.0.0
>>> 

which cleared up by removing the DYLD_LIBRARY_PATH from my ~/.profile file. This might be a bother if you need this set for something else.

PYTHONPATH

I found I also needed to set my PYTHONPATH to the location that cv.so was moved to by "make install" (should be the last line of its output). My ~/.profile file has the following line in it:

export PYTHONPATH=/opt/local/lib/python2.6/site-packages:${PYTHONPATH}

Further problems

I got the following errors after I ran cmake:

-- Looking for libavformat/avformat.h
-- Looking for libavformat/avformat.h - not found
-- Looking for ffmpeg/avformat.h
-- Looking for ffmpeg/avformat.h - not found
-- checking for module 'libdc1394-2'
--   package 'libdc1394-2' not found
-- checking for module 'libdc1394'
--   package 'libdc1394' not found

Despite this the Cam demos for Python seemed to work.


Well, that was 4 days of my life I'll never get back.

As an alternative to the SWIG interface there is the PyOpenCv project which is still in Alpha at the time of writing this but seems to have a more OO interface and perhaps even be faster then SWIG. Will investigate and report back...

Comments

Eeek!

Here's a few points from my 4-day-build-marathon:
- it's important to use svn-trunk, I tried 2.1 assuming it would be more stable and couldn't get it to work
- quicktime support doesn't seem to be necessary for getting the webcam to work contrary to what I've read elsewhere - in the end I gave up trying to get it to compile and lo and behold, my webcam works!

Did you install both swig & swig-python from macports?