我在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. More on Class Loading and Initialization

    上一篇博客中对于类的加载和初始化进行了详细的说明,但上一篇博客代码中的main()所在的类为导出类, 对其中一些问题的理解可能会引起误导和不明确,所以补充这篇博客进一步说明.以下面的代码为例进行说明: ...

  2. python有哪些好的学习资料或者博客?

    推荐Full Stack Python 有各种python资源汇总,从基础入门到各种框架web应用开发和部署,再到高级的ORM.Docker都有.以下是Full Stack Python 上总结的一些 ...

  3. Linux文件系统管理 fdisk分区命令

    概述 我们在安装操作系统的过程中已经对系统硬盘进行了分区,但是如果我新添加了一块硬盘,想要正常使用时,在Linux中有专门的分区命令 fdisk 和 parted.其中 fdisk 命令较为常用,但不 ...

  4. Android相机实时自动对焦的完美实现

    https://zhidao.baidu.com/question/873328177698804372.html Android相机实时自动对焦的完美实现 http://blog.csdn.net/ ...

  5. OC_链表实现队列

    @interface Node : NSObject @property(nonatomic,strong)NSString *value; @property(nonatomic,strong)No ...

  6. log4j2.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?> <!--日志级别以及优先级排序: OFF > FATAL ...

  7. 通用Mapper(Mybatis)

    1.Mapper的简单介绍 2.Mapper的作用 通用Mapper可以通过Mybatis的拦截器原理,动态的帮我们实现单表的增删改查功能,大大降低了我们的开发成本,减少了我们的工作量. 3.Mapp ...

  8. Windows命令行乱码问题解决

    命令 chcp功能: 显示或设置活动代码页编号 CHCP [nnn] nnn 指定代码页编号. 不加参数键入 CHCP 显示活动代码页编号. nnn指定一已有的系统字符集,该字符集在CONFIG.SY ...

  9. 利用CXF框架开发webservice

    开发服务端代码 1. web.xml文件中添加cxf的servlet 2. 定义接口 @WebService(targetNamespace="http://UserInfo.ws.com& ...

  10. [转载]Struts2.1.6+Spring2.5.6+Hibernate3.3.

    原文地址:Struts2.1.6+Spring2.5.6+Hibernate3.3.1全注解实例详解(一)(转载大象)作者:沉睡森林  在JavaEE企业级开发中,以SSH2框架为核心的应用非常广,大 ...