OpenCV于1999年由Intel 建立,全称:
Open Source Computer Vision Library。
OpenCV是一个
跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口。当前版本已经支持Android。
当前,Sam需要在Android上使用OpenCV。 虽然OpenCV已经有了Android版本。但因为当前代码基于OpenCV2.0. 此版本没有Android版本。所以,必须交叉编译此版本。
0. 下载相关版本OpenCV Source Code:
http://opencv.org/downloads.html
下载For Linux Version。得到:OpenCV-2.0.0.tar.bz2
1. 使用NDK编译之:
1.1:编译Linux X86版本:
首先,Sam想通过正常x86_Linux 编译,看看基本库都包括哪些,以及这些库是由哪些CPP文件组成的。有了以上信息,可以创建Android.mk。
$cd OpenCV-2.0.0
$./configure
$make
竟然出现错误:error: 'ptrdiff_t' does not name a type
于是在cxcore.h中添加一行:
#include < stddef.h >
又缺乏unlink.
还是添加头文件:#include
之后,又是HighGUI 缺乏cvCreateCameraCapture_V4L(int)
undefined reference to 'cvCreateCameraCapture_V4L(int)'
Sam查了Google, 看到最快的办法是修改define.即让代码不进去。感觉有点不对,但不管了。先这么来吧。反正HighGUI也不会真去用。
$gedit src/highgui/cvcap.cpp.
//#if defined(HAVE_CAMV4L) || defined(HAVE_CAMV4L2)
#if defined (HAVE_CAMV4L)
编译通过。(记得上次编译OpenCV2.0,没这么多问题啊,有点忘记了)
验证:Sam编译了一个OpenCV自带例子:samples/c/squares.c
$g++ squares.c -o squares -I../../include/opencv/ -L../../src/.libs/ -lhighgui -lcv -lcxcore
编译正常,说明编译出的库应该正常。
1.2:编译为Android NativeC版本库:
观察前面编译Linux-x86的过程,感觉需要编译的模块有:libcxcore.so, libcv.so等。至于highgui,它不是产品化的库,所以可以不用。
从名字上听,libcxcore.so应该是最基础的库。所以先编译之:
1.2.1:创建Android.mk
首先说到Application.mk, 这个Sam一直用通用的。所以不用修改。这里只生成Android.mk即可。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := cxcore
LOCAL_SRC_FILES := cxconvert.cpp \
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T
LOCAL_CXXFLAGS += -I../../../include/opencv/ -I../../../3rdparty/flann/ -I../../../3rdparty/include/
include $(BUILD_SHARED_LIBRARY)
此时,会有一个奇怪的错误出现:
home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxlapack.cpp: In function 'bool cv::jacobi(const cv::Mat&, cv::Mat&, cv::Mat&, bool, Real)':
/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxlapack.cpp:759:9: error: expected unqualified-id before numeric constant
/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxlapack.cpp:760:18: error: no matching function for call to 'cv::Mat::copyTo(int) const'
Sam将 _S 全部修改为 _S1即可。
Mat _S1(_S0.size(), _S0.type(), S);
/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxlapack.cpp:759:9: error: expected unqualified-id before numeric constant
/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxlapack.cpp:760:18: error: no matching function for call to 'cv::Mat::copyTo(int) const'
Sam将 _S 全部修改为 _S1即可。
Mat _S1(_S0.size(), _S0.type(), S);
还有几个地方有类似问题。按此方法修改之。
网络上有人说:
All uppercase names are often used for preprocessor macros, which
doesn't respect namespace scopes. Therefore such names should
generally be avoided for everything else.
doesn't respect namespace scopes. Therefore such names should
generally be avoided for everything else.
const:/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxflann.cpp:51: error: undefined reference to 'flann::Index::Index(flann::Matrixconst&, flann::IndexParams const&)'
编译flann:
进入OpenCV-2.0.0/3rdparty/flann
$mkdir jni
copy all cpp and .h file to jni
create Application.mk and android.mk
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := flann
LOCAL_SRC_FILES := constants.h\
flann.cpp\
flann.hpp\
dist.cpp\
index_testing.cpp\
logger.cpp\
random.cpp\
saving.cpp
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T
LOCAL_CXXFLAGS += -I../../include/flann/ -I../util/ -I../nn -I../algorithms
#include $(BUILD_EXECUTABLE)
include $(BUILD_SHARED_LIBRARY)
$mkdir jni
copy all cpp and .h file to jni
create Application.mk and android.mk
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := flann
LOCAL_SRC_FILES := constants.h\
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T
LOCAL_CXXFLAGS += -I../../include/flann/
#include $(BUILD_EXECUTABLE)
include $(BUILD_SHARED_LIBRARY)
编译libflann.so 成功。
再次编译cxcore,又报错:
/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxpersistence.cpp:257: error: undefined reference to 'gzclose'
/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxpersistence.cpp:233: error: undefined reference to 'gzputs'
查找之,发现是3rdparty/zlib没有编译。编译之。
再次编译cxcore,又报错:
/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxpersistence.cpp:257: error: undefined reference to 'gzclose'
/home/sam/work/current/AM/Thirdparty/OpenCV/OpenCV-2.0/Linux_Version/OpenCV-2.0.0/src/cxcore/jni/cxpersistence.cpp:233: error: undefined reference to 'gzputs'
查找之,发现是3rdparty/zlib没有编译。编译之。
同样,建立jni目录。创建Android.mk .这个编译很简单.
再后来,发现lapack又没有提供库。再编译之。
此时,将cxcore的Android.mk修改为如下方式,即将刚才编译的几个第三方库加入。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := cxcore
LOCAL_SRC_FILES := cxconvert.cpp \
cxflann.cpp\
cxpersistence.cpp\
cxcopy.cpp\
cximage.cpp\
cxprecomp.cpp\
cxlapack.cpp\
cxrand.cpp\
cxalloc.cpp\
cxdatastructs.cpp\
cxmathfuncs.cpp\
cxstat.cpp\
cxarithm.cpp\
cxdrawing.cpp\
cxmatmul.cpp\
cxsystem.cpp\
cxarray.cpp\
cxdxt.cpp\
cxmatrix.cpp\
cxtables.cpp
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T
LOCAL_CXXFLAGS += -I../../../include/opencv/ -I../../../3rdparty/flann/ -I../../../3rdparty/include/
LOCAL_LDLIBS := -L../../../3rdparty/flann/libs/armeabi-v7a/ -lflann -L../../../3rdparty/zlib/libs/armeabi-v7a/ -lzlib -L../../../3rdparty/lapack/libs/armeabi-v7a/ -llapack
include $(BUILD_SHARED_LIBRARY)
则cxcore编译成功。
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := cxcore
LOCAL_SRC_FILES := cxconvert.cpp \
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T
LOCAL_CXXFLAGS += -I../../../include/opencv/ -I../../../3rdparty/flann/ -I../../../3rdparty/include/
LOCAL_LDLIBS := -L../../../3rdparty/flann/libs/armeabi-v7a/ -lflann -L../../../3rdparty/zlib/libs/armeabi-v7a/ -lzlib -L../../../3rdparty/lapack/libs/armeabi-v7a/ -llapack
include $(BUILD_SHARED_LIBRARY)
则cxcore编译成功。
下面编译cv:
cv编译中,遇到的最多的问题是某变量以下划线开头,后面只有一个字母. 需要将其加长.修改后就可以编译了.
其Android.mk如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := cv
LOCAL_SRC_FILES := cvaccum.cpp cvcontourtree.cpp cvfundam.cpp cvmatchcontours.cpp cvprecomp.cpp cvstereogc.cpp\
cvapprox.cpp cvconvhull.cpp cvgeometry.cpp cvmodelest.cpp cvpyramids.cpp cvsubdivision2d.cpp\
cvcalccontrasthistogram.cpp cvcorner.cpp cvhaar.cpp cvmoments.cpp cvpyrsegmentation.cpp cvsumpixels.cpp\
cvcalcimagehomography.cpp cvcornersubpix.cpp cvhistogram.cpp cvmorph.cpp cvrotcalipers.cpp cvsurf.cpp\
cvcalibinit.cpp cvderiv.cpp cvhough.cpp cvmotempl.cpp cvsamplers.cpp cvtables.cpp\
cvcalibration.cpp cvdistransform.cpp cvimgwarp.cpp cvmser.cpp cvsegmentation.cpp cvtemplmatch.cpp\
cvcamshift.cpp cvdominants.cpp cvinpaint.cpp cvoptflowbm.cpp cvshapedescr.cpp cvthresh.cpp\
cvcanny.cpp cvemd.cpp cvkalman.cpp cvoptflowgf.cpp cvsmooth.cpp cvtriangulate.cpp\
cvcascadedetect.cpp cvfeatureselect.cpp cvkdtree.cpp cvoptflowhs.cpp cvsnakes.cpp cvundistort.cpp\
cvcolor.cpp cvfeaturetree.cpp cvlinefit.cpp cvoptflowlk.cpp cvspilltree.cpp cvutils.cpp\
cvcondens.cpp cvfilter.cpp cvlkpyramid.cpp cvpgh.cpp cvstardetector.cpp\
cvcontours.cpp cvfloodfill.cpp cvlsh.cpp cvposit.cpp cvstereobm.cpp\
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T
LOCAL_CXXFLAGS += -I../../../include/opencv/ -I../../../3rdparty/flann/ -I../../../3rdparty/include/
LOCAL_LDLIBS := -L../../cxcore/libs/armeabi-v7a/ -lcxcore -L../../../3rdparty/flann/libs/armeabi-v7a/ -lflann -L../../../3rdparty/zlib/libs/armeabi-v7a/ -lzlib -L../../../3rdparty/lapack/libs/armeabi-v7a/ -llapack
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := cv
LOCAL_SRC_FILES := cvaccum.cpp
cvapprox.cpp
cvcalccontrasthistogram.cpp
cvcalcimagehomography.cpp
cvcalibinit.cpp
cvcalibration.cpp
cvcamshift.cpp
cvcanny.cpp
cvcascadedetect.cpp
cvcolor.cpp
cvcondens.cpp
cvcontours.cpp
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T
LOCAL_CXXFLAGS += -I../../../include/opencv/ -I../../../3rdparty/flann/ -I../../../3rdparty/include/
LOCAL_LDLIBS := -L../../cxcore/libs/armeabi-v7a/ -lcxcore -L../../../3rdparty/flann/libs/armeabi-v7a/ -lflann -L../../../3rdparty/zlib/libs/armeabi-v7a/ -lzlib -L../../../3rdparty/lapack/libs/armeabi-v7a/ -llapack
include $(BUILD_SHARED_LIBRARY)
总结下来:
OpenCV的编译过程如下:
先编译3rdparty/flann, 3rdparty/lapack, 3rdparty/zlib.
之后编译cxcore.它依赖于以上几个库。
最后编译cv. 它依赖于cxcore.