我在http://www.cnblogs.com/fx-blog/p/8206737.html一文中提到了如何在Android Studio中Java层导入OpenCV(包含opencv_contrib部分),但是这仅仅是Java层的导入,随着学习的深入,我们可以渐渐的发现OpenCV库对Java的支持不是很给力,比如我使用SIFT算法时,一般提取出来的特征点有一万多个,这其中包含了大量的无效特征点,如果我想指定特征点的数目,比如说500个(经过测试,Java中利用OpenCV提取特征点默认为500),但是OpenCV Java库中并没有提供这样的方法(或者是我没有发现,如果有大神知晓,还望告知)。但是在C++中,是可以给SIFT指定特征点的,这里面就需要有一个在Java中调用C++的功能,Java中我们知道可以利用JNI或者JNA解决,那么在Androd中我们便可以利用NDK做到Java对C++的调用。

  在Android Studio 2.2之前,我们通常是通过Android.mk和Application.mk两个文件设置本地开发;但是在Android Studio 2.2之后的版本,加入了利用CMAKE配置编译NDK项目的方法,这无疑是一个很好的消息,我们终于可以抛弃之前那种繁琐的方法啦,本篇文章只要讲的就是在Android Studio中利用CMAKE进行OpenCV的NDK开发。

准备工作:

  首先,我们需要在Android Studio中配置CMAKE、NDK工具,打开Android Studio 2.2,点击按钮打开SDK Manager,在SDK Platforms中选择你所需要的Android版本,这里我使用的是Android 7.0。

    

  在SDK Tools中选择红框标出的部分(这里推荐SDK Manager当中提供的NDK,NDK安装好后路径为<Android SDK Path>\ndk-bundle):

    

正式开始:

  创建一个新项目,在创建的过程中,我们需要勾选Include C++ Support,之后的步骤默认即可,可以与http://www.cnblogs.com/fx-blog/p/8206737.html相应正,写的不是很好,大家见谅。

  项目创建成功之后,会自动在app\src\main下建立一个名为cpp的文件夹,其中包含一个native-lib.cpp文件。同时,在app目录下会多出一个CMakeLists.txt文件,Android Studio调用CMAKE利用该文件来协调C++代码的编译(默认使用Clang编译),并将产生的.so文件提供给apk文件的打包过程。

  然后需要在Java层导入OpenCV,OpenCV 3.2 Android SDK可以选用之前编译好的库,下载地址:https://pan.baidu.com/s/1kVOejLt;在Android Studio中点击File -> New… -> Import Module,然后在Source Directory中选取<OpenCV 3.2 Android SDK>\sdk\java目录,这时Module Name就会自动变成“openCVLibrary320”,之后的步骤采用默认设置即可。

  刚刚导入OpenCV包之后,Android Studio会尝试自动编译,由于其默认的build.gradle文件设置并不适合最新版本,所以会报错。修改openCVLibrary320\build.gradle为如下内容就会纠正这些错误(红框标出的部分需要与app\build.gradle一致)。

    

   点击File -> Project Structure,在左边的Modules中点击“app”,然后点击右边的加号,再选择Module Dependency,然后在弹出框中选择:openCVLibrary320。这样,就为我们的项目app在Java层上添加了OpenCV支持(其中library是我使用的另外一个库,不用理会)。

    

接下来就是配置利用CMAKE配置OpenCV应用了:

  首先,需要将应用OpenCV C++所需要头文件和库文件全部复制到项目中,将<OpenCV 3.2 Android SDK>\sdk\native\jni\include文件夹复制到app\src\main\cpp当中,把<OpenCV 3.2 Android SDK>\sdk\native\libs文件夹复制到app\src\main当中,并将文件夹重命名为jniLibs。

    

  然后将 app\build.gradle修改为(各位看官可以对比修改):

apply plugin: 'com.android.application'

android {
compileSdkVersion
buildToolsVersion "27.0.1"
defaultConfig {
applicationId "com.example.demo02"
minSdkVersion
targetSdkVersion
versionCode
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++11", "-frtti", "-fexceptions"
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
}
}
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
} dependencies {
compile 'com.android.support:design:25.3.1'
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
compile project(':openCVLibrary320')
}

  app\CMakeLists.txt修改为:

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_VERBOSE_MAKEFILE on)
set(ocvlibs "${CMAKE_SOURCE_DIR}/src/main/jniLibs")
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include) add_library(libopencv_java3 SHARED IMPORTED )
set_target_properties(libopencv_java3 PROPERTIES
IMPORTED_LOCATION "${ocvlibs}/${ANDROID_ABI}/libopencv_java3.so") add_library( # Sets the name of the library.
native-lib # Sets the library as a shared library.
SHARED # Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp ) find_library( # Sets the name of the path variable.
log-lib # Specifies the name of the NDK library that
# you want CMake to locate.
log ) target_link_libraries( # Specifies the target library.
native-lib android log libopencv_java3 # Links the target library to the log library
# included in the NDK.
${log-lib} )

  配置部分就此完成了,贴一下关键部分的代码吧,NDK帮助类OpenCVNDKHelper:

 package com.example.ndk;

 public class OpenCVNDKHelper {
static {
System.loadLibrary("native-lib");
}
public native static void detectFeatures(long srcMatAddr, long dstMatAddr);
}

  C++文件native-lib.cpp:

 #include <jni.h>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp> using namespace std;
using namespace cv;
using namespace xfeatures2d; extern "C"
{
JNIEXPORT void JNICALL Java_com_example_ndk_OpenCVNDKHelper_detectFeatures
(JNIEnv *, jclass, jlong srcMatAddr, jlong dstMatAddr) {
Mat* srcMat = (Mat*)srcMatAddr;
Mat* descriptors = (Mat*)dstMatAddr;
vector<KeyPoint> Keypoints;
Ptr<SIFT> detector = SIFT::create(1000);
detector->detect(*srcMat, Keypoints);
detector->compute(*srcMat, Keypoints, *descriptors);
}
}

  这段代码主要的作用就是提取Sift特征(这里我就不介绍生成.h文件的过程了,只要掌握.cpp文件中的函数命名的方法,这个过程是可以省略的啦)。

  补充一点:这个代码其实也解释了如何在Java中将Mat传递到C++中的方法,在java中的调用如下(src和srcMat为Mat对象):

OpenCVNDKHelper.detectFeatures(src.getNativeObjAddr(), srcMat.getNativeObjAddr());

  PS:文章中使用的jniLibs是直接拷贝到目录中的,这个项目的存储空间就比较大了,大约1G左右,每次新建项目都需要重新拷贝,大家也可以用软链接或者绝对路径代替,这里就不多介绍啦。但是最终生成的APK文件大小是差不多的。

  over~~~

跑下题:

  写博客的过程中,老爸忽然找我视频聊天,我们聊了蛮多,主要就是催我找个女朋友,难道95后也要被家长催找女朋友了吗,感觉从我6月份毕业以来(可能更早),这个话题就没有停过啊,脑补过年回家的场面。。。

OpenCV - Android Studio 2.2 中利用CAMKE进行OpenCV的NDK开发的更多相关文章

  1. android Log 等级以及在Android Studio 的Logcat中过滤方法

    Log等级 等级越高,问题越严重. Log.e(TAG,"级别5,错误信息"); Log.e(TAG,"级别5,错误信息"); Log.w(TAG," ...

  2. 【Android Studio安装部署系列】四十二、Android Studio使用Eclipse中的keystore为App签名

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 从eclipse迁移到AndroidStudio,要用原Eclipse的签名文件,这样才能保证转到AndroidStudio后更新的 ...

  3. Android Studio使用过程中常见问题及解决方案

    熟悉Android的童鞋应该对Android Studio都不陌生.Android编程有两个常用的开发环境,分别是Android Studio和Eclipse,之前使用比较多的是Eclipse,而现在 ...

  4. OpenCV - Android Studio 中集成Opencv环境(包含opencv_contrib部分)

    我在上一篇博客中说到了在Android中集成OpenCV,但是那个版本的OpenCV是没有SIFT和SURF算法的,因为这些算法是受专利保护的,所以并没有被包含在预编译库中,所以如果想要使用SIFT和 ...

  5. OpenCV - Android Studio 中集成Opencv环境(不包含opencv_contrib部分)

    OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,支持的运行环境也是非常的多,这篇文章主要讲的是Android环境集成OpenCV(IDE是Android Studio,我想Eclip ...

  6. android studio和eclipse中如何获取sha1值

    首先如果是eclipse的话, 直接打开eclipse开发工具 那么接下来问题来了,现在很多开发者都已经从es转型到as开发工具了, 在android studio上没有直接提供这个GUI界面让我们去 ...

  7. Android studio 一个项目中添加两个module遇到的bug

    1.在一个Android studio中,我添加了一个模块,然后就是各种bug 找到到R 是在module 名上面 右键 Make Module '模块名' 经过各种google 的时候发现了 htt ...

  8. 【android studio】android studio使用过程中,搜集的一些问题

    1.[知乎]在Android Studio中如何将依赖的jar包放在SDK的android.jar前? 在编译原生Contacts应用时需用到非公开的API,需要引入framework等jar包,但在 ...

  9. Android Studio] Gradle项目中添加JNI生成文件(.so文件)

    转:http://blog.csdn.net/qiujuer/article/details/24209457 为了适应潮流使用Android Studio还是有半年多了! 对于从Eclipse迁移项 ...

随机推荐

  1. ABP框架数据迁移报错

    问题描述:将项目从TFS载下来  然后敲update-database 进行数据迁移 提示:Update-Database : 无法将“Update-Database”项识别为 cmdlet.函数.脚 ...

  2. 026_默认的MapReduce Driver(最小驱动问题)

    1. 最小配置的MapReduce Driver 读取输入文件中的内容,输出到指定目录的输出文件中,此时文件中的内容为: Key---输入文件每行内容的起始位置. Value---输入文件每行的原始内 ...

  3. ETL应用:使用shell实现文件级校验的方法

    BI应用中,对接口规范性约束很重要,接口文件提供需要配套提供该文件的校验文件,校验文件格式如下: 序号 信息内容 数据类型及长度 说明 1 接口数据文件名称 CHAR(50) 2 文件的大小(字节数) ...

  4. 线程同步synchronized和ReentrantLock

    一.线程同步问题的产生及解决方案 问题的产生: Java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突. 如下例:假设有一个卖票 ...

  5. 使用JDK将tomcat变成https访问

    1,今日JDK目录,执行命令 keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore " ...

  6. node做验证码

    使用了ccap插件 1.安装: 通用方法:npm install ccap 2. cnst ccap= require('ccap')({ width: 128, height: 40, offset ...

  7. HTML5模拟衣服撕扯动画

    在线演示 本地下载

  8. python的语法错误总结

    1.keyerror一般是你使用字典里不存在的key产生的错误. 2.TypeError一般是使用的数据类型不符合要求 join函数要求a都是string

  9. php数组函数-array_diff()

    array_diff()函数返回两个数组的差集数组.该数组包括了所有在被比较数组中,但是不在任何其他参数数组中的键值在返回数组中,键名保持不变. array_diff(array1,array2,ar ...

  10. Python的装饰器实例用法小结

    这篇文章主要介绍了Python装饰器用法,结合实例形式总结分析了Python常用装饰器的概念.功能.使用方法及相关注意事项 一.装饰器是什么 python的装饰器本质上是一个Python函数,它可以让 ...