- 1:尝试接入Opencv Android SDK
- 2:寻找问题
- 3:解决方法
为了在AOSP的Hal层相机添加图片处理的一些功能。我尝试接入OpenCV 4.5.1来实现该功能,本文将介绍接入过程中所遇到的坑和对应的解决方法。
尝试接入Opencv Android SDK
首先,我尝试接入4.5.1版本的Android SDK版本,需要将SDK包下的arm32位动态库和arm64位动态库添加到AOSP的模块中。首先在vendor目录下对应厂商的目录下创建libs目录,并在libs目录下定义libopencv_java4模块,具体目录结构如下:
- vendor
- mediatek (联发科)
- libs
- libopencv_java4
- Android.mk
- arm32
- libopencv_java4.so
- arm64
- libopencv_java4.so
Android.mk的定义如下:
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE = libopencv_java4.so
LOCAL_MODULE_CLASS = SHARED_LIBRARIES
LOCAL_MODULE_OWNER = mtk
LOCAL_MODULE_SUFFIX = .so
LOCAL_MODULE_TAGS = optional
LOCAL_MULTILIB = 64
LOCAL_SRC_FILES_64 = arm64/$(LOCAL_MODULE).so
LOCAL_MODULE_PATH_64 = $(TARGET_OUT_VENDOR)/lib64
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE = libopencv_java4.so
LOCAL_MODULE_CLASS = SHARED_LIBRARIES
LOCAL_MODULE_OWNER = mtk
LOCAL_MODULE_SUFFIX = .so
LOCAL_MODULE_TAGS = optional
LOCAL_MULTILIB = 32
LOCAL_SRC_FILES_32 = arm32/$(LOCAL_MODULE).so
LOCAL_MODULE_PATH_32 = $(TARGET_OUT_VENDOR)/lib
include $(BUILD_PREBUILT)
然后在对应厂商的device.mk下添加如下代码来将该模块包含到产品里:
#在打包vendor.img前将32位动态库和64位动态库拷贝到 vendor/lib目录和vendor/lib64目录下
PRODUCT_COPY_FILES += vendor/mediatek/libs/libopencv_java4/arm32/libopencv_java4.so:$(TARGET_COPY_OUT_VENDOR)/lib/libopencv_java4.so:mtk
PRODUCT_COPY_FILES += vendor/mediatek/libs/libopencv_java4/arm64/libopencv_java4.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libopencv_java4.so:mtk
#把该模块添加到产品中
PRODUCT_PACKAGES += libopencv_java4
在需要使用的模块下,导入opencv的头文件和libopencv_java4动态库模块,然后在cpp文件中使用opencv的库函数:
#将头文件放入include文件夹下
LOCAL_C_INCLUDES += include
#添加动态库依赖
LOCAL_SHARED_LIBRARIES += libopencv_java4
当以为一切完美无缺并在mm编译该模块时,出现了如下错误信息:
undefined reference to 'cv::imwrite(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cv::_InputArray const&, std::__1::vector<int, std::__1::allocator<int> > const&)'
寻找问题
在上面提到的编译问题中,可以看到在链接opencv的动态库时不能在动态库中寻找到指定的函数。可以知道,AOSP在编译时是用的是libc++的标准库,而libc++的标志库字符串的命名空间是std::__1::basic_string开头的,当用nm命令查看opencv库中记录的符号名称却如下:
nm -D libopencv_java4.so | c++filt | grep imwrite
00000000001f108c T Java_org_opencv_imgcodecs_Imgcodecs_imwrite_10
00000000001f12c0 T Java_org_opencv_imgcodecs_Imgcodecs_imwrite_11
00000000001f14ec T Java_org_opencv_imgcodecs_Imgcodecs_imwritemulti_10
00000000001f17bc T Java_org_opencv_imgcodecs_Imgcodecs_imwritemulti_11
000000000080429c T cv::imwrite(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, cv::_InputArray const&, std::__ndk1::vector<int, std::__ndk1::allocator<int> > const&)
可以看到,opencv的动态库的符号却是std::__ndk1::basic_string开头,因为符号不一致,这肯定链接不上。既然opencv和AOSP模块都是用的libc++去编译的,为什么两者都不一致呢。
将google官网下载的ndk解压后(在AOSP的prebuilts/ndk中也可以找到),在r13/sources/cxx-stl/llvm-libc++/include/__config下可以找到如下代码:
#define _LIBCPP_ABI_VERSION 1
...
#define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__ndk,_LIBCPP_ABI_VERSION)
标准的llvm-libc++ 的__config定义如下:
#define _LIBCPP_ABI_VERSION 1
...
#define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION)
从上面的对比,可以看出,谷歌在ndk中集成libc++时对其部分代码进行了修改。而opencv交叉编译出的so库是用的ndk中的libc++,所以其命名空间是std::__ndk1::basic_string。
解决方法
既然找出了问题,就需要找出解决办法,我们可以在opencv 的release页面下下载对应版本的源码,然后编写Android.mk放到AOSP中和用到的模块一起进行编译。不了解opencv的源码?谷歌官方已经集成了opencv 3.00的版本,你只需要将其目录下的Android.mk中每个模块的LOCAL_NDK_STL_VARIANT和LOCAL_SDK_VERSION注释掉(因为是c++编写,所以也需要把libopencv_java模块去掉),然后mm就可以用标准的llvm-libc++编译出动态库。然后将各个模块添加到device.mk中,然后在使用的模块中引入该模块就行了。
Hi 你编译有遇到这样的问题吗?
error: vendor/nxp-opensource/imx/camera/Android.bp:107:1: dependency "libopencv_core" of "libimxcamerahwl_impl" missing variant:
os:android, image:vendor.30, arch:arm64_armv8-a_cortex-a53, sdk:, link:shared, version:
available variants:
你需要添加opencv的动态库到你用到的模块中
嗯嗯 这个我加上了。
但是还有另一个问题哎, 我的头文件应该怎么include呀?
应该说是 我的头文件应该指向什么位置的文件呢? 是inlcude opencv 的source code里面的文件路径吗
你可以下载对应版本的opencv的android sdk,里面有所有的头文件。https://github.com/opencv/opencv/releases,sdk/native/jni/include下面的所有的头文件拷贝包含到你的模块中去就行了
当然你也可以从他源码里面去一个一个找,比较麻烦
嗯嗯,我是这么做的 直接拷贝的prebuilt sdk的include
不过我编译的android.bp对每个lib都加了
cppflags: ["-fexceptions"],
不知道为啥在编译调用opencv lib的地方编译的时候还是有下面的报错哎
opencv/include/opencv2/flann/hierarchical_clustering_index.h:385:13: error: cannot use 'throw' with exceptions disabled
FLANN_THROW(cv::Error::StsError, "Unknown algorithm for choosing initial centers.");
^
opencv/include/opencv2/flann/general.h:53:32: note: expanded from macro 'FLANN_THROW'
#define FLANN_THROW(TYPE, STR) throw FLANNException(STR)
我是直接用的google aosp里面的3.0.0,把它克隆到external里面的,然后如果想用ndk里面的libc++编译可以不做任何修改,如果想用默认的libc++去编译需要将它目录下的Android.mk中每个模块的LOCAL_NDK_STL_VARIANT和LOCAL_SDK_VERSION注释掉,然后你可以进它的目录mm,可以在out目录下面的产品的system目录下面的lib和lib64目录找到生成的18个动态库,你把这些定义成预编译库(如果不是给java用就不要libopencv_java),在你用到的地方导入这些动态库和头文件,你用到的地方可能要加一些cppflag
https://developer.android.com/ndk/guides/cpp-support Android.mk下添加c++的异常处理支持:
LOCAL_CPPFLAGS += -fexceptions -frtti
你用到opencv的模块中也要加
嗯, 谢谢! 加上之后我编译能过了。
不过跑不起来。。(sad)
我感觉还是因为rtti 的关系, 导致找不到vtab
不知道老哥你那边都没这样的问题的吗?
而且我试了下aosp opencv3 编不出来的额, 我的android版本是android11
我编译出来的arm32和64位的动态库,你试试,里面的Android.mk可能要改改。链接: https://pan.baidu.com/s/11ecgINPIPDDgMmPKluJPlQ 密码: 0roh
--来自百度网盘超级会员V2的分享
大佬,opencv编写好的Android.mk能不能共享下,谢谢
大佬,麻烦了,请求指导一下
大佬真的请求了,我必定重谢
按照你的这个提示操作,方便贴一下的 android.mk 文件吗?
我是直接用的google aosp里面的3.0.0,把它克隆到external里面的,然后如果想用ndk里面的libc++编译可以不做任何修改,如果想用默认的libc++去编译需要将它目录下的Android.mk中每个模块的LOCAL_NDK_STL_VARIANT和LOCAL_SDK_VERSION注释掉,然后你可以进它的目录mm,可以在out目录下面的产品的system目录下面的lib和lib64目录找到生成的18个动态库,你把这些定义成预编译库(如果不是给java用就不要libopencv_java),在你用到的地方导入这些动态库和头文件,你用到的地方可能要加一些cppflag
已经搞定了,多谢大神
LOCAL_PATH := $(call my-dir)
FLOW := $(LOCAL_PATH)
############# compile opencv3.0.0 libs/*so ############
include $(LOCAL_PATH)/libs/Android.mk
############# compile opticalflow.so ############
LOCAL_PATH :=$(FLOW)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_optical_flow
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/bin
LOCAL_SRC_FILES := \
optical_flow.cpp
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include/
LOCAL_SHARED_LIBRARIES := \
libopencv_calib3d \
libopencv_core \
libopencv_features2d \
libopencv_flann \
libopencv_highgui \
libopencv_imgcodecs \
libopencv_imgproc \
libopencv_ml \
libopencv_objdetect \
libopencv_photo \
libopencv_rsobjdetect \
libopencv_shape \
libopencv_stitching \
libopencv_superres \
libopencv_video \
libopencv_videoio \
libopencv_videostab
include $(BUILD_SHARED_LIBRARY)
你好,我也一样,麻烦指导一下
请问博主的 AOSP 版本是多少呢
萌萌哒的大佬,“Hal层相机添加图片处理的一些功能”可否分享下处理流程。
谷歌官方已经集成了opencv 3.00的版本。
// 大佬,谷歌官方这个Android.mk无法编译通过,可否分享下Android.mk,谢谢。