Sunday, January 30, 2011

CrossCompiling OpenCV 2.1 for ARM-CPUs

It's unbelievable but is has been exactly one year since I wrote my last post on this blog. It has been a busy year and I have worked almost every day with the new C++-Interface of OpenCV. It has greatly improved with the last two versions 2.1 and 2.2 but there are still some issues need fixing. 

One thing I was particularly interested in last year was compiling OpenCV 2.1 for ARM-CPUs which will help you develop your applications for mobile devices without the need to compile it with the iOS-Toolchain or anything like that. When it comes to compiling OpenCV 2.1 with the CodeSourcery g++ compiler there are a few errors that need addressing first although many known bugs from the previous version are already fixed. Since we run our ARM (TI OMAP35x) without a unix-like os, the most of the problems are os-based. Beneath you'll find a list of all errors I encountered and also a hint for a quick fix. 

One of the biggest issues compiling OpenCV 2.1 for ARM is the “cxrand.cpp”-file which obviously implements a random number generator that uses threads. Because “pthreads” are a problem when you don't have a suitable OS that takes care of threads I had to remove the code in order to successfully compile the library. So if you want to have random numbers you may have to implement them for your own. Since I'm not entirely sure which OpenCV functions use this random number generator be careful!
Error:  
cxcore/cxrand.cpp:594: error: 'pthread_key_t' does not name a type
Solution:
Replace line 634-668 with:

RNG& theRNG()
{
   CV_Assert(FALSE); // runtime stop if this one is really used!
   RNG* rng = NULL;
   return *rng;
}
There is also a strange error that seems to come from the CodeSourceryG++ itself. When compiling 'cv/smooth.cpp' the compiler breaks with
Error:
cv/cvsmooth.cpp:1149: internal compiler error: Segmentation fault
Maybe a newer version of the compiler will help – but theres also a simple workaround: Just use the compilerflag “-verbose” and the file will be compiled successfully.
 Solution: 
use compiler flag '-verbose' for gcc/g++
There is also an error in the highgui part. Since it is not (easily) possible to exclude the hole highgui part from the compilation which would seem reasonable since most of it's functionality couldn't be used on the target we need to address the issue. The solution is quite simple. Just add '#include '

Error:

highgui/loadsave.cpp: In function 'void* cv::imdecode_(const cv::Mat&, int, int, cv::Mat*)':
highgui/loadsave.cpp:333: error: 'unlink' was not declared in this scope

Solution:

#include <unistd.h>

The next error isn't far away, this time it shows first when the linker is active. The problem is again the 'unistd.h' which is not included. But instead of simply including the header replace the following lines. Doing this means, that you need to define NO_OS before compiling!
Error: 
../../lib/libcvhaartraining.a(cvcommon.obj): In function `icvMkDir(char const*)':
cvcommon.cpp:(.text._Z8icvMkDirPKc+0x90): undefined reference to `mkdir'
Solution:
[...]
#else /* _WIN32 */
#ifdef NO_OS
    assert(FALSE);
#else
    if( stat( path, &st ) != 0 )
   {
       if( mkdir( path, mode ) != 0 ) return 0;
   }
#endif
#endif /* _WIN32 */

The next error occurs when compiling the 'traincascade/imagestorage.h' here it is also only a missing include file:
Error:
/apps/traincascade/features.h:4, from /apps/traincascade/cascadeclassifier.h:5, from /apps/traincascade/traincascade.cpp:2:
/apps/traincascade/imagestorage.h:27: error: ISO C++ forbids declaration of 'FILE' with no type
/apps/traincascade/imagestorage.h:27: error: expected ';' before '*' token
Solution:
#include <stdio.h>

This should help YOU to get OpenCV 2.1 up and running on your ARM-machine. Some of these bugs are already I the official cv bugtracker - I hope they are fixed by version 2.3, since most of them are still active in 2.2

The next time I'll write about UnitTesting with OpenCV datatypes using the great GTest (googletest) framework that comes with a BSD licence and can therefore be used commerically and free. GoogleTest provides some nice features to test your coding and brings built in capability for compilation on other target systems like the ARM-CPU. I hope It won't take another year to write this post... ;)