Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiling mexopencv in OS X 10.9 with Xcode 5 and Matlab R2013b

I'm interested in using Kota Yamaguchi's mexopencv library on my system with the following specifications:

  • OS X 10.9 (Mavericks)
  • Xcode 5
  • Matlab 2013b
  • OpenCV installed via macports to /opt/local/include/{opencv,opencv2} and /opt/local/lib

I git cloned the latest OpenCV revision using the command on the mexopencv web site; this is version 084838d62a25fcb3eec9f610abf91b167bc6c2f5 from Sat Jul 20 05:18:37 2013 -0700.

I ran Matlab's mex -setup command and then implemented this workaround from Mathworks to use Xcode 5 as my mex compiler.

I added macports' pkg-config command to the path with the Matlab command setenv('PATH', [getenv('PATH') ':/opt/local/bin']);

Now, running mxopencv.make yields the following linker error message:

Undefined symbols for architecture x86_64:
  "cv::merge(std::vector<cv::Mat, std::allocator<cv::Mat> > const&, cv::_OutputArray const&)", referenced from:
      MxArray::toMat(int, bool) const in libMxArray.a(MxArray.o)
  "cv::split(cv::Mat const&, std::vector<cv::Mat, std::allocator<cv::Mat> >&)", referenced from:
      MxArray::MxArray(cv::Mat const&, mxClassID, bool) in libMxArray.a(MxArray.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

    mex: link of ' "+cv/CamShift.mexmaci64"' failed.

make: *** [+cv/CamShift.mexmaci64] Error 255

I'm not sure what to do at this point. Is it possible to build mexopencv on my system?

like image 239
Daniel Golden Avatar asked Nov 04 '13 17:11

Daniel Golden


1 Answers

I finally figured out my problem, the solution of which led to other problems, which I eventually was able to solve. So here's a complete step-by-step procedure of what I did to get mexopencv working on my system (some steps will be repeated from my original question).

  1. Get mexopencv from http://www.cs.sunysb.edu/~kyamagu/mexopencv/
  2. Implement the Mathworks workaround to get the Matlab mex compiler working with Xcode 5
  3. Run mex -setup from within Matlab
  4. Modify the newly-created ~/.matlab/R2013b/mexopts.sh file as follows:

    1. Replace all references of "-lstdc++" with "-lc++"
    2. Add the following arguments to the CXXFLAGS variable: "-std=gnu++11 -stdlib=libc++". These two steps ensure that you're using C++11 instead of C++98 (thanks to this stack overflow post).
    3. You should have already replaced all instances of the text "10.7" with "10.8" from an earlier step
    4. Change the line

    MLIBS="-L$TMW_ROOT/bin/$Arch -lmx -lmex -lmat"

    to

    MLIBS="$TMW_ROOT/bin/$Arch/libmx.dylib $TMW_ROOT/bin/$Arch/libmex.dylib $TMW_ROOT/bin/$Arch/libmat.dylib"
    

    This ensures that the compiler does not search for OpenCV libraries in $TMW_ROOT/bin/$Arch which, on my system, evaluates to /Applications/MATLAB_R2013b.app/bin/maci64. For whatever reason, libraries from an older version of OpenCV (2.4.2) come with Matlab and live in that folder (maybe they come with the Computer Vision System Toolbox). [Note: this step may not be necessary]

  5. Create a folder /Applications/MATLAB_R2013b.app/bin/maci64/libopencv and move all of the libopencv*.dylib files from /Applications/MATLAB_R2013b.app/bin/maci64 into that folder. This prevents the linker from finding and accidentally linking to this older version of OpenCV.
  6. Add macports' pkg-config command to the Matlab path with the Matlab command setenv('PATH', [getenv('PATH') ':/opt/local/bin']); To avoid entering this command every time you start Matlab, you can add this to your startup.m file. Mine lives in ~/Documents/MATLAB/startup.m.
  7. Make sure that you run mexopencv.make('clean', true); in Matlab to erase any prior failed attempts at compiling mexopencv
  8. Run mexopencv.make in Matlab; it should work properly (with some warnings) and in five minutes or so you will have a MEX-compiled version of OpenCV; congratulations! But you're not done yet.

I tried out my installation of OpenCV with a simple one-liner test:

imshow(cv.Canny(rgb2gray(imread('peppers.png')), [10 100]))

When I attempted to run it at this point, I got the following error message:

>> imshow(cv.Canny(rgb2gray(imread('peppers.png')), [10 100]));
Error using cv.Canny
Invalid MEX-file '/Users/dgolden/software/cpp/mexopencv/+cv/Canny.mexmaci64': dlopen(/Users/dgolden/software/cpp/mexopencv/+cv/Canny.mexmaci64, 6): Library not loaded:
/opt/local/lib/libtiff.5.dylib
  Referenced from: /opt/local/lib/libopencv_highgui.2.4.dylib
  Reason: Incompatible library version: libopencv_highgui.2.4.dylib requires version 8.0.0 or later, but libtiff.5.dylib provides version 6.0.0

The problem is that Matlab has its own version of some macports-installed libraries, contained in /Applications/MATLAB_R2013b.app/bin/maci64, that are different from the ones in /opt/local/lib. By default, Matlab tries to dynamically link its own versions of the libraries, which are not the versions that OpenCV expects, so the program doesn't run.

The solution is suggested in the README.markdown file included with mexopencv. You need to tell Matlab not to use its own version of the shared libraries and to instead use the versions from /opt/local/lib.

You can do this one of two ways. First, try to run your program and note the name of the library that yields an error. Then, either:

  1. Find the library file in /Applications/MATLAB_R2013b.app/bin/maci64 and rename or move it. E.g., rename /Applications/MATLAB_R2013b.app/bin/maci64/libtiff.5.dylib to /Applications/MATLAB_R2013b.app/bin/maci64/libtiff.5.dylib.bak. This might have unintended consequences if other Matlab functionality depends on that library. You shouldn't need to do anything else in order for OpenCV to find the correct library in /opt/local/lib.
  2. Close Matlab and start it from the command line by first setting the DYLD_INSERT_LIBRARIES environment variable, like:

    DYLD_INSERT_LIBRARIES=/opt/local/lib/libtiff.5.dylib /Applications/MATLAB_R2013b.app/bin/matlab &

    In my case, after I solved the problem with libtiff.5.dylib, I also had a problem with libfreetype.6.dylib, so I added that to the DYLD_INSERT_LIBRARIES variable, like:

    DYLD_INSERT_LIBRARIES=/opt/local/lib/libtiff.5.dylib:/opt/local/lib/libfreetype.6.dylib /Applications/MATLAB_R2013b.app/bin/matlab &

Then try to run your program again. If you get another library version error, keep iterating and either renaming/moving libraries from /Applications/MATLAB_R2013b.app/bin/maci64 or adding the correct library paths to the DYLD_INSERT_LIBRARIES variable. Eventually, it should work!

After I followed all these steps, I was able to run my Matlab command successfully:

imshow(cv.Canny(rgb2gray(imread('peppers.png')), [10 100]))

Let me know if these steps did or didn't work for you, and whether I skipped any steps or made anything more complicated than it had to be.

I hope this helps someone! I spent several days combing the Internet and bothering Kota to finally arrive at the correct solution.

like image 69
Daniel Golden Avatar answered Sep 21 '22 04:09

Daniel Golden