OpenCV uses floating point operations a lot, but not all of the ARM processors have FP coprocessor, so developers should use either some FP library, or as in my case – use Linux kernel FP emulation. There are two types of such emulation OABI and EABI. More details can be found here and here. Kernel release 2.6.16 was the first one to include ARM EABI support.
Unfortunately, CPUs of both SBCs do not support floating point in hardware, but luckily enough, TS-7800 has Debian Linux with 2.6.21 kernel. So I had a chance to compare OpenCV performance for OABI and EABI.
Both SBCs have necessary tool-chains in package – TS-7800 has Linux and Windows(Cygwin) tool-chains, SBC-2440 – only Linux one. In addition to these I downloaded newer release of Codesourcery ARM tool-chain for Windows, because the one from TS-7800 SW package didn’t work properly with Cygwin.
I wrote a pretty simple script to ease OpenCV (version 1.1pre1 from here) configuration for various toolchains. Here it is:
#!/bin/bash ##======== TS-7800 environment settings====== #### Linux host. EABI complier #export DEVROOT=/opt/crosstool/arm-none-linux-gnueabi #export APP_PREFIX=arm-none-linux-gnueabi #export GCC_HOST=i686-pc-linux-gnu ##-O3 kills gcc : cvpyrsegmentation.cpp:1021: internal compiler error: in verify_local_live_at_start, at flow.c:546 #export OFLAGS=-O2 ### Linux host. OABI compiler #export DEVROOT=/opt/crosstool/arm-linux/gcc-3.3.4-glibc-2.3.2 #export APP_PREFIX=arm-linux #export GCC_HOST=i686-pc-linux-gnu ##Any optimization causes SEGFAULTS during face detection application execution #export OFLAGS=-O0 ### Windows (Cygwin) host. EABI compiler (Codesourcery 2008q3-72) export APP_PREFIX=arm-none-linux-gnueabi export DEVROOT=/opt/crosstool/codesourcery export CYGPATH=d:/cygwin/bin/cygpath export GCC_HOST=i686-pc-cygwin ###Windows (Cygwin) host. OABI compiler #export APP_PREFIX=arm-unknown-linux-gnu #export DEVROOT=/opt/crosstool/gcc-3.3.4-glibc-2.3.2 #export CYGPATH=d:/cygwin/bin/cygpath #export GCC_HOST=i686-pc-cygwin ##Any optimization causes SEGFAULTS during face detection application execution #export OFLAGS=-O0 ##======== SBC2440-III environment settings====== ####Linux host only. OABI compiler only. (Out of the box kernel does not support EABI) #export DEVROOT=/usr/local/arm/3.4.1 #export APP_PREFIX=arm-linux #export GCC_HOST=i686-pc-linux-gnu ##Any optimization causes SEGFAULTS during face detection application execution #export OFLAGS=-O0 ##=============================================== export PATH=$DEVROOT/$APP_PREFIX/bin:$PATH ./configure \ --target=$APP_PREFIX \ --host==$APP_PREFIX \ --build=$GCC_HOST \ --disable-shared \ --enable-static \ --without-imageio --without-carbon \ --without-quicktime --without-python \ --without-gtk --without-swig \ --without-v4l \ --disable-apps \ --prefix=$DEVROOT/$APP_PREFIX \ CC=$DEVROOT/bin/$APP_PREFIX-gcc \ CXXFLAGS="-fsigned-char $OFLAGS -pipe" \ LD=$DEVROOT/bin/$APP_PREFIX-ld \ CPP=$DEVROOT/bin/$APP_PREFIX-cpp \ CXXCPP=$DEVROOT/bin/$APP_PREFIX-cpp \ CXX=$DEVROOT/bin/$APP_PREFIX-g++ \ AR=$DEVROOT/bin/$APP_PREFIX-ar \ RANLIB=$DEVROOT/bin/$APP_PREFIX-ranlib \ NM=$DEVROOT/bin/$APP_PREFIX-nm \ STRIP=$DEVROOT/bin/$APP_PREFIX-strip \ AS=$DEVROOT/bin/$APP_PREFIX-as
Just uncomment setting you need, and comment all the others and you’re all set.
CXXFLAGS is a must. OpenCV will (somehow) work even without this flag, but some functionality will be broken – JPEG parser for example (to say the truth, it will still be broken event with
-fsigned-char, but at least it will correctly parse JPEG headers).
After script finished run
make and then
make install . Libraries and headers will be placed in directory, specified with
Now when OpenCV is built and ready it’s time to “feel the power in your ARMs”.
I used facedetect sample application (/samples/c/) to test OpenCV on SBCs. I had to remove UILib -related code and add ome more parameter to application, named
--extension, which allows specifying of input file type (BMP, YML, JPG). Changes I made to file can be observed here
The makefile I sued to build the application is written in a way similar to the previous configure script:
# TS-7800 environment settings #DEVROOT=/opt/crosstool/arm-none-linux-gnueabi #APP_PREFIX=arm-none-linux-gnueabi #SBC2440-III environment settings #DEVROOT=/usr/local/arm/3.4.1 #APP_PREFIX=arm-linux #CodeSourcery setup DEVROOT=/opt/crosstool/codesourcery APP_PREFIX=arm-none-linux-gnueabi CC = $(DEVROOT)/bin/$(APP_PREFIX)-g++ CPP = $(DEVROOT)/bin/$(APP_PREFIX)-cpp LD=$(DEVROOT)/bin/$(APP_PREFIX)-ld CXXFLAGS = -I"$(DEVROOT)/$(APP_PREFIX)/include" -I"$(DEVROOT)/$(APP_PREFIX)/include/opencv" CXXFLAGS+= -fsigned-char LDFLAGS = -static -L"$(DEVROOT)/$(APP_PREFIX)/lib" -lcv -lhighgui -lcxcore -lml -lcvaux -lpthread -ldl all: facedetect.o $(CC) facedetect.o $(LDFLAGS) -o facedetect facedetect.o: $(CC) $(CXXFLAGS) -c facedetect.c clean: rm -f facedetect facedetect.o
Copy and paste this text to a file, say makefile_facedetect, and then use it:
make -f makefile_facedetect. It will build statically linked executable – I didn’t want to bother with shared OpenCV libraries.
The file used to detect face was lena.jpg (512×512) from OpenCV samples/c/ directory. I also converted it to BMP and YML, since JPEG parser does not work properly on ARM.
EABI build: detection time = 31 512.1ms
OABI build: detection time = 448 151 ms
1) EABI is MUCH better than OABI
2) Even with EABI FP support, there is still much needed to be improved in OpenCV to make it usable on ARM processors.