android studio使用jni调用opencv库实现图片转换【详细实例】(二)
代码过程实现
AndroidStudio平台JNI对Opencv环境搭建请参考文章 https://blog.csdn.net/u014159143/article/details/88975487
平台开发环境
- Android Studio 3.2
- opencv-3.4.3-android-sdk
配置文件修改
1、将opencv和app的build.gradle中配置改成一致:
compileSdkVersion 28minSdkVersion 17targetSdkVersion 28
2、修改openCVLibrary343\src\main\AndroidManifest.xml文件中的配置(根据你的需要修改)
<?xml version="1.0" encoding="utf-8"?>
3、在app的build.gradle文件中指定jnilib目录
android { compileSdkVersion 28 defaultConfig { ... ... externalNativeBuild { cmake { cppFlags "-std=c++11 -frtti -fexceptions" } } } ... ... externalNativeBuild { cmake { path "CMakeLists.txt" } } sourceSets{ main{ jniLibs.srcDirs = ['libs'] } }}
4、在CMakeLists.txt文件中添加opencv的库配置
cmake_minimum_required(VERSION 3.4.1)# 添加opencv的头文件目录include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)# 导入opencv的soadd_library(opencv_java3 SHARED IMPORTED)set_target_properties(opencv_java3 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libopencv_java3.so)... ...target_link_libraries( # Specifies the target library. native-lib opencv_java3 # Links the target library to the log library # included in the NDK. ${log-lib})
千万注意:以上代码中的三个库名称可以写成opencv_java3、libopencv_java3、mylib等等,这里我先前纠结了很久,主要是发现网上有写成opencv_java3的也有写成libopencv_java3的,后来我查了下cmake的原理才明白, 它的原理就是将你调用的库重新编译成一个文件,当然编译成的名字还是libopencv_java3.so(你可以对比下apk中的so库和libs下的已经不一样了),叫啥名字无所谓,只是方便jni编译和调用而已,但是一定要一致,否则将报错。
好了如果AS没有报错误,恭喜你,你的平台环境已经搭建完成,现在只需要修改代码就可实现你想要的功能了,这里我们还是用网上比较多的图片二值化效果:
编写功能代码
1、编写布局文件layout.xml
首先将你要用的图片拖进来:
编写你的布局文件:
<?xml version="1.0" encoding="utf-8"?>
2、编写MainActivity.java代码
package com.hello;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.ImageView;import android.widget.TextView;import org.opencv.core.Mat;public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("opencv_java3"); System.loadLibrary("native-lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView ivOld = (ImageView)findViewById(R.id.ivOld); ImageView ivNew = (ImageView)findViewById(R.id.ivNew); Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.luffy); int width = bitmap.getWidth(); int height = bitmap.getHeight(); int[] pixArr = new int[width*height]; bitmap.getPixels(pixArr,0,width,0,0,width,height); gray(pixArr,width,height); Bitmap newBitmap = Bitmap.createBitmap(width,height,Bitmap.Config.RGB_565); newBitmap.setPixels(pixArr,0,width,0,0,width,height); ivNew.setImageBitmap(newBitmap); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); public native int[] gray(int [] pix,int w,int h);}
说明一下,这里的gray函数是我想添加的native函数,教大家一个快速生成jni接口的方法:将光标放在gray上,按住Alt+Enter,选择Create fuction将自动生成Jni接口函数,怎么样帅不帅,还傻傻的自己写或者javac编译么,哈哈,智能改变工作。
还有一点需要说明的是System.loadlibrary(opencv_java3),在高版本android设备上是不需要的,但是如果低版本就必须写上,而且是在调用opencv_java3的jni库前面写,具体原因不知道,这是我在调试android4.2版本的时候遇到的,都是血与泪的教训啊。
3、编写native-lib.cpp
#include #include #include #include #include #include using namespace cv;extern "C" JNIEXPORT jstring JNICALLJava_com_test_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str());}extern "C"JNIEXPORT jintArray JNICALLJava_com_test_MainActivity_gray(JNIEnv *env, jobject instance, jintArray pix_, jint w, jint h) { jint *pix = env->GetIntArrayElements(pix_, NULL); if (pix == NULL) { return 0; }#if 1 //将c++图片转成Opencv图片 Mat imgData(h, w, CV_8UC4, (unsigned char *) pix); 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; }#endif int size = w * h; jintArray result = env->NewIntArray(size); env->SetIntArrayRegion(result, 0, size, pix); env->ReleaseIntArrayElements(pix_, pix, 0); return result;}
切记一定要加上opencv2/opencv.hpp和using namespace cv;
好了到这里已经全部完成了。下面来看看效果:
如果还有问题的话可以参考我的代码:点我下载
更多相关文章
- android中打开本地doc、pdf、ppt、text等文件功能的实现
- Android封装BaseActivity
- android音乐播放器怎么搜索SD卡上的音乐文件
- Android读取手机文件列表
- android刷字体教程
- 【WEB服务器】i-jetty环境搭配与编译 .
- 在Android中修改快捷方式的图标
- Android-常用代码-36片段
- 常用的 Android(安卓)Studio 快捷键