{"id":11,"date":"2009-03-31T18:07:48","date_gmt":"2009-03-31T08:07:48","guid":{"rendered":"http:\/\/computer-vision-software.com\/blog\/?p=11"},"modified":"2009-11-30T12:54:17","modified_gmt":"2009-11-30T02:54:17","slug":"compiling-opencv-for-arm9-platform-pico","status":"publish","type":"post","link":"http:\/\/www.computer-vision-software.com\/blog\/2009\/03\/compiling-opencv-for-arm9-platform-pico\/","title":{"rendered":"Compiling OpenCV for ARM9 platform"},"content":{"rendered":"<p>Compiling OpenCV<\/p>\n<ul>\n<li>Build platform: Windows XP SP3<\/li>\n<li>Target platform: ARM9\u00a0fixed point<\/li>\n<\/ul>\n<p>Contents<\/p>\n<ul>\n<li>Download and prepare OpenCV library source code<\/li>\n<li>Download and prepare compiler<\/li>\n<li>Create\/Modify Makefile<\/li>\n<li>Compile and link<\/li>\n<li>Run and Test<\/li>\n<li>Performance<\/li>\n<li>Profiling<\/li>\n<\/ul>\n<p>\u00a0<!--more--><\/p>\n<h1>Download and prepare OpenCV library source code<\/h1>\n<ul>\n<li>1. Download the latest version of OpenCV (<a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/sourceforge.net\/project\/showfiles.php?group_id=22870');\"  href=\"http:\/\/sourceforge.net\/project\/showfiles.php?group_id=22870\">http:\/\/sourceforge.net\/project\/showfiles.php?group_id=22870<\/a>). As build platform is Windows, select Windows version (opencv-win).<\/li>\n<li>2. Install OpenCV (e.g. C:\\Program Files\\OpenCV).<\/li>\n<li>3. Copy the complete installation directory into work location (e.g. D:\\BH\\OpenCV)<\/li>\n<li>4. Based on an OpenCV sample (e.g. D:\\BH\\OpenCV\\samples\\c\\facedetect.c) create a test application which will run on the Target hardware. Save it in its own directory (e.g. D:\\BH\\OpenCV\\fd\\src\\facedetect.cpp)<\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<h1>Download and prepare cross-compiler<\/h1>\n<ul>\n<li>1. Download the latest version of Sourcery G++ GNU Toolchain for ARM Linux (<a onclick=\"javascript:pageTracker._trackPageview('\/outgoing\/www.codesourcery.com\/sgpp\/lite\/arm\/portal\/subscription3057');\"  href=\"http:\/\/www.codesourcery.com\/sgpp\/lite\/arm\/portal\/subscription3057\">http:\/\/www.codesourcery.com\/sgpp\/lite\/arm\/portal\/subscription3057<\/a>).<\/li>\n<li>2. Install it (e.g. D:\\gcc)<\/li>\n<li>3. Copy short name executables (gcc.exe, g++.exe, ld.exe, ar.exe, etc.) from D:\\gcc\\arm-none-linux-gnueabi\\bin\\ to D:\\gcc\\bin\\<\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<h1>Create\/Modify Makefiles.<\/h1>\n<p>\u00a0All paths in all makefiles should be relative to the make directory (D:\\BH\\OpenCV\\_make)<\/p>\n<ul>\n<li>1. Use makefile_all_gnu.mak as a basis for the main Makefile. Save is as &#8220;Makefile&#8221;.<\/li>\n<li>1.1. Comment libraries\/binaries you are not going to compile\/use (like cxcoretest, cvtest, etc.)<\/li>\n<li>1.2. Rework &#8220;clean&#8221; target &#8211; remove lines containing *.dll and replace all *.lib with lib*.a; Remove or comment all lines with *.exe and add ..\\bin\\fd (the name and path of our test application)<\/li>\n<li>1.3. Add lines to build application. E.g. @-mkdir ..\\_temp\\fd$(DR) and @$(MAKE) $(OPT) &#8211;directory=..\/_temp\/fd$(DR) &#8211;makefile=..\/..\/fd\/src\/makefile.gnu<\/li>\n<li>2. Use make_module_gnu.mak as a basis for the module makefile.<\/li>\n<li>2.1. You may need to update CXXFLAGS_DBG variable to include necessary flags, like -D&#8221;NDEBUG&#8221; -O3 -ffast-math -pg -g -fno-bounds-check -c. The &#8220;-c&#8221; option says compiler to just compile the code (to not link)<\/li>\n<li>2.2. All libraries&#8217; makefiles specify BINTYPE=DLL, so update OUTBIN and OUTLIB paths accordingly. For DLL, OUTLIB should generate a library name like ..\/..\/lib\/lib$(TARGET)$(DBG).a. OUTBIN should be OUTBIN := ..\/..\/bin\/$(TARGET)$(DBG)<\/li>\n<li>2.3. CXX variable should be &#8220;arm-none-linux-gnueabi-g++.exe&#8221; or just g++.<\/li>\n<li>2.4. LINKFLAGS variable should include -Wl,-L..\/..\/lib $(LINKFLAGS_DLL)<\/li>\n<li>2.5. LIBS variable should include all necessary libraries and should look like &#8220;-Wl,-lpthread,-ldl,-lstdc++,$(LIBS)&#8221;<\/li>\n<li>2.6. AR variable should be equal to &#8220;arm-none-linux-gnueabi-ar.exe&#8221; or just ar.<\/li>\n<li>2.7. LINK variable should be equal to $(CXX).<\/li>\n<li>2.8. OUBLIB target $(OUTLIB): $(OBJS) should include @-mkdir ..\\..\\lib and $(AR) $(ARFLAGS) $@ $^.<\/li>\n<li>2.9. OUTBIN target $(OUTBIN): $(OBJS) should include @-mkdir ..\\..\\bin and $(LINK) $(LINKFLAGS) $^ -g -o $@ $(LIBS).<\/li>\n<li>2.10. .o: target should contain command &#8220;$(CXX) $(CXXFLAGS) $&lt;&#8220;.<\/li>\n<li>3. Use a Makefile.gnu from tests\\cv\\src directory to create Makefile.gnu for fd application. Save it in the fd source code directory (D:\\BH\\OpenCV\\fd\\src\\)<\/li>\n<li>3.1. TARGET should be fd<\/li>\n<li>3.2. BINTYPE should be APP<\/li>\n<li>3.3. At a minimum, the cxcore and cv includes should be available, so CV_INC and CXCORE_INC variables should be defined (..\/..\/cxcore\/include and ..\/..\/cv\/include)<\/li>\n<li>3.4. CXXFLAGS should include -D&#8221;CVAPI_EXPORTS&#8221; and -I&#8221;$(CXCORE_INC)&#8221; -I&#8221;$(CV_INC)&#8221; and other include paths as necessary<\/li>\n<li>3.5. LIBS should include at least -lcxcore$(DBG),-lcv$(DBG) and other libraries as needed.<\/li>\n<li>3.6. After definitions of variables the make module makefile should be included (include ..\/..\/_make\/make_module_gnu.mak)<\/li>\n<\/ul>\n<h1>Compile and link<\/h1>\n<ul>\n<li>1. Run Makefile (created on previous section). To do this just type make<\/li>\n<li>1.1. Make will first compile all source files (-c compiler option does this) and create corresponding object files at corresponding folders (_temp\/cv_Rls, _temp\/cxcore_Rls, _temp\/fd_Rls, etc.)<\/li>\n<li>1.2. After compiling next library (like cxcore or cv, where the corresponding makefile contain BINTYPE := DLL) make will run &#8220;ar&#8221; command to create static library (libcv.a or libcxcore.a). Static library is just an archive of corresponding object (&#8220;*.o&#8221;) files. Object files in the static library are not linked, so they may contain errors which may show up later on the linking stage.<\/li>\n<li>1.3. When all libraries are created, the application is compiled and linked. Make sure you give the linker all libraries needed to link the application (command should include options like -Wl,-L..\/..\/lib,-lcxcore,-lcv). When you specify &#8220;-lcxcore&#8221; the linker will look for library named libcxcore.a<\/li>\n<li>1.4. If everything was right, the bin folder will contain built application fd.<\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<h1>Run and Test<\/h1>\n<ul>\n<li>1. The only way to run the application is to run it from MMC (Micro SD card). Copy fd to the mmc card then telnet to the device. Or, telnet to the phone and get binary application via ftp. It is recommended to create directory structure for the application like \/mmc\/mmca1\/OpenCV\/bin\/facedetect (\/mmc\/mmca1 is a path to the root of MMC card)<\/li>\n<li>2. cd to \/mmc\/mmca1\/OpenCV\/bin\/facedetect and run the application by typing &#8220;.\/fd&#8221;.<\/li>\n<li>2.1. If everything is correct, the application will display error message about missing cascade classifiers and exit. In this case put xml classifiers from OpenCV installation into the phone (..\/..\/data\/haarcascades\/) and re-run the application.<\/li>\n<li>2.2. You may get the &#8220;Segmentation Fault&#8221; error. Typically, this error is occurred when the application is linked with (or to use) incorrect libraries or incorrect libraries versions (usually dynamically linked).<\/li>\n<li>2.3. You may get the following error: &#8220;fd: \/lib\/libpthread.so.0: version &#8216;GLIBC_2.4&#8217; not found (required by fd)&#8221;. It means that the application was linked with the pthread library that is not compatible with the one in the phone Linux installation. To fix this you need to replace corresponding libraries with the ones compatible with the phone. In my case, I had to replace pthread and stdc++ libraries, which caused multiple linker errors and necessity for replacing more libraries. The complete list of libraries I replaced is listed below:<\/li>\n<li>added gcc\\arm-none-linux-gnueabi\\libc\\lib\\ld-2.3.3.so<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\lib\\ld-2.8.so<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\lib\\libc-2.8.so<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\lib\\libc.so.6<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\lib\\libpthread-2.8.so<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\lib\\libpthread.so.0<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\crt1.o<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\crti.o<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\crtn.o<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libc.a<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libc.so<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libc_nonshared.a<\/li>\n<li>added gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libc_p.a<\/li>\n<li>added gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libc_pic.a<\/li>\n<li>added gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libc_pic.map<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libstdc++.a<\/li>\n<li>added gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libstdc++.la<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libstdc++.so<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libstdc++.so.6<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libstdc++.so.6.0.10<\/li>\n<li>added gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\libstdc++.so.6.0.3<\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<h1>Performance<\/h1>\n<ul>\n<li>1. Only face detection time is displayed. In reality, application takes more time needed to load classifiers, load input file and save resulted output file. All these times are not counted.<\/li>\n<li>1.1. It took on average about 6.4 seconds to process file sqa.jpg with resolution of 314&#215;209 pixels.<\/li>\n<li>1.2. It took on average about 41 seconds to process file pic.jpg with resolution of 640&#215;476 pixels.<\/li>\n<li>2. The application under performance test was compiled with maximum optimization level (-O3) and with the following options (-ffast-math -fno-bounds-check)<\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<h1>Profiling<\/h1>\n<ul>\n<li>1. To build application with enabled profiling give the &#8220;-pg&#8221; option to the compiler <em>and<\/em> linker, and re-build the whole project.<\/li>\n<li>2. To make it compile, I had to replace the following libraries with ones compatible with the phone.<\/li>\n<li>replaced gcc\\arm-none-linux-gnueabi\\libc\\usr\\lib\\gcrt1.o<\/li>\n<li>3. Run application with profiling support on the phone. After completion, the gmon.out file should be created. Copy this file from the phone to the PC.<\/li>\n<li>4. Run the gprof.exe with binary (fd) and gmon output (gmon.out) as command line arguments. Redirect standard output to a text file. This file will contain resulted profiling data, including timing (which function took how much time) and call graph.<\/li>\n<li>5. In my case, the result was not quite correct &#8211; it shown total execution time of about 14 seconds while real execution time was over 45 seconds (about 41 seconds on face detection and other time on loading haar cascades, loading input file and saving output file).<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Compiling OpenCV Build platform: Windows XP SP3 Target platform: ARM9\u00a0fixed point Contents Download and prepare OpenCV library source code Download and prepare compiler Create\/Modify Makefile Compile and link Run and Test Performance Profiling \u00a0<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[84],"tags":[7,6],"class_list":["post-11","post","type-post","status-publish","format-standard","hentry","category-opencv","tag-arm","tag-opencv"],"_links":{"self":[{"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/posts\/11","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/comments?post=11"}],"version-history":[{"count":0,"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/posts\/11\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/media?parent=11"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/categories?post=11"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.computer-vision-software.com\/blog\/wp-json\/wp\/v2\/tags?post=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}