Android OpenCV 实例笔记1--Jni及OpenCV环境的搭建

发表于 2016-08-03  |   第1更新

工程源代码整理中

本文示例OPENCV为3.1.0版本,OpenCV各版本下载地址http://opencv.org/   NDK版本为r10e


前言速记

不用安装manager有三种方法,三种方式的Application.mk内容都一样

三者的Android.mk内容有所不一样,区别如下

1、使用静态的OpenCV库的方式:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OpenCV_INSTALL_MODULES:=on//自动将依赖的OpenCV的so库拷贝到libs目录下
OPENCV_CAMERA_MODULES:=off//on时,会自动将里面的带camera的so拷贝至工程下的libs文件夹下
OPENCV_LIB_TYPE:=STATIC
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
include 
D:\Android\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk
else  
include $(OPENCV_MK_PATH)  
endif 
LOCAL_MODULE := ImgFun
LOCAL_SRC_FILES := ImgFun.cpp
LOCAL_LDLIBS += -lm -llog			
include $(BUILD_SHARED_LIBRARY) 


 
  
 
  

2、使用动态的OpenCV库的方式:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

OpenCV_INSTALL_MODULES:=on
OPENCV_CAMERA_MODULES:=off
OPENCV_LIB_TYPE:=SHARE  //注意这里为SHARE,通过动态链接的方式连接OpenCV的so
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
include D:\Android\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk
else  
include $(OPENCV_MK_PATH)  
endif 

LOCAL_MODULE := ImgFun
LOCAL_SRC_FILES := ImgFun.cpp
LOCAL_LDLIBS += -lm -llog
			
include $(BUILD_SHARED_LIBRARY) 
3、同时使用Java的API又使用JNI的接口的方式,此时编译时一般使用的是动态链接OpenCV库的方式
与第二种类似

下面介绍第一种方法,此种方法生成的APK体积较小

配置OpenCV

这一步是必须的,不管想在手机上直接用Java实现,还是通过Jni调用c++实现。

  1. 下载Open_CV_for_Android,假设放在D盘下(D:\Android\OpenCV-android-sdk)。
  2. Android Studio -> File -> import mudules,选择OpenCV文件夹下的sdk/java
  3. Android Studio -> Project Structure -> app -> Dependencies -> 添加Module Dependencies ->添加OpenCV。
  4. 在建好的Android工程的main文件夹下,新建一个文件夹,命名jniLibs。将OpenCV文件夹下的sdk/native/libs下的文件复制到该文件夹下。
  5. 新导入的openCVLibrary300(300表示3.0.0,其它版本类推),下面有个build.gradle文件,将里面的compileSdkVersion、buildToolsVersion、minSdkVersion、targetSdkVersion修改,使其与app目录下的build.gradle保持一致。

至此OpenCV配置完成。

Java调用Op

编辑gradle.properties文件,增加下面的属性使用旧版的ndk功能(不添加会使用实验性的ndk构建工具)

android.useDeprecatedNdk=true


在Java代码中添加一个静态域

static {
        System.loadLibrary(
"ImgFun");
}

即可直接调用OpenCV的库函数进行。


配置NDK

NDK全称为Native Development Kit,便于安卓调用底层代码。
主要配置过程如下:

  1. 下载NDK,假设放在D盘(D:\android-ndk-r10e)。
  2. 在Android Studio 中添加NDK,Project Structure -> SDK Location 最下面一栏添加ndk的路径。
  3. 在main文件夹下新建文件夹jni。该目录主要用于放置c++文件及其头文件。
  4. 在app文件夹下build.gradle中添加
    ndk{
    moduleName “Demo”
    }。编译后生成一个libDemo.so文件。
  5. 在Java中添加System.loadLibrary(“Demo”)即可调用so库。

Jni调用OpenCV

在jni文件夹新建Android.mk,添加以下代码:

LOCAL\_PATH := $(call my-dir)
include $(CLEAR\_VARS)
include D:\Android\OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
LOCAL\_MODULE :=Demo LOCAL\_SRC\_FILES :=Demo.cpp LOCAL\_LDLIBS += -llog -ldl
include $(BUILD\_SHARED\_LIBRARY)



上述的include后接OpenCV目录下的文件。
在jni文件夹新建Application.mk,添加以下代码:

APP\_STL:=gnustl_static   
APP\_CPPFLAGS:=-frtti -fexceptions   
APP\_ABI:=armeabi armeabi-v7a


在app下的build.gradle下,可以删除上一节中的

ndk{
moduleName “Demo”
},

因为在Android.mk已经定义过了。添加以下代码:

sourceSets.main{
    jniLibs.srcDir'src/main/libs' //set .so files directory to libs
    jni.srcDirs =[] //disable automatic ndk-build call
}
// call regular ndk-build(.cmd) script from app directory
task ndkBuild(type: Exec) {
    if(Os.isFamily(Os.FAMILY_WINDOWS)) {
        commandLine'D:\android-ndk-r10e\ndk-build.cmd', '-C',file('src/main').absolutePath//windows系统下的操作
    } else {
        commandLine'ndk-build', '-C', file('src/main').absolutePath
    }//linux,mac系统的操作
}
tasks.withType(JavaCompile) {
    compileTask-> compileTask.dependsOn ndkBuild
}


可以直接在cpp文件#include “opencv2/openc.hpp”,如果编译成功会在main文件夹下生成一个obj文件夹,这个文件夹的so文件可以供Java调用。
此,Android Studio下的配置工作基本完成。

 

详细的源代码见下

jni文件夹下Android.mk文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

OPENCV_LIB_TYPE:=STATIC

 

ifeq ("$(wildcard$(OPENCV_MK_PATH))","")

includeD:\Android\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk//地址改成自己的

else

include $(OPENCV_MK_PATH)

endif

 

LOCAL_MODULE := ImgFun

LOCAL_SRC_FILES := ImgFun.cpp

LOCAL_LDLIBS += -lm -llog

include $(BUILD_SHARED_LIBRARY)

jni文件夹下的Application.mk

APP\_STL:=gnustl_static   

APP\_CPPFLAGS:=-frtti -fexceptions   

APP\_ABI:= x86 armeabi-v7a

app下的build.gragle

apply plugin: 'com.android.application'

 

android {

   compileSdkVersion 23

   buildToolsVersion '23.0.1'

 

    defaultConfig {

       applicationId "com.study.opencvedge"

       minSdkVersion 14

       targetSdkVersion 23

        versionCode1

        versionName"1.0"

    }

    buildTypes {

        release {

           minifyEnabled false

           proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

        }

    }

 

    sourceSets.main{

       jniLibs.srcDir 'src/main/libs' //set .so files directory to libs

        jni.srcDirs= []

    }

 

    taskndkBuild(type: Exec) {

        commandLine'D:\\Android\\android-ndk-r10e\\ndk-build.cmd', '-C',file('src/main').absolutePath

//windows系统下的操作;将路径替换为自己NDK所在位置;

       tasks.withType(JavaCompile) {

            compileTask-> compileTask.dependsOn ndkBuild

        }

    }

}

 

    dependencies {

        compilefileTree(include: ['*.jar'], dir: 'libs')

        compile'com.android.support:appcompat-v7:22.2.0'

        compileproject(':openCVLibrary310')

    }  

jni下C++源代码

//实现图片的截取

#include

#include

#include

#include

using namespace cv;

IplImage * change4channelTo3InIplImage(IplImage * src);

extern "C" {

JNIEXPORT jintArray JNICALL Java_com_study_opencvedge_MainActivity_ImgFun(

        JNIEnv*env, jobject obj, jintArray buf, int w, int h);

JNIEXPORT jintArray JNICALL Java_com_study_opencvedge_MainActivity_ImgFun(

        JNIEnv*env, jobject obj, jintArray buf, int w, int h){

  jint *cbuf;

  cbuf = env->GetIntArrayElements(buf,false);

  if(cbuf == NULL)

  {

    return 0;

  }

  Mat myimg(h, w, CV_8UC4,(unsigned char*)cbuf);

  for(intj=0;j

  {

    myimg.row(j).setTo(Scalar(0,0,0,0));

  }

  int size=w * h;

  jintArray result= env->NewIntArray(size);

 env->SetIntArrayRegion(result, 0, size, cbuf);

  env->ReleaseIntArrayElements(buf,cbuf, 0);

  return result;

}

}

 

你可能感兴趣的:(安卓开发)