EmguCV on the Raspberry Pi with Mono

Aug 28, 2014

These are my notes on getting OpenCV working on the raspberry pi with mono. In order to use OpenCV with C#, we will use EmguCV which is an open source C#  wrapper for the OpenCV C++ libraries. I'll add a disclaimer that I'm not claiming these hacks below are the most elegant way to get EmguCV compiled on Raspbian, it is just the path I took to determine if it was even at all possible - which it is - keep reading!

UPDATE January 2015: See these newer instructions

Prerequisites

These steps assume Raspbian Wheezy with hard float and a recent version of mono. Mono on my pi is compiled from source at version 3.2.7 (master/d7ce227 Monday 23 December 21:49:08 EST 2013).
The emgu git repository was cloned from commit e73c06e71b7e1628c54ec1165409367665721a8a, Date: Mon Aug 4 12:54:23 2014 -0400. The EmguCV master branch is actively being worked on so some of these instructions may already be out of date at the time of writing.

Download EmguCV and compile

Wheezy and Ubuntu are both based off Debian, so head to the EmguCV website and follow the instructions for Ubuntu. It won't work without some changes so read on.

The first problem you will hit is that the list of apt-get prerequisite packages will fail. Thread building blocks library libtbb-dev is not available for armhf in Wheezy. It will be available in Jessy. We will work around this so skip over this error by removing libtbb-dev from the install list and try again.

Go ahead and clone the emgucv repo as per EmguCV instructions. These are the easiest steps of the whole procedure so don't get cocky yet.

When you get to the cmake step, you will need to use this command line rather than the specified Ubuntu one

cmake -DBUILD_TESTS:BOOL=FALSE -DBUILD_DOCS:BOOL=FALSE -DEMGU_CV_WITH_TIFF:BOOL=FALSE -DWITH_TBB:BOOL=FALSE -DWITH_CUDA:BOOL=FALSE -DWITH_OPENCL:BOOL=FALSE -DWITH_IPP:BOOL=FALSE -DWITH_EIGEN:BOOL=FALSE

The options listed below were changed / added to set them to FALSE.

  • EMGUCV_WITH_TIFF Further along I was having trouble with this library. Turning it off helped get me past it.
  • WITH_TBB As noted above, libtbb-dev is not available on the armhf debian platform.
  • WITH_IPP Turning this off also solved some problems with make.
  • WITH_EIGEN Turning this off solved some problems with missing resources

With this configuration for CMake, you will get to about 89% through make when something like the following might happen:

[ 89%] Building CXX object opencv/modules/python/CMakeFiles/opencv_python.dir/sr c2/cv2.cpp.o
 c++: internal compiler error: Killed (program cc1plus)
 Please submit a full bug report,
 with preprocessed source if appropriate.
 See <file:///usr/share/doc/gcc-4.6/README.Bugs> for instructions.
 make[2]: *** [opencv/modules/python/CMakeFiles/opencv_python.dir/src2/cv2.cpp.o] Error 4
 make[1]: *** [opencv/modules/python/CMakeFiles/opencv_python.dir/all] Error 2
 make: *** [all] Error 2 

Whatever the problem was, I didn't plan on using the Python OpenCV bindings so I went ahead and deleted anything that looked CMake related from the opencv/modules/python/ tree. Onward.

After a new make make command, the next roadblock:

[ 91%] Building CXX object Emgu.CV.Extern/CMakeFiles/cvextern.dir/emgu_c.cpp.o
In file included from /home/pi/emgucv/Emgu.CV.Extern/emgu_c.cpp:7:0:
/home/pi/emgucv/Emgu.CV.Extern/emgu_c.h:13:37: fatal error: opencv2/text/erfilter.hpp: No such file or directory
compilation terminated.
make[2]: *** [Emgu.CV.Extern/CMakeFiles/cvextern.dir/emgu_c.cpp.o] Error 1
make[1]: *** [Emgu.CV.Extern/CMakeFiles/cvextern.dir/all] Error 2
make: *** [all] Error 2

I solved this by finding where that missing file was:
find . -name 'erfilter.hpp'
and copying it into the same folder as emgu_c.cpp.

Next up:

[100%] Building CXX object tests/cvextern_test/CMakeFiles/cvextern_test.dir/cvextern_test.cpp.o
Linking CXX executable ../../bin/cvextern_test
/usr/bin/ld: warning: libtiff.so.4, needed by /usr/lib/liblept.so.3, may conflict with libtiff.so.5
../../bin/libcvextern.so: undefined reference to `cv::text::ERStat::ERStat(int, int, int, int)'
collect2: ld returned 1 exit status
make[2]: *** [bin/cvextern_test] Error 1
make[1]: *** [tests/cvextern_test/CMakeFiles/cvextern_test.dir/all] Error 2
make: *** [all] Error 2

At this stage I was getting good at removing code willy nilly, so wherever I found a reference to cvextern_test in a CMakelist.txt file, I chopped it out.

The make is reporting 100% as you can see above but there still a few more hurdles to clear:
/home/pi/emgucv/Emgu.CV/PInvoke/Unity/TextureConvert.cs(6,7): error CS0246: The type or namespace name `UnityEngine' could not be found. Are you missing an assembly reference?
/home/pi/emgucv/Emgu.CV/PInvoke/Unity/TextureConvert.cs(20,76): error CS0246: The type or namespace name `Texture2D' could not be found. Are you missing an assembly reference?
/home/pi/emgucv/Emgu.CV/PInvoke/Unity/TextureConvert.cs(42,21): error CS0246: The type or namespace name `Texture2D' could not be found. Are you missing an assembly reference?
Compilation failed: 3 error(s), 0 warnings
make[2]: *** [Emgu.CV] Error 1
make[1]: *** [Emgu.CV/CMakeFiles/Emgu.CV.dir/all] Error 2
make: *** [all] Error 2

All this code looks Android related and I hope I won't need TextConvert.cs because I hacked the methods to replace their defintions with throw new NotImplementedException(). That let me remove the using statements which were causing these problems.

Almost at the finish line, I had some errors compiling the examples. I had these errors on my Windows build too and since they are only examples, out comes the knife:

cd Emgu.CV.Example
rm -r SURFFeature
rm -r LatentSvmDetector
rm -r TrafficSignRecognition

Finally, you should have successfully compiled the EmguCV C# libraries on your raspberry pi!

Plug a USB web cam in, cd into the bin folder and in an X Window session, execute:

mono Example.CameraCapture.monoexe

emgucv-usb

Woohoo! Except this screenshot hides the inconvenient truth that rather than measuring the camera speed in frames per second, you need to measure in seconds per frame while the CPU churns at 100%. Of course, running X-Windows via VNC doesn't help but essentially, the pi SoC is not powerful enough to do OpenCV work with a USB camera.

Hang on you say, the raspberry pi camera module uses the GPU to take full HD 1080p photo and video and can be controlled programmatically! The catch being that because this is a custom board for the pi, OpenCV and hence EmguCV can't see this non usb camera.

The next post takes care of this problem.