概述
sam_code@hotmail.com
自从2011年开始交叉编译OpenCV, 到今天陆陆续续编译了很多版本,
有尝试过编译Linux版本(http://blog.sina.com.cn/s/blog_602f87700102wuv7.html),交叉编译过ARM版本,在Android版本出现后,又编译过OpenCV4Android
(http://blog.sina.com.cn/s/blog_602f87700102wwvb.html) (http://blog.sina.com.cn/s/blog_602f87700102xdzq.html).
编译这么多次后,希望对自己的编译历程做个总结,所以借这次机会记录下来。
0. 交叉编译OpenCV的原因:
0.1:OpenCV2.0时代:
最初交叉编译OpenCV,是想在Android系统上使用它,而在OpenCV2.0时代,并不提供Android版本。所以下载了OpenCV2.0
Source For Linux. 对各个模块自己写Android.mk, Application.mk.
顺利的编译出对应版本。
cvaux,cv,cxcore,
ml, highgui等全部成功编译。且highgui底层支持V4L2, libv4l, ffmpeg等
(http://blog.sina.com.cn/s/blog_602f87700101de4o.html)
0.2: OpenCV3.1时代:
OpenCV3.1时代,已经开始提供OpenCV4Android,理论上,根本不需要再自行编译.
OpenCV的官方建议是: 直接使用OpenCV库。libopencv_java.so.
并提供了两套使用方法:
A. 利用OpenCV提供的全套Java接口, 在Android Java层使用。
B. 利用OpenCV提供的C/C++ 接口, 在JNI层使用。
但Sam当时需要比较特殊: 与官方提供过使用方法不同的是:需要在Android
NativeC控制台层面使用OpenCV。这本身没有问题,但会遇到Camera问题(注1)。
换句话说,就是要在Android NativeC 层, 把V4L2支持也打开。这就是每升级一次OpenCV,
Sam都需要重新编译的核心原因。
0.3: OpenCV3.4时代:
从OpenCV3.3. 它加入了DNN,需要用它,还想把OpenCL加入。又需要用到Camera,所以.....
1. OpenCV编译思路:
既然知道了特殊的OpenCV使用要求(在NativeC控制台程序中使用OpenCV, 同时提供Camera接口)。
那编译思路就很清晰了。
1.1:打开所有想要支持的模块和功能:
如:TBB, Eigen, OpenCL.
1.2: 打开V4L2支持。
此处要注意,使用官方方法打开V4L2支持,并不一定可以起效。因为在设置文件中,这个设置会被去掉。
1.3:堵住Native-JNI所用的Camera接口:
这个接口是给JNI-NativeC用的,与OpenCV-Manager关联。不是Sam所能使用的。所以需要把这条路堵住。
2. 编译方法研究总结:
回顾:
OpenCV2.0时代,当时编译工具还采用autoconf. 所以直接自己写Android.mk ,
Application.mk。
OpenCV2.4.20时代,编译工具切换到cmake. 所以编译方法有所变化。直到OpenCV3.4,
(OpenCV4.0还没看)。 一直可以延续这种编译方法。(中间也许添加了Python编译方法,后续再研究)。
首先看这种编译方法:
2.1: 几个关键文件:
A. CMakeLists.txt
在OpenCV Source Tree根目录。有CMakeLists.txt. 它是OpenCV CMake 的根
Makefile。
B: platforms/scripts 目录:
V2.4.20, V3.1.0 V3.3.0中,platforms/scripts目录中,有很多 sh 脚本。
这些脚本用来帮助开发人员编译不同平台,不同架构的OpenCV.
cmake_android_arm.sh : Android ARM平台版本。
cmake_android_mips.sh: Android MIPS平台版本
cmake_android_x86.sh: X86版本。
cmake_arm_gnueabi_hardfp.sh: ARM
hardfp版本。
其中,我们用到的就是cmake_android_arm.sh 。
这些脚本,其实是帮助开发人员编译的。
它的主要思想是:
#cd platforms
#sh
scripts/cmake_android_arm.sh
它就会在platforms下建立一个类似
build_android_arm的目录。并生成(新产生,而非copy)将要编译的源码和头文件以及Makefile。等待用户编译。
其中,不同平台,不同架构的的编译设置,
-DCMAKE_TOOLCHAIN_FILE=../android/android.toolchain.cmake:放在platforms/中不同目录内。
如:android, ios, linux,
osx等。
android-ARM的编译配置文件:就在android/android.toolchain.cmake 中 .
C: platforms/android
这个目录放置的是android-arm版本的编译设置选项。
其中,V3.4.1版本,在platforms/scripts中,已经没有cmake_android_arm.sh
了。
但在platforms/android/ 增加了build_sdk.py , ndk-xx.config.py等。
估计是为python编译准备的。
不过,既然platforms/android/android.toolchain.cmake 还在,那老版本应该还行的通。
3. 编译前的准备工作:
不同OpenCV版本的编译中,要求各个软件和库的版本也在不断升级中。所以就不提具体版本了。只说需要什么软件吧。
git
cmake
Android NDK
JDK
Android SDK
Apache Ant
Python.
环境变量设置:
export ANDROID_NDK=/opt/android-ndk-r10e
export ANDROID_SDK=/home/sam/Android/android-sdk-linux/
#export ANDROID_SDK=/home/sam/Android/Sdk/
export ANDROID_ABI=armeabi-v7a
export ANT_HOME=/usr/share/ant
export PATH=${PATH}:${ANT_HOME}/bin
Sam 把他们写到一个脚本中:
SET_ENV_32BIT
#source SET_ENV_32BIT
4. 实际编译:
4.1:设置环境变量:
#source SET_ENV_32BIT
4.2:
哪怕是V3.4.1, Sam也建议自己建立scripts/cmake_android_arm.sh.
这样在后续修改设置,如加入TBB,OpenCL等时,就直接添加在cmake_android_arm.sh 中了。
#cd platforms
#sh scripts/cmake_android_arm.sh
#cd build_android_arm
#make VERBOSE=1
5. 修改Android相关设置:
在OpenCV4Android编译List中,可以看到以下信息。这些信息都要设置正确。
-- Android:
-- Android ABI:
-- STL
type:
-- Native API level:
-- SDK
target:
-- Android NDK:
-- android tool:
这篇Blog 列出了如何设置以上参数:
http://blog.sina.com.cn/s/blog_602f87700102xdzq.html
5.1:关键文件---platforms/android/android.toolchain.cmake
这个关键文件有以下几个地方需要注意:
1. NDK版本:
它屡次明确说明: ANDROID_NDK= 应该设置为:R5-R10D
ANDROID_NDK=/opt/android-ndk-r10d
指定指令集:
ANDROID_ABI=armeabi-v7a
可选项有很多,armeabi,
armeabi-v7a, armeabi-v7a-hard
with NEON, armeabi-v7a
with NEON, x86, mips, arm64-v8a. 等等。
指定Native API
Level:
ANDROID_NATIVE_API_LEVEL=android-24
指定ToolChain:
ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9
支持以下设置(脚本对R10C
以后的NDK处理的不够好,会导致Clang找不到):
# *
aarch64-linux-android-4.9
# *
aarch64-linux-android-clang3.4
# *
aarch64-linux-android-clang3.5
# *
arm-linux-androideabi-4.6
# *
arm-linux-androideabi-4.8
# *
arm-linux-androideabi-4.9 (default)
# *
arm-linux-androideabi-clang3.4
# *
arm-linux-androideabi-clang3.5
# *
mips64el-linux-android-4.9
# *
mips64el-linux-android-clang3.4
# *
mips64el-linux-android-clang3.5
# *
mipsel-linux-android-4.6
# *
mipsel-linux-android-4.8
# *
mipsel-linux-android-4.9
# *
mipsel-linux-android-clang3.4
# *
mipsel-linux-android-clang3.5
# *
x86-4.6
# *
x86-4.8
# *
x86-4.9
# *
x86-clang3.4
# *
x86-clang3.5
# *
x86_64-4.9
# *
x86_64-clang3.4
# *
x86_64-clang3.5
指定C++库:
ANDROID_STL=gnustl_shared
# Possible
values are:
# none ->
Do not configure the runtime.
# system ->
Use the default minimal system C++ runtime library.
# Implies
-fno-rtti -fno-exceptions.
# Is
not available for standalone toolchain.
# system_re ->
Use the default minimal system C++ runtime library.
# Implies
-frtti -fexceptions.
# Is
not available for standalone toolchain.
# gabi++_static ->
Use the GAbi++ runtime as a static library.
# Implies
-frtti -fno-exceptions.
# Available
for NDK r7 and newer.
# Is
not available for standalone toolchain.
# gabi++_shared ->
Use the GAbi++ runtime as a shared library.
# Implies
-frtti -fno-exceptions.
# Available
for NDK r7 and newer.
# Is
not available for standalone toolchain.
# stlport_static
-> Use the STLport runtime as a static library.
# Implies
-fno-rtti -fno-exceptions for NDK before r7.
# Implies
-frtti -fno-exceptions for NDK r7 and newer.
# Is
not available for standalone toolchain.
# stlport_shared
-> Use the STLport runtime as a shared library.
# Implies
-fno-rtti -fno-exceptions for NDK before r7.
# Implies
-frtti -fno-exceptions for NDK r7 and newer.
# Is
not available for standalone toolchain.
# gnustl_static ->
Use the GNU STL as a static library.
# Implies
-frtti -fexceptions.
# gnustl_shared ->
Use the GNU STL as a shared library.
# Implies
-frtti -fno-exceptions.
# Available
for NDK r7b and newer.
# Silently
degrades to gnustl_static if not available.
6. 修改OpenCV设置:
6.1: Eigen支持添加:
A. 添加设置:
在scripts/cmake_android_arm.sh 中,添加:
-DHAVE_EIGEN=1
但此时可以看到:
-- Other third-party
libraries:
-- Eigen: YES (ver
..)
说明没找到Eigen的库和头文件。
查看CMakeLists.txt, 可以看到以下语句:
if(WITH_EIGEN OR HAVE_EIGEN)
status(" Eigen:" HAVE_EIGEN THEN "YES (ver
${EIGEN_WORLD_VERSION}.${EIGEN_MAJOR_VERSION}.${EIGEN_MINOR_VERSION})"
ELSE NO)
endif()
说明没有获取到以上信息。
查看CMakeList.txt:
OCV_OPTION(WITH_EIGEN "Include
Eigen2/Eigen3 support" (NOT
CV_DISABLE_OPTIMIZATION) IF (NOT WINRT AND NOT
CMAKE_CROSSCOMPILING) )
可以看到,如果是交叉编译,则WITH_EIGEN不被设置。
所以如果需要加入EIGEN支持,首先要交叉编译EIGEN, 再去掉这个语句。这个后面再尝试。
6.2: 添加TBB支持:
添加设置:
-DBUILD_TBB=ON -DWITH_TBB=ON
它会自动下载TBB。
如果顺利:
-- Parallel
framework: TBB (ver
2018.0 interface 10001)
6.3: 增加动态库:
-DBUILD_SHARED_LIBS=ON
顺利的话:
会显示:
-- C/C++:
-- Built as dynamic libs?: YES
6.4:增加V4L2支持:
-DWITH_V4L=1
会因为某些情况,导致这个设置无效:
例如:
OCV_OPTION(WITH_V4L "Include Video 4 Linux
support" ON IF (UNIX AND NOT ANDROID AND NOT APPLE) )
在Android平台下,会把WITH_V4L undef。
而一些ANDROID_NATIVE_API_LEVEL设置也会导致出问题。所以Sam直接强行修改了:
# --- V4L ---
ocv_clear_vars(HAVE_LIBV4L HAVE_CAMV4L HAVE_CAMV4L2
HAVE_VIDEOIO)
if(WITH_V4L)
if(WITH_LIBV4L)
CHECK_MODULE(libv4l1
HAVE_LIBV4L1 VIDEOIO)
CHECK_MODULE(libv4l2
HAVE_LIBV4L2 VIDEOIO)
if(HAVE_LIBV4L1 AND
HAVE_LIBV4L2)
set(HAVE_LIBV4L YES)
else()
set(HAVE_LIBV4L NO)
endif()
endif()
CHECK_INCLUDE_FILE(linux/videodev.h
HAVE_CAMV4L)
CHECK_INCLUDE_FILE(linux/videodev2.h
HAVE_CAMV4L2)
set(HAVE_CAMV4L2
ON)
message("SamInfo===================================================================:
HAVE_CAMV4L2 is:" ${HAVE_CAMV4L2})
CHECK_INCLUDE_FILE(sys/videoio.h
HAVE_VIDEOIO)
endif(WITH_V4L)
6.5: 支持NEON:
-DANDROID_ARM_NEON=TRUE
注1:
OpenCV中本机Camera支持:
Android Camera的原生接口与平台相关。
OpenCV将依赖于平台的代码隔离到单独的库中,并提供了几个预构建的库。如:
libnative_camera_r2.2.0.so libnative_camera_r4.0.3.so libnative_camera_r4.1.1.so等。
OpenCV的本机Camera在控制台应用程序中不起作用。
注2:
WITH_EIGEN, HAVE_EIGNE, WITH_TBB, HAVE_TBB关系。
最后
以上就是俭朴板栗为你收集整理的linux opencv 编译.a,OpenCV编译总结的全部内容,希望文章能够帮你解决linux opencv 编译.a,OpenCV编译总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复