2019-10-21
AS和cmake笔记
android的cpu架构
- android查看cpu架构(
termux)
cat /proc/cpuinfo |
cmake在AS中的使用
不要把mk和cmake两种方法混淆
输出控制(message)
(TODO)如果想直接看到打印信息,使用
WARNING以上的级别进行打印
message(WARNING "fuck")- 在
Build->Build Output->CMake warnings查看 - 在
Build->Build Output->Toggle View查看
- 在
Android
- 版本信息
Android Studio版本为3.5Build-Tools版本为28.0.3
- 需要使用
SDK Manager安装- ndk
- cmake
只使用java模块
3.x-3.4.7-3.x版本
File->New->Import Module->选择opencv文件夹下的sdk/java文件夹,此时Android Studio会自动加载Module name- 将
opencv模块的AndroidManifest.xml中<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" />删除 File->Project Structure->Dependencies->选择app->添加Module Dependency->选择opencv- 将opencv文件夹下的
sdk/native/libs下自己手机cpu对应的架构文件夹复制到app/libs下 - 将opencv模块的
build.gradle的complieSdkVersion,buildToolVersion,minSdkVersion,targetSdkVersion改成和app的build.gradle一样 - 在
app的build.gradle的android节点下添加然后点击sourceSets {
main {
jni.srcDirs = []
jniLibs.srcDirs = ['libs']
}
}sync now - 在使用opencv前进行初始化
static {
if (!OpenCVLoader.initDebug()) {
...
}
}
常见错误
Caused by: CvException [org.opencv.core.CvException: OpenCV(4.1.1) /build/master_pack-android/opencv/modules/java/generator/src/cpp/utils.cpp:101: error: (-215:Assertion failed)
在Mat与Bitmap互转的时候长宽设置不对
只使用native模块
3.x-3.4.7-3.x版本
方法一
CMakeLists.txt编写- include头文件目录
- 加载libopencv动态库(
libopencv_world或libopencv_java3),命名为opencv_lib - 将
opencv_lib加载至目标文件
set(opencv_dir /home/lynx/fuck_mount/opencv/build_dir/4_1_0_shared/OpenCV-android-sdk) |
- 修改app的
build.gradle- 在
android节点下插入,否则会报错找不到libopencv_world.so或libopencv_java3.so
- 在
sourceSets { |
方法二
CMakeLists.txt- 设置OpenCV查找的目录
- 查找OpenCV
- include头文件目录
- 将OpenCV的库添加至目标文件
set(sdk_dir /home/lynx/fuck_mount/opencv/build_dir/4_1_0_shared) |
- 如果不设置
OpenCV_DIR将无法查找OpenCV包
- 修改app的
build.gradle
sourceSets { |
- 此外,务必将
minSdkVersion调至21以上,否则将会只有v8a架构才能成功编译 - 在app的
build.gradle中:minSdkVersion->ANDROID_PLATFORM - 在
ndk的android.toolchain.cmake中:ANDROID_PLATFORM->ANDROID_PLATFORM_LEVEL->ANDROID_NATIVE_API_LEVEL - 如果不设置
minSdkVersion,由于以上的确定关系,ANDROID_NATIVE_API_LEVEL会被设置为16,find_package会失败
4.x-4.1.0-4.x版本
方法一
同3.x版本的方法一
方法二
同3.x版本的方法二
常见问题
java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found(4.x版本)
(不确定的解决方法)在app的gradle中修改
externalNativeBuild { |
不要使用gnustl_shared或gnustl_static,已经过时
java.lang.UnsatisfiedLinkError: dlopen failed: library "libopencv_java3.so" not found(或libopencv_java4.so)
这是由于忘记了上面的第2步.Android Studio默认的jni路径为app/src/main/jniLibs,除了在CMakeLists.txt中导入opencv的库以外还需要二选一
- 将对应版本opencv的库(
libs/下一级的各个${ANDROID_ABI}文件夹)移动到jniLibs下 - 在
build.gradle中修改默认jni路径(见上面第2步)
- 各种
undefined reference to *(3.x版本)
如std::ios_base::Init::Init()等
TODO
- 各类
AndroidBitmap的问题(3.x版本)
undefined reference to `AndroidBitmap_getInfo' |
在CMakeLists.txt增加
target_link_libraries( |
参考:CSDN,这是一个很小的库,展示一个稳定的,基于C语言的接口,使本机代码安全地访问Java对象的像素缓冲区的位图
source code(使用完整代码)
3.x-3.x版本(未成功,需要eclipse)
4.x-4.1.0-4.x版本
环境变量
JAVA_HOMEexport JAVA_HOME=/home/lynx/fuck_mount/Android_Studio/jre # 使用Android Studio的JDK位置
ANDROID_SDK(非必须)export ANDROID_SDK=/home/lynx/fuck_mount/Android_SDK
ANDROID_NDK(非必须)export ANDROID_NDK=/home/lynx/fuck_mount/Android_SDK/ndk/{版本}
调整结构
- 修改toolchain:android ndk的
ndk/build/cmake/android.toolchain.cmake(约112行)elseif(ANDROID_TOOLCHAIN_NAME MATCHES "-[0-9].[0-9]$")
set(ANDROID_TOOLCHAIN clang) # 将gcc改成clang
endif() - android stl,在源代码的
/platforms/android/build_sdk.py(约113行)(非必须)self.cmake_vars = dict(
ANDROID_STL="c++_static", # change `gnustl_static` to `c++_static` or `c++_shared`
ANDROID_ABI=self.name,
ANDROID_PLATFORM_ID=platform_id,
) - 在
Android Studio的android sdk文件夹下,创建软连接ln -s build-tools/{版本} tools,否则无法编译安卓模块
- 修改toolchain:android ndk的
修改
cmake参数(2选1,推荐world)(修改根CMakeLists.txt)- java
OPENCV_ENABLE_NONFREE:改为ONBUILD_SHARED_LIBS:不动或者改为OFF,与生成java库冲突BUILD_ANDROID_PROJECTS:不动或者改为ONBUILD_FAT_JAVA_LIB:不动或者改为ON,保证生成libopencv_java4.soBUILD_JAVA:不动或者改为ON- 对
/samples/android/CMakeLists.txt中除了ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations)那一行,其他全部注释掉,否则android sdk会在编译sample时报错
- world
OPENCV_ENABLE_NONFREE:改为ONBUILD_SHARED_LIBS:改为ONBUILD_ANDROID_PROJECTS:不动或者改为ONBUILD_FAT_JAVA_LIB:改为OFF,生成libopencv_world.soBUILD_JAVA:不动或者改为ON- 对
/samples/android/CMakeLists.txt中除了ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations)那一行,其他全部注释掉,否则android sdk会在编译sample时报错
- java
执行
platforms/android/build_sdk.py,完成编译
./build_sdk.py --ndk_path {ndk路径} --sdk_path {android sdk路径} --extra_modules_path {path_to_contrib/modules} {目标位置} {opencv源码位置} |
如果没有设置则默认为环境变量
sdk-path:Android Studio的SDK目录ndk-path:Android Studio的SDK目录下ndk/{ndk版本号文件}
- 后续关于
CMakeLists.txt(android项目内的)和build.gradle的修改同native方法
常见错误
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.stitch-sPWgBONIqUrdX9XLB1OY6w==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.stitch-sPWgBONIqUrdX9XLB1OY6w==/lib/arm64, /data/app/com.example.stitch-sPWgBONIqUrdX9XLB1OY6w==/base.apk!/lib/arm64-v8a, /system/lib64, /product/lib64]]] couldn't find "libnative-lib.so"
缺少相应ABI的so库(目前计时在gradle里加入abiFilters也没有用),上述报错是因为没有编译全ABI.ABI配置:opencv-4.x/platforms/android/ndk-18-api-level-21.config.py
- 没装
cmake
Executing: ['ninja', '--version'] |
Android Studio需要在SDK Manager里面预先安装CMake,否则编译的时候会找不到ninja等程序
没有
libopencv_java4.soBUILD_FAT_JAVA_LIB和BUILD_ANDROID_PROJECTS要设置ON(或默认)- 记得修改android sdk tools文件结构
- 不能同时编译动态库
编译错误
Regex: 'command line option .* is valid for .* but not for C\+\+' |
TODO,可能是编译器的问题或cmake参数设置错误
- android project报错
A problem occurred configuring project ':face-detection'. |
把samples/android/CMakeLists.txt对应代码注释掉
- ndk报错
CMake Error at /home/lynx/fuck_mount/Android_SDK/ndk/20.1.5948944/build/cmake/android.toolchain.cmake:169 (message): |
需要将ndk的build/cmake/android.toolchain.cmake中set(ANDROID_TOOLCHAIN gcc)改为clang
- ninja报错
CMake Error: CMake was unable to find a build program corresponding to "Ninja". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool. |
将ndk的bin目录(包含ninja等程序)添加至$PATH
- ccache未安装(
3.x版本,TODO:不确定是否为必须)
用apt安装ccache即可
- ld报错(
3.x版本)
cannot open crtbegin_dynamic.o: 没有那个文件或目录 |
TODO修改gcc参数(但很大程度上是由于cmake参数配置错误)
- 添加
-nostdlib - 修改
--sysroot参数
- clang++报错
error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory |
使用apt安装libtinfo5
- 编译错误
error: use of undeclared identifier 'vcvt_f16_f32' |
多种可能
- 换
ndk opencv_contrib的路径设置错误
libopencv_java3.so没有生成(3.x版本)
TODO,很大程度上是由于cmake参数配置错误
- cmake报错
Android SDK: Can't build Android projects as requested by |
4.x:android sdk build tool版本过低3.x:需要sdk整合ant(ide为eclipse)
- java报错
opencv init failed |
检查gradle的lib路径是否正确加载
freetype/harfbuzz报错
卸载系统中的freetype和harfbuzz在opencv_contrib/modules/freetype/CMakeLists.txt中修改
if(PKG_CONFIG_FOUND) |
注释掉搜索freetype和harfbuzz的那两句
额外说明
4.x版本
- 不需要额外安装的软件:
jdk,ninja-build,ndk,直接使用android studio的即可 - 成功编译的版本:
ndk:20.1.5948944sdk tools:28.0.3cmake:3.13.4
- 失败的版本:
ndk:21.0.6113669(报错undefined referrence to '__write_chk')sdk tools:25.0.3(不能configure android project)
3.x版本 目前还没能成功编译android project
3.x成功编译的版本:- 无
- 失败的版本:
ndk:20.1.5948944(报错undefined referrence to '__vsnprintf_chk')
使用JavaCV
4.x版本
不同导入方法,
import的class位置可能不同
opencv部分功能的初始化
Loader.load(opencv_java.class);// 不能直接放在class开头 |
使用远程导入
app的build.gradle示例(最外节点)
ext { |
作为lib导入
根据手机具体的cpu架构进行导入
app的build.gradle
dependencies { |
将文件(视具体情况)
javacpp.jarjavacv.jaropenblas.jaropenblas-android-arm64.jaropencv.jaropencv-android-arm64.jar
复制到app/libs/文件夹里
常见错误
- cpu架构错误/缺少(需添加
-android-arm之类的库)
2019-10-27 16:01:32.439 29256-29322/? E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1 |
- 没有对
opencv初始化
2019-10-27 16:00:43.930 28933-28933/? E/AndroidRuntime: FATAL EXCEPTION: main |
- 缺少
openblas的相关jar库
2019-10-27 15:59:23.158 28618-28618/? E/AndroidRuntime: FATAL EXCEPTION: main |
混用java+native模块
4.x native(或source code)+3.x java
加载
native模块File->New->Import Module->选择opencv文件夹下的sdk/java文件夹,自己定义模块的名字修改模块的gradle文件(TODO)
// 将原来的application改成library |
- 修改app的gradle文件,加载两者的lib,缺一不可
sourceSets { |
- 修改app的gradle文件,添加java模块依赖
|
Linux
OpenCV source code 3.x(3.4.7)
gui安装
和4.x一样
常见错误
fatal error: Eigen/Core: 没有那个文件或目录``#include <Eigen/Core>修改
WITH_EIGEN=OFF(或)
- 先保证安装
eigen:sudo apt install libeigen3-dev - 添加
EIGEN_INCLUDE_PATH=/usr/include/eigen3(视具体情况)
- 先保证安装
ippicv_linux_20141027.tgz下载失败CMake Error at 3rdparty/ippicv/downloader.cmake:71 (file):
file DOWNLOAD HASH mismatch
for file: [/home/lynx/fuck_mount/opencv_3_0_0/opencv/3rdparty/ippicv/downloads/linux-8b449a536a2157bcad08a2b9f266828b/ippicv_linux_20141027.tgz]
expected hash: [8b449a536a2157bcad08a2b9f266828b]
actual hash: [5c4f36bf7b2421d52289f0297ba1406f]
status: [28;"Timeout was reached"]
TODO
ippicv_2019_lnx_intel64_general_20180723.tgz下载超时IPPICV: Download: ippicv_2019_lnx_intel64_general_20180723.tgz
CMake Warning at cmake/OpenCVDownload.cmake:193 (message):
IPPICV: Download failed: 28;"Timeout was reached"在
opencv/opencv_3rdparty的ippicv对应分支中下载对应的tgz将
tgz放入/home/lynx/Downloads/修改opencv的source code:
vi /3rdparty/ippicv/ippicv.cmake,将ippicv的https地址改为file:/home/lynx/Downloads/重新
cmake-gui
OpenCV source code 4.x(4.1.0)
依赖包
sudo apt install libgtk2.0-dev pkg-config # libgtk-3-dev |
一定要安装,否则会报错
- 缺少
gtk
terminate called after throwing an instance of 'cv::Exception' |
命令行安装(TODO)
cmake
cd {生成makefile的位置} |
make
cd {生成makefile的位置} |
make install
make install {安装的位置} |
gui安装
- 安装
cmake-gui
sudo apt install cmake-gui |
- 启动
cmake-gui
cd {build二进制文件的目录} |
Configure->Unix Makefiles:Use default native compilers->finish狂点
Configure直到没有红色区域赋值
| 变量名 | 赋值 |
|---|---|
BUILD_EXAMPLES |
|
CMAKE_BUILD_TYPE |
Release |
CMAKE_INSTALL_PREFIX |
{自己定的cmake_install路径} |
OPENCV_ENABLE_NONFREE |
勾选 |
OPENCV_EXTRA_MODULES_PATH |
{opencv-contrib source code}/modules |
OPENCV_GENERATE_PKGCONFIG |
勾选 |
狂点
ConfigureGenerate,等到Generating done在build路径
make
sudo make -j4 # 具体看有多少cpu |
配置
opencv4.pc(2选1)- 修改
PKG_CONFIG_PATH:增加{你cmake_install的路径}/lib/pkgconfig(opencv4.pc所在的路径) - (TODO,没试过)复制
opencv4.pc到/usr/lib/pkgconfig
- 修改
配置库路径,(新建)
/etc/ld.so.conf.d/opencv.conf
{你cmake_install路径}/lib/ # 自己的lib路径 |
sudo ldconfig |
- 编译测试
如果是
opencv.pc将opencv4改成opencv
pkg-config --modversion opencv4 |
常见问题
- 在其他项目中用
CMake导入OpenCV模块:之后find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})cmake出现By not providing "FindOpenCV.cmake" in CMAKE_MODULE_PATH ...:
这是由于没有设置环境变量OpenCV_DIR,设置为OpenCV编译后的目录下含有OpenCVConfig.cmake的对应路径
VIDIOC_REQBUFS: Inappropriate ioctl for device: 缺少ffmpeg
TODO: 需要在安装ffmpeg(以源代码的方式安装, 不要使用apt)之后重新编译OpenCV, ffmpeg安装