LYNX

Links

Tags

Categories

openCV安装

AS和cmake笔记

android的cpu架构

  • android查看cpu架构(termux)
cat /proc/cpuinfo
  • AArch32ARMv7架构的一种执行状态
  • AArch64ARMv8架构的一种执行状态
  • 64位ARMv8包含上面两种状态

cmake在AS中的使用

不要把mkcmake两种方法混淆

输出控制(message)

(TODO)如果想直接看到打印信息,使用WARNING以上的级别进行打印

  • message(WARNING "fuck")
    • Build->Build Output->CMake warnings查看
    • Build->Build Output->Toggle View查看

Android

  • 版本信息
    • Android Studio版本为3.5
    • Build-Tools版本为28.0.3
  • 需要使用SDK Manager安装
    • ndk
    • cmake

只使用java模块

3.x-3.4.7-3.x版本

  1. File->New->Import Module->选择opencv文件夹下的sdk/java文件夹,此时Android Studio会自动加载Module name
  2. File->Project Structure->Dependencies->选择app->添加Module Dependency->选择opencv
  3. 将opencv文件夹下的sdk/native/libs下自己手机cpu对应的架构文件夹复制到app/libs
  4. 将opencv模块的build.gradlecomplieSdkVersion,buildToolVersion,minSdkVersion,targetSdkVersion改成和appbuild.gradle一样
  5. appbuild.gradleandroid节点下添加
    sourceSets {
    main {
    jni.srcDirs = []
    jniLibs.srcDirs = ['libs']
    }
    }

然后点击sync now

  1. 在使用opencv前进行初始化
    static {
    if (!OpenCVLoader.initDebug()) {
    ...
    }
    }

常见错误

  1. 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)

MatBitmap互转的时候长宽设置不对

只使用native模块

3.x-3.4.7-3.x版本

方法一

  1. CMakeLists.txt编写
    1. include头文件目录
    2. 加载libopencv动态库(libopencv_worldlibopencv_java3),命名为opencv_lib
    3. opencv_lib加载至目标文件
set(opencv_dir /home/lynx/fuck_mount/opencv/build_dir/4_1_0_shared/OpenCV-android-sdk)
set(opencv_lib libopencv_world.so) # 或libopencv_java3.so

include_directories(${opencv_dir}/sdk/native/jni/include)
add_library(opencv_lib SHARED IMPORTED)
set_target_properties(opencv_lib PROPERTIES IMPORTED_LOCATION
${opencv_dir}/sdk/native/libs/${ANDROID_ABI}/${opencv_lib})

target_link_libraries(
# 目标文件

opencv_lib
# 其他库 )
  1. 修改app的build.gradle
    • android节点下插入,否则会报错找不到libopencv_world.solibopencv_java3.so
sourceSets {
main {
jniLibs.srcDirs = ['/sdk/native/libs 对应目录']
}
}

方法二

参考:CSDN

  1. CMakeLists.txt
    1. 设置OpenCV查找的目录
    2. 查找OpenCV
    3. include头文件目录
    4. 将OpenCV的库添加至目标文件
set(sdk_dir /home/lynx/fuck_mount/opencv/build_dir/4_1_0_shared)
set(OpenCV_DIR ${sdk_dir}/OpenCV-android-sdk/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${sdk_dir}/OpenCV-android-sdk/sdk/native/jni/include)

target_link_libraries(
# 目标文件

${OpenCV_LIBS}
# 其他库 )
  • 如果不设置OpenCV_DIR将无法查找OpenCV
  1. 修改app的build.gradle
sourceSets {
main {
jniLibs.srcDirs = ['/home/lynx/fuck_mount/opencv/build_dir/4_1_0_shared/OpenCV-android-sdk/sdk/native/libs']
}
}
  • 此外,务必将minSdkVersion调至21以上,否则将会只有v8a架构才能成功编译
  • 在app的build.gradle中:minSdkVersion->ANDROID_PLATFORM
  • ndkandroid.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版本的方法二

常见问题

  1. java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found(4.x版本)

stackoverflow

(不确定的解决方法)在app的gradle中修改

externalNativeBuild {
cmake {
cppFlags ""
arguments "-DANDROID_STL=c++_shared"
}
}

不要使用gnustl_sharedgnustl_static,已经过时

  1. 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步)
  1. 各种undefined reference to *(3.x版本)

std::ios_base::Init::Init()

TODO

  1. 各类AndroidBitmap的问题(3.x版本)
undefined reference to `AndroidBitmap_getInfo'

CMakeLists.txt增加

target_link_libraries(
# TODO 解决 AndroidBitmap 报错
jnigraphics)

参考:CSDN,这是一个很小的库,展示一个稳定的,基于C语言的接口,使本机代码安全地访问Java对象的像素缓冲区的位图

source code(使用完整代码)

3.x-3.x版本(未成功,需要eclipse)

4.x-4.1.0-4.x版本

参考:CSDN

  1. 环境变量

    • JAVA_HOME

      export 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/{版本}
  2. 调整结构

    • 修改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,否则无法编译安卓模块

  3. 修改cmake参数(2选1,推荐world)(修改根CMakeLists.txt)

    • java
      • OPENCV_ENABLE_NONFREE:改为ON
      • BUILD_SHARED_LIBS:不动或者改为OFF,与生成java库冲突
      • BUILD_ANDROID_PROJECTS:不动或者改为ON
      • BUILD_FAT_JAVA_LIB:不动或者改为ON,保证生成libopencv_java4.so
      • BUILD_JAVA:不动或者改为ON
      • /samples/android/CMakeLists.txt中除了ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations)那一行,其他全部注释掉,否则android sdk会在编译sample时报错
    • world
      • OPENCV_ENABLE_NONFREE:改为ON
      • BUILD_SHARED_LIBS:改为ON
      • BUILD_ANDROID_PROJECTS:不动或者改为ON
      • BUILD_FAT_JAVA_LIB:改为OFF,生成libopencv_world.so
      • BUILD_JAVA:不动或者改为ON
      • /samples/android/CMakeLists.txt中除了ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations)那一行,其他全部注释掉,否则android sdk会在编译sample时报错
  4. 执行platforms/android/build_sdk.py,完成编译

./build_sdk.py --ndk_path {ndk路径} --sdk_path {android sdk路径} --extra_modules_path {path_to_contrib/modules} {目标位置} {opencv源码位置}
# example
/home/lynx/fuck_mount/opencv_4_1_0/opencv-4.1.0/platforms/android/build_sdk.py --ndk_path /home/lynx/fuck_mount/Android/SDK/ndk/18.1.5063045 --sdk_path /home/lynx/fuck_mount/Android/SDK --extra_modules_path /home/lynx/fuck_mount/opencv/source_code/opencv_contrib_4_1_0/modules /home/lynx/fuck_mount/opencv_4_1_0/android_build /home/lynx/fuck_mount/opencv_4_1_0/opencv-4.1.0

如果没有设置则默认为环境变量

  • sdk-path:Android Studio的SDK目录
  • ndk-path:Android Studio的SDK目录下ndk/{ndk版本号文件}
  1. 后续关于CMakeLists.txt(android项目内的)和build.gradle的修改同native方法

常见错误

  1. 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

  1. 没装cmake
Executing: ['ninja', '--version']
Failed: [Errno 2] No such file or directory

Android Studio需要在SDK Manager里面预先安装CMake,否则编译的时候会找不到ninja等程序

  1. 没有libopencv_java4.so

    • BUILD_FAT_JAVA_LIBBUILD_ANDROID_PROJECTS要设置ON(或默认)
    • 记得修改android sdk tools文件结构
    • 不能同时编译动态库
  2. 编译错误

Regex: 'command line option .* is valid for .* but not for C\+\+'

TODO,可能是编译器的问题或cmake参数设置错误

  1. android project报错
A problem occurred configuring project ':face-detection'.
> NDK not configured.
Download it with SDK manager.

samples/android/CMakeLists.txt对应代码注释掉

  1. ndk报错
CMake Error at /home/lynx/fuck_mount/Android_SDK/ndk/20.1.5948944/build/cmake/android.toolchain.cmake:169 (message):
GCC is no longer supported. See
https://android.googlesource.com/platform/ndk/+/master/docs/ClangMigration.md.

需要将ndkbuild/cmake/android.toolchain.cmakeset(ANDROID_TOOLCHAIN gcc)改为clang

  1. 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

  1. ccache未安装(3.x版本,TODO:不确定是否为必须)

用apt安装ccache即可

  1. ld报错(3.x版本)
cannot open crtbegin_dynamic.o: 没有那个文件或目录
cannot open crtend_android.o: 没有那个文件或目录
cannot find -lstdc++
cannot find -lm
cannot find -lc
cannot find -ldl

TODO修改gcc参数(但很大程度上是由于cmake参数配置错误)

  1. 添加-nostdlib
  2. 修改--sysroot参数
  1. clang++报错
error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory

使用apt安装libtinfo5

  1. 编译错误
error: use of undeclared identifier 'vcvt_f16_f32'
float16x4_t v_dst = vcvt_f16_f32(v_src);

多种可能

  • ndk
  • opencv_contrib的路径设置错误
  1. libopencv_java3.so没有生成(3.x版本)

TODO,很大程度上是由于cmake参数配置错误

  1. cmake报错
Android SDK: Can't build Android projects as requested by
BUILD_ANDROID_PROJECTS=ON variable.
  • 4.x:android sdk build tool版本过低
  • 3.x:需要sdk整合ant(ide为eclipse)
  1. java报错
opencv init failed

检查gradlelib路径是否正确加载

额外说明

4.x版本

  • 不需要额外安装的软件:jdk,ninja-build,ndk,直接使用android studio的即可
  • 成功编译的版本:
    • ndk:20.1.5948944
    • sdk tools:28.0.3
    • cmake: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部分功能的初始化

github原文

Loader.load(opencv_java.class);// 不能直接放在class开头

使用远程导入

appbuild.gradle示例(最外节点)

ext {
versions = [
'javacv': '1.4.4',
'ffmpeg': '4.1',
'opencv': '4.0.1'
]
}

dependencies {
...
implementation(group: 'org.bytedeco', name: 'javacv-platform', version: versions.javacv) {
exclude group: 'org.bytedeco.javacpp-presets'
}
implementation group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: "${versions.ffmpeg}-${versions.javacv}"
implementation group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: "${versions.ffmpeg}-${versions.javacv}", classifier: 'android-arm'
implementation group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: "${versions.ffmpeg}-${versions.javacv}", classifier: 'android-arm64'
implementation group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: "${versions.opencv}-${versions.javacv}"
implementation group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: "${versions.opencv}-${versions.javacv}", classifier: 'android-arm'
implementation group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: "${versions.opencv}-${versions.javacv}", classifier: 'android-arm64'
}

作为lib导入

根据手机具体的cpu架构进行导入

appbuild.gradle

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}

将文件(视具体情况)

  • javacpp.jar
  • javacv.jar
  • openblas.jar
  • openblas-android-arm64.jar
  • opencv.jar
  • opencv-android-arm64.jar
    复制到app/libs/文件夹里

常见错误

  1. cpu架构错误/缺少(需添加-android-arm之类的库)
2019-10-27 16:01:32.439 29256-29322/? E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.github.crazyorr.ffmpegrecorder, PID: 29256
java.lang.RuntimeException: An error occurred while executing doInBackground()
  1. 没有对opencv初始化
2019-10-27 16:00:43.930 28933-28933/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.javacv, PID: 28933
java.lang.UnsatisfiedLinkError: No implementation found for long org.opencv.core.Mat.n_Mat() (tried Java_org_opencv_core_Mat_n_1Mat and Java_org_opencv_core_Mat_n_1Mat__)
  1. 缺少openblas的相关jar
2019-10-27 15:59:23.158 28618-28618/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.javacv, PID: 28618
java.lang.NoClassDefFoundError: Failed resolution of: Lorg/bytedeco/openblas/presets/openblas;

混用java+native模块

4.x native(或source code)+3.x java

参考:CSDN

  1. 加载native模块

  2. File->New->Import Module->选择opencv文件夹下的sdk/java文件夹,自己定义模块的名字

  3. 修改模块的gradle文件(TODO)

// 将原来的application改成library
apply plugin: 'com.android.library'

android {
// 将版本信息改得和`app`的`build.gradle`一样
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
// 删除applicationId
minSdkVersion 15
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
// 不改动
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
  1. 修改app的gradle文件,加载两者的lib,缺一不可
sourceSets {
main {
jniLibs.srcDirs = ['/home/lynx/fuck_mount/opencv/source_code/opencv_3_4_7_android/sdk/native/libs',
'/home/lynx/fuck_mount/opencv/build_dir/4_1_0_shared/OpenCV-android-sdk/sdk/native/libs']
}
}
  1. 修改app的gradle文件,添加java模块依赖

dependencies {
implementation project(path: ':openCVLibrary347')
}

Linux

OpenCV source code 3.x(3.4.7)

gui安装

4.x一样

常见错误

  1. fatal error: Eigen/Core: 没有那个文件或目录``#include <Eigen/Core>

    1. 修改WITH_EIGEN=OFF

    2. (或)

      • 先保证安装eigen:sudo apt install libeigen3-dev
      • 添加EIGEN_INCLUDE_PATH=/usr/include/eigen3(视具体情况)
  2. 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

  1. 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"
    1. opencv/opencv_3rdpartyippicv对应分支中下载对应的tgz

    2. tgz放入/home/lynx/Downloads/

    3. 修改opencv的source code: vi /3rdparty/ippicv/ippicv.cmake,将ippicvhttps地址改为file:/home/lynx/Downloads/

    4. 重新cmake-gui

OpenCV source code 4.x(4.1.0)

依赖包

sudo apt install libgtk2.0-dev pkg-config

一定要安装,否则会报错

  • 缺少gtk
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.1.0) /home/lynx/fuck_mount/opencv/source_code/opencv_4_1_0/modules/highgui/src/window.cpp:610: error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Cocoa support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvNamedWindow'

命令行安装(TODO)

  1. cmake
cd {生成makefile的位置}
cmake {source的位置}
  1. make
cd {生成makefile的位置}
make
  1. make install
make install {安装的位置}

gui安装

参考:CSDN

  1. 安装cmake-gui
sudo apt install cmake-gui
  1. 启动cmake-gui
cd {build二进制文件的目录}
cmake-gui {opencv source code}
  1. Configure->Unix Makefiles:Use default native compilers->finish

  2. 狂点Configure直到没有红色区域

  3. 赋值

变量名 赋值
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 勾选
  1. 狂点Configure

  2. Generate,等到Generating done

  3. 在build路径make

sudo make -j4 # 具体看有多少cpu
cat /proc/cpuinfo | grep "processor" | wc -l # 查看cpu个数
sudo make install
  1. 配置opencv4.pc(2选1)

    • 修改PKG_CONFIG_PATH:增加{你cmake_install的路径}/lib/pkgconfig(opencv4.pc所在的路径)
    • (TODO,没试过)复制opencv4.pc/usr/lib/pkgconfig
  2. 配置库路径,(新建)/etc/ld.so.conf.d/opencv.conf

{你cmake_install路径}/lib/ # 自己的lib路径
sudo ldconfig
  1. 编译测试

如果是opencv.pcopencv4改成opencv

pkg-config --modversion opencv4
g++ a.cpp `pkg-config --cflags --libs opencv4` -o test && ./test

常见问题

  1. 在其他项目中用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的对应路径

Tags

ndk

Categories

1 / 1