NDK使用 ,OpenCV库的调用,在NDK中使用纯C++代码,android studio 2.1(1)

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的路径
    可以选择download 或者选择解压自己的下载的NDK的路径

    你就可以看到local.properite文件中就添加了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 = (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:虽然过程很艰难,结果只需要修改几行代码,带但是我还是很开心,因为没有现成的答案,我靠自己解决了问题。后面会继续写代码,后续也会继续更新分享。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值