NDK使用 ,OpenCV库的调用,在NDK中使用纯C++代码,android studio 2.1(1)
2016-07-25 19:11
288 查看
NDK使用 ,OpenCV库的调用,在NDK中调用纯C++代码,android studio 2.1(1)
盖天地不全,这经原是全全的,今沾破了, 乃是应不全之奥妙也,岂人力 所能与耶! 愿来者补充最近需要把一个使用了OpenCV(249)的C++人脸检测的代码,转到Android中使用,恰好Android Studio2.1可以使用NDK这么一个很好用的东西来直接代码。故,决定使用NDK,但是这个里面的坑确实太多了,决定写下来,提醒自己也帮助他人。
1,NDK的安装,和配置OpenCV
开始的时候是借鉴这篇文章[Android开发配置opencv环境超详细教程
这篇文章确实很详细,但是我在运行的时候还有遇到了一些小麻烦,
:1下载NDK和OpenCV for android
选择你的项目,右键
可以选择download 或者选择解压自己的下载的NDK的路径
你就可以看到local.properite文件中就添加了NDK路径
:2 添加opencv native包,这个是为了C++代码中需要使用到OpenCV的库。
方法呢更最前面说的文章做法一样我就不再过多说明了
我就说明一点,下载的是OpenCV-**-Android-sdk这样的,然后解压就可以了。
:3,编辑gradle.properties文件
在文件最后一行直接添加android.useDeprecatedNdk=true ,这句好,这句话我之前没有添加,老是报错说要添加,后来查了一下是因为增加下面的属性使用旧版的ndk功能(不添加会使用实验性的ndk构建工具)
:4,接下来几步,和最前面说的文章做法一样
但我安装他的安装步骤就是运行不了,就是会出错,后来发现好像是他的代码中出现了一下问题。这里没有说他错的意思,可能是版本不同,或者配置不一样,才导致最后我运行失败了。
#include "com_example_administrator_tryopencv_OpenCVHelper.h" #include <stdio.h> #include <stdlib.h> #include <opencv2/opencv.hpp> using namespace cv; extern "C" { /*注意这里,下面2行,这里,我使用的时候是直接拷贝他的,但是运行就出现找不到这个方法,错误 然后我就有点发现者2行代码是多余的吗,我就删除了者下面2行结果就对了*/ JNIEXPORT jintArray JNICALL Java_com_example_administrator_tryopencv_OpenCVHelper_gray(JNIEnv *env,jclass obj,jintArray buf,int w,int h); JNIEXPORT jintArray JNICALL Java_com_example_administrator_tryopencv_OpenCVHelper_gray(JNIEnv *env,jclass obj,jintArray buf,int w,int h) { jint *cbuf; cbuf = env->GetIntArrayElements(buf,JNI_FALSE); if (NULL == cbuf) { return 0; } Mat imgData(h,w,CV_8UC4,(unsigned char*) cbuf); u_char *ptr = imgData.ptr(0); for (int i = 0; i < w*h; ++i) { //图像存储方式为:BGRA int grayScale = ( b3e6 int)(ptr[4*i+2]*0.299 + ptr[4*i+1]*0.587 + ptr[4*i+0]*0.144 ); ptr[4*i+0] = grayScale; ptr[4*i+1] = grayScale; ptr[4*i+2] = grayScale; } int size = w * h; jintArray result = env->NewIntArray(size); env->SetIntArrayRegion(result,0,size,cbuf); env->ReleaseIntArrayElements(buf,cbuf,0); return result; } }
:5到这里NDK的安装和OpenCV的添加调用,基本都没有问题,
2,怎么调用纯C++代码呢,或者说以前自己写的C++代码呢?
要是都按照上面的方法来写C++代码的话就太麻烦了,这也不是google的风格,肯定有个方法可以直接调用C++的代码。但是我查了好多,看了其他人写的博客,实在是找不到,办法。。最后只能去求助官方给的文档和代码。哈哈,,虽然麻烦了一点,但是结果是好的。下面来说一下
我先看了一下文档觉得不行,然后只能求助代码官方给的一些实例然后我就找到了其中naticve-codec/jin这里下面的代码,看到looper.h文件就是纯C的我就知道有希望了,然后查看了Android.mk文件,看下面
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := native-codec-jni /*重点在这里,看到没有,loop.cpps是C++的代码,这么写就可以直接调用而不会出现没有这个文件,或者没有编译的情况,是不是很简单,但是我查了很多,都没有找到要不就是"./looper.cpp"这样的,我要来解释一下,对于纯C++代码,是“空格+文件名.cpp”这样添加的,而自己写的作为java和c++代码的交接的地方就是包含这样函数“JNIEXPORT jintArray JNICALL Java_com_example_administrator_gray”的代码文件是“./+文件名.cpp”,形式的*/ LOCAL_SRC_FILES := native-codec-jni.cpp looper.cpp # for native multimedia LOCAL_LDLIBS += -lOpenMAXAL -lmediandk # for logging LOCAL_LDLIBS += -llog # for native windows LOCAL_LDLIBS += -landroid LOCAL_CFLAGS += -UNDEBUG include $(BUILD_SHARED_LIBRARY)
好了,到这里,基本可以做到,调用纯的C++代码没有问题了
3:怎么在C++代码中使用Log.e(“”,”“),这样的输出
我也看了好多介绍,说是修改Android.mk或者其他的就可以使用,我也忘了。但是我发现了一个更为简单的使用办法,这个也是在官方代码中找到的
#include <android/log.h> #define TAG "NativeCodec-looper"//这是Log.v(TAG,"")中的TAG,自己修改就好了 #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
在前面加上这样几句话就可以在C++代码中使用下面形式的输出,下面输出相当于Log.v
LOGV("Looper deleted while still running. Some messages will not be processed")
是不是很简单
4:对于在native方法参数中使用Bitmap或者其他类型,我只想说,方法有。但是我尝试了好多,效果并不好,那怎么办呢?我是使用byte,int这样的数据,将bitmap转为byte,然后用int等来记录长,宽就可以了。这样传就一定不会出现问题。其他类型我的建议是转为最简单的类型,这样就可以保证正确,希望以后能够支持更多类型吧
5:虽然过程很艰难,结果只需要修改几行代码,带但是我还是很开心,因为没有现成的答案,我靠自己解决了问题。后面会继续写代码,后续也会继续更新分享。
相关文章推荐
- [置顶] android之View和ViewGroup事件分发机制分析(一)(View的事件分发机制)
- Create android source branch (创建安装源码分支)
- 关于Android.view.WindowManager$BadTokenException异常
- 如何自动连接上次连接的蓝牙的设备(Android开发)
- 【原创】android内存管理-内存泄漏原因
- Android Service基础之Bound Services
- Android Activity学习笔记——Activity的启动和创建
- Android-3 Activity启动模式
- How to get file path in onActivityResult in Android 4.4
- [转] ImageView的android:adjustViewBounds属性
- 11 百度地图
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- Glide框架使用笔记
- Android Studio 和 gradle 修改缓存文件夹路径
- Android—AlertDialog提示信息
- Android开发之shape自定义图形
- Android进阶处理图片之压缩图片大小、Lru内存解决方案
- activity和软键盘遮挡问题
- Android Studio improt project APIDemo
- Android 软键盘的显示和隐藏