声明下,我使用的是opencv3.3.4的库,ndk15,至于为什么,看我下一篇文章。
1、环境搭建
首先要确保你的第一个ndk-jni 环境搭建成功,参考我的上一篇文章《我的第一个NDK-jni程序》,下面呢我会再给大家重新配置一次,看不懂下面配置的就看我上一篇文章https://mp.csdn.net/mdeditor/89525978#。
1、下载ndk15
此时我们要用的ndk15,所以我们卸载掉as默认的最新版本,操作如下
然后去掉Android NDK前面的勾,点击ok就会完成卸载。
接下来需要下载一个ndk15版本,给你们提供一个链接,里面有各个版本。
https://blog.csdn.net/shuzfan/article/details/52690554
下载完毕后需要解压文件,将解压路径设置为:Android Studio的SDK目录里,并命名为ndk-bundle。
2、取消Android studio默认NDK支持
因为我们要自己写Android.mk和Application.mk文件,所以我们要取消默认NDK支持,话不多说,看图。
去掉Android NDK support前面的勾,此时Android APK support前面的勾也会自动被去掉,不用管它,去掉之后点ok,会重启。
3、添加ndk依赖目录
1、选择你的NDK目录就行了,我的只是作为参考,点击ok。
2、接下来gradle.properties
添加一句
android.useDeprecatedNdk=true
3、打开local.properties
当你配置好NDK目录后,会自动生成这两句。
ndk.dir=/home/book/Android/Sdk/ndk-bundle
sdk.dir=/home/book/Android/Sdk
2、开始编写代码
1、创建一个新的java类
我们暂且命名为NDKUtils,内容如下:
package com.example.book.ndklinkopecv1;
public class NDKUtils {
static {
System.loadLibrary("OpenCV");//导入生成的链接库文件
}
public static native int[] grayProc(int[] pixels, int w, int h);
}
2、生成头文件
打开目录:/src/main/java
然后输入以下代码生成头文件
javah -jni com.example.book.ndklinkopecv1.NDKUtils
注意:本目录仅供参,实际以你的目录为准。
此时就会生成一个头文件
3、创建jni文件
此时我们需要创建一个jni文件夹,把头文件移进去。
在main目录上右键
选择JNIFolder,生成jni文件夹。
把头文件移动进去,并且创建一个cpp文件,直接复制就行了,后缀改一下就ok。
4、创建Android.mk和Application.mk文件
touch 就行了,不多说。
5、添加opencv依赖库
进入你下载的opencv(一定是android版本的),把sdk下的native文件复制到jni文件下。
6、Android.mk配置
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
OpenCV_INSTALL_MODULES := on
OpenCV_CAMERA_MODULES := off
OPENCV_LIB_TYPE :=STATIC
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
include /work/h_course/android/NdklinkOPecv1/app/src/main/jni/native/jni/OpenCV.mk //本目录仅供参考,根据自己的目录为准
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := OpenCV //生成依赖库的名字
LOCAL_SRC_FILES := com_example_book_ndklinkopecv1_NDKUtils.cpp //该文件下的cpp文件,名字要准确
LOCAL_LDLIBS += -lm -llog
LOCAL_CPP_FEATURES += exceptions
include $(BUILD_SHARED_LIBRARY)
7、Application.mk配置
APP_STL += gnustl_static //ndk16版本及以上用c++_static
APP_CPPFLAGS += -frtti -fexceptions
APP_PLATFORM := android-16
8、cpp文件内容
#include <jni.h>
#include <string.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "com_example_book_ndklinkopecv1_NDKUtils.h"
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
extern "C" {
JNIEXPORT jintArray JNICALL Java_com_example_book_ndklinkopecv1_NDKUtils_grayProc
(JNIEnv *env, jclass obj, jintArray buf, int w, int h){
jint *cbuf;
cbuf = env->GetIntArrayElements(buf, JNI_FALSE );
if (cbuf == NULL) {
return 0;
}
Mat imgData(h, w, CV_8UC4, (unsigned char *) cbuf);
uchar* ptr = imgData.ptr(0);
for(int i = 0; i < w*h; i ++){
//计算公式:Y(亮度) = 0.299*R + 0.587*G + 0.114*B
//对于一个int四字节,其彩色值存储方式为:BGRA
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] = grayScale;
ptr[4*i+2] = grayScale;
ptr[4*i+0] = grayScale;
}
int size = w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result, 0, size, cbuf);
env->ReleaseIntArrayElements(buf, cbuf, 0);
return result;
}
}
9、MainActivity文件
package com.example.book.ndklinkopecv1;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NDKUtils ndk = new NDKUtils();
Bitmap bitmap;
bitmap = ((BitmapDrawable) getResources().getDrawable(
R.drawable.h1)).getBitmap(); //在drawble文件下导入图片为h1
int w = bitmap.getWidth(), h = bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
int [] resultPixes=NDKUtils.grayProc(pix,w,h);
Bitmap result = Bitmap.createBitmap(w,h, Bitmap.Config.RGB_565);
result.setPixels(resultPixes, 0, w, 0, 0,w, h);
ImageView img = (ImageView)findViewById(R.id.imageView);
img.setImageBitmap(result);
}
}
10、配置界面
<ImageView
android:id="@+id/imageView"
android:layout_width="377dp"
android:layout_height="wrap_content"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="0dp" />
>界面自行脑补
11、ndk-build编译生成依赖库
进入jni文件,ndk-build编译,编译成功后会生成库文件
这一步你可能会遇到很多坑,但是不要怕,静下心,方法总比困难多,该栽的跟头一个都不会少,这样你才会进步。你可以去我的下一篇文章中找答案,或者去度娘。
12、运行
如果你的ndk版本、opencv版本和我的一样,两个mk文件配置正确,ndk-build通过,那么运行是没有问题的,如果遇到问题,请看下一篇文章。
到此结束。