Android Studio+OpenCV+jni

初学者刚开始接触Android,又要开发opencv,真是举步维艰啊,现把阶段学习结果记录下:

1.android studio+opencv的安装及配置

android studio2.2官网下载

opencv-android2.4.10官网下载

这个网上资料介绍的很多,不过由于环境不一样,还是踩了很多坑。由于opencv是C++为基础语言,所以很多资料也是C的代码,而android studio采用的是java,不过还好android studio可以利用jni调用C++代码,android studio默认使用CMake构建编译,以前做Andorid下的opencv开发都是基于Android.mk方式是编译和配置opencv依赖的加载,本文通过配置CMakeList.txt来完成NDK opencv开发。

这个配置搞了很久,配置不好jni里面没法引用OpenCV,因为有很多不懂的地方,后续还是需要学习下,把配置以上传供后来人参考。

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)
#工程路径
set(pathToProject D:\\androidwork\\myfirstapp6)

#OpenCV-android-sdk路径
set(pathToOpenCv D:\\OpenCV-2.4.10-android-sdk)
SET(OpenCV_lib_DIR $ENV{HOME}/OpenCV-2.4.10-android-sdk/sdk/native/jni)

#支持-std=gnu++11
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

#配置加载native依赖
include_directories(${pathToOpenCv}/sdk/native/jni/include)

#CPP文件夹下带编译的cpp文件
add_library(native-lib SHARED src/main/cpp/native-lib.cpp)

#动态方式加载
add_library(lib_opencv SHARED IMPORTED )

#引入libopencv_java3.so文件
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${pathToProject}/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java.so)

#C++日志
find_library( log-lib log )

#target_link_libraries( native-lib $\{log-lib} )
target_link_libraries( native-lib $\{log-lib} lib_opencv jnigraphics)
2.在java里添加java层声明函数,然后在函数上alt+enter就会出现创建native层对应函数的菜单。

public static native int[] getGrayImage(int[] pixels, int w, int h);//静态函数
native函数默认创建在native-lib.cpp内,对应函数如下:
JNIEXPORT jintArray JNICALL
Java_myandroidword_myfirstapp6_MainActivity_getGrayImage(JNIEnv *env, jclass type,
                                                         jintArray pixels_, jint w, jint h) {
    jint *pixels = env->GetIntArrayElements(pixels_, NULL);
    // TODO
    if(pixels==NULL){
        return NULL;
    }
    cv::Mat imgData(h, w, CV_8UC4, pixels);
    uchar *ptr = imgData.ptr(0);
    for (int i = 0; i < w * h; i++) {
        int grayScale = (int) (ptr[4 * i + 2] * 0.299 + ptr[4 * i + 1] * 0.587
                               + ptr[4 * i + 0] * 0.114);
        ptr[4 * i + 1] = (uchar) grayScale;
        ptr[4 * i + 2] = (uchar) grayScale;
        ptr[4 * i + 0] = (uchar) grayScale;
    }

    int size = w * h;
    jintArray result = env->NewIntArray(size);
    env->SetIntArrayRegion(result, 0, size, pixels);
    env->ReleaseIntArrayElements(pixels_, pixels, 0);
    return result;
此函数转换后并返回灰度图数据。

3.如果要灵活使用jni开发,就需要在java层和native层进行参数传递,用法如下:

JNIEXPORT jlong JNICALL
Java_myandroidword_myfirstapp6_MainActivity_GrayImage(JNIEnv *env, jobject instance, jlong bitmat) {

    // TODO
    Mat *bitmpaMat = (Mat*) bitmat;
    Mat *gray = new Mat(bitmpaMat->rows ,bitmpaMat->cols,CV_32FC1);
    cv::cvtColor(*bitmpaMat,*gray,CV_BGR2GRAY);
    jlong j=(jlong)gray;
    if(j>0)
    {
        return j;
    }
    else{ return 0;}

}

4.native层调用java方法

//     1 . 找到java代码的 class文件
//     jclass(*FindClass)(JNIEnv*, const char*);
    jclass dpclazz = env->FindClass("myandroidword/myfirstapp6/MainActivity");
//    instance代表类的实例getobjclass取得实例所属的类
//    jclass dpclazz = env->GetObjectClass(instance);
    if(dpclazz==0){
        return;
    }
//    2 寻找class里面的方法
//    jmethodID(*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    jmethodID method1 = env->GetMethodID(dpclazz,"testcalljava","(J)V");
    if(method1==0){
        return;
    }
    //3 .调用这个方法
    // void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    std::string hello = "Hello Call Java OK";
    jstring js=env->NewStringUTF(hello.c_str());
    env->CallVoidMethod(instance,method1,js);

其中需要知道java层的函数签名描述,采用的是javap - s+classpath,需要进入classes文件夹,才能使用。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值