前言

这里要演示的是使用Android studio 做APP开发,使用JNI与C++交互的demo。

一.创建工程

1.创建一个Native C++工程。

2.命令工程和指定交互语言。

3.指定C++ 语法版本。

4.创建完成之后打开cpp目录下的CMakeLists.txt文件,这里有IDE默认生成的链接路径。

5.把编译好的opencv库(ndk r21d,android api 24)复制到CPP目录下,添加依赖。(我这里用的OpenCV是nihui大佬的opencv-mobile,因为小(不到20M)而且不用自己编译)。

二.实现代码

1.首先在main.xml布局文件添加控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><ImageViewandroid:id="@+id/image_view"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"></ImageView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/btn_open_images"android:layout_width="0dp"android:text="打开图像"android:layout_height="wrap_content"android:layout_weight="1"></Button><Buttonandroid:id="@+id/btn_gray_image"android:layout_width="0dp"android:text="处理图像"android:layout_height="wrap_content"android:layout_weight="1"></Button><Buttonandroid:id="@+id/btn_send_image"android:layout_width="0dp"android:text="交互图像"android:layout_height="wrap_content"android:layout_weight="1"></Button></LinearLayout>></LinearLayout>

2.添加一个Java类用来写交互接口

2.添加两个接口, 一个是本地读取图像,一个是从资源里面读取图像。
3.MainActivity.java的代码:

package com.dashu.dashuaiip;import java.io.InputStream;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;import java.io.FileNotFoundException;
import java.io.IOException;public class MainActivity<bitmap2> extends Activity
{private static final int SELECT_IMAGE = 1;private ImageView imageView;private Bitmap bitmap = null;private Bitmap temp = null;private Bitmap showImage = null;private Bitmap bitmapCopy = null;private Bitmap dst = null;boolean useGPU = true;DaShuAPI dashuapi = new DaShuAPI();@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);imageView = (ImageView) findViewById(R.id.image_view);//初始化模板try{initTemplate();Log.e("MainActivity", "init template file ok!");} catch (IOException e) {Log.e("MainActivity", "init template file  error!");}//打开图像Button openFile = (Button) findViewById(R.id.btn_open_images);openFile.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View arg0){Intent i = new Intent(Intent.ACTION_PICK);i.setType("image/*");startActivityForResult(i, SELECT_IMAGE);}});Button image_gray = (Button) findViewById(R.id.btn_gray_image);image_gray.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View arg0){if (showImage == null){return;}Bitmap bitmap = dashuapi.grayModel(showImage);imageView.setImageBitmap(bitmap);}});Button read_assets_image = (Button) findViewById(R.id.btn_send_image);read_assets_image.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View arg0){if (showImage == null){return;}Bitmap bitmap = dashuapi.readAssetsImage();imageView.setImageBitmap(bitmap);}});}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data){super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK && null != data) {Uri selectedImage = data.getData();try{if (requestCode == SELECT_IMAGE) {bitmap = decodeUri(selectedImage);showImage = bitmap.copy(Bitmap.Config.ARGB_8888, true);bitmapCopy = bitmap.copy(Bitmap.Config.ARGB_8888, true);imageView.setImageBitmap(bitmap);}}catch (FileNotFoundException e){Log.e("MainActivity", "FileNotFoundException");return;}}}private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException{// Decode image sizeBitmapFactory.Options o = new BitmapFactory.Options();o.inJustDecodeBounds = true;BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);// The new size we want to scale tofinal int REQUIRED_SIZE = 640;// Find the correct scale value. It should be the power of 2.int width_tmp = o.outWidth, height_tmp = o.outHeight;int scale = 1;while (true) {if (width_tmp / 2 < REQUIRED_SIZE|| height_tmp / 2 < REQUIRED_SIZE) {break;}width_tmp /= 2;height_tmp /= 2;scale *= 2;}// Decode with inSampleSizeBitmapFactory.Options o2 = new BitmapFactory.Options();o2.inSampleSize = scale;Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);// Rotate according to EXIFint rotate = 0;try{ExifInterface exif = new ExifInterface(getContentResolver().openInputStream(selectedImage));int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);switch (orientation) {case ExifInterface.ORIENTATION_ROTATE_270:rotate = 270;break;case ExifInterface.ORIENTATION_ROTATE_180:rotate = 180;break;case ExifInterface.ORIENTATION_ROTATE_90:rotate = 90;break;}}catch (IOException e){Log.e("MainActivity", "ExifInterface IOException");}Matrix matrix = new Matrix();matrix.postRotate(rotate);return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);}private void initTemplate() throws IOException{//用io流读取二进制文件,最后存入到byte[]数组中InputStream in = getAssets().open("template.jpg");//模板图像文件int length = in.available();byte[] buffer = new byte[length];in.read(buffer);//转换为BitmapBitmapFactory.Options opts = new BitmapFactory.Options();Bitmap template = BitmapFactory.decodeByteArray(buffer, 0, buffer.length, opts);int width = template.getWidth();int height = template.getHeight();int[] pixArr = new int[width*height];template.getPixels(pixArr,0,width,0,0,width,height);int rt = dashuapi.sendTemplate(pixArr,width,height);}
}

4.jni.cpp的代码

#include <android/bitmap.h>
#include <android/log.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
cv::Mat cv_template;void BitmapToMat2(JNIEnv *env, jobject& bitmap, cv::Mat& mat, jboolean needUnPremultiplyAlpha)
{AndroidBitmapInfo info;void *pixels = 0;cv::Mat &dst = mat;try {CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||info.format == ANDROID_BITMAP_FORMAT_RGB_565);CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);CV_Assert(pixels);dst.create(info.height, info.width, CV_8UC4);if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {cv::Mat tmp(info.height, info.width, CV_8UC4, pixels);if (needUnPremultiplyAlpha) cvtColor(tmp, dst, cv::COLOR_mRGBA2RGBA);else tmp.copyTo(dst);} else {//             info.format == ANDROID_BITMAP_FORMAT_RGB_565cv::Mat tmp(info.height, info.width, CV_8UC2, pixels);cvtColor(tmp, dst, cv::COLOR_BGR5652RGBA);}AndroidBitmap_unlockPixels(env, bitmap);return;} catch (const cv::Exception &e) {AndroidBitmap_unlockPixels(env, bitmap);jclass je = env->FindClass("org/opencv/core/CvException");if (!je) je = env->FindClass("java/lang/Exception");env->ThrowNew(je, e.what());return;} catch (...) {AndroidBitmap_unlockPixels(env, bitmap);jclass je = env->FindClass("java/lang/Exception");env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}");return;}
}void BitmapToMat(JNIEnv *env, jobject& bitmap, cv::Mat& mat) {BitmapToMat2(env, bitmap, mat, false);
}void MatToBitmap2(JNIEnv *env, cv::Mat& mat, jobject& bitmap, jboolean needPremultiplyAlpha){AndroidBitmapInfo info;void *pixels = 0;cv::Mat &src = mat;try {CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||info.format == ANDROID_BITMAP_FORMAT_RGB_565);CV_Assert(src.dims == 2 && info.height == (uint32_t) src.rows &&info.width == (uint32_t) src.cols);CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4);CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);CV_Assert(pixels);if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888){cv::Mat tmp(info.height, info.width, CV_8UC4, pixels);if (src.type() == CV_8UC1){cvtColor(src, tmp, cv::COLOR_GRAY2RGBA);}else if (src.type() == CV_8UC3){cvtColor(src, tmp, cv::COLOR_RGB2RGBA);}else if (src.type() == CV_8UC4){if (needPremultiplyAlpha){cvtColor(src, tmp, cv::COLOR_RGBA2mRGBA);}else{src.copyTo(tmp);}}} else {// info.format == ANDROID_BITMAP_FORMAT_RGB_565cv::Mat tmp(info.height, info.width, CV_8UC2, pixels);if (src.type() == CV_8UC1){cvtColor(src, tmp, cv::COLOR_GRAY2BGR565);}else if (src.type() == CV_8UC3){cvtColor(src, tmp, cv::COLOR_RGB2BGR565);}else if (src.type() == CV_8UC4){cvtColor(src, tmp, cv::COLOR_RGBA2BGR565);}}AndroidBitmap_unlockPixels(env, bitmap);return;}catch (const cv::Exception &e) {AndroidBitmap_unlockPixels(env, bitmap);jclass je = env->FindClass("org/opencv/core/CvException");if (!je) je = env->FindClass("java/lang/Exception");env->ThrowNew(je, e.what());return;} catch (...) {AndroidBitmap_unlockPixels(env, bitmap);jclass je = env->FindClass("java/lang/Exception");env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");return;}
}jobject generateBitmap(JNIEnv *env, uint32_t width, uint32_t height)
{jclass bitmapCls = env->FindClass("android/graphics/Bitmap");jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls,"createBitmap","(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");jstring configName = env->NewStringUTF("ARGB_8888");jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf","(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass,valueOfBitmapConfigFunction, configName);jobject newBitmap = env->CallStaticObjectMethod(bitmapCls,createBitmapFunction,width,height, bitmapConfig);return newBitmap;
}void MatToBitmap(JNIEnv *env, cv::Mat& mat, jobject& bitmap)
{MatToBitmap2(env, mat, bitmap, false);
}extern "C" JNIEXPORT jobject JNICALL
Java_com_dashu_dashuaiip_DaShuAPI_grayModel(JNIEnv *env,jobject, jobject image)
{cv::Mat cv_src,cv_gray;//bitmap转化成matBitmapToMat(env,image,cv_src);cv::cvtColor(cv_src,cv_gray,cv::COLOR_BGRA2GRAY);MatToBitmap(env,cv_gray,image);return image;
}extern "C" JNIEXPORT jobject JNICALLJava_com_dashu_dashuaiip_DaShuAPI_readAssetsImage(JNIEnv *env,jobject)
{jobject dst = generateBitmap(env,cv_template.cols,cv_template.rows);MatToBitmap(env,cv_template,dst);return dst;
}extern "C"
JNIEXPORT int JNICALL
Java_com_dashu_dashuaiip_DaShuAPI_sendTemplate(JNIEnv *env, jobject instance, jintArray pix_, jint w, jint h)
{jint *pix = env->GetIntArrayElements(pix_, NULL);if (pix == NULL){return -1;}//将c++图片转成Opencv图片cv::Mat cv_temp(h, w, CV_8UC4, (unsigned char *) pix);if(cv_temp.empty()){return -2;}cv::cvtColor(cv_temp,cv_template,cv::COLOR_BGRA2BGR);return 0;
}

5.在assets目录下添加一张用来测试(这里是为了测试从资源目录读入图像,可以不用)。

6.运行测试Demo。

Android NDK开发——Android studio使用JNI调用OpenCV处理图像相关推荐

  1. 【学习Android NDK开发】Java通过JNI调用native方法

    参考:Android NDK,sample/hello-jni示例项目 系统环境:Ubuntu 12.04 LTS 32-bit 1.准备工作 打开Eclipse,新建Android项目: Appli ...

  2. Android NDK开发之旅(2):一篇文章搞定Android Studio中使用CMake进行NDK/JNI开发

    Android NDK开发之旅(2):一篇文章搞定android Studio中使用CMake进行NDK/JNI开发 (码字不易,转载请声明出处:http://blog.csdn.NET/andrex ...

  3. [安卓开发笔记二]android Studio通过jni调用C++代码

    [安卓开发笔记二]android Studio通过jni调用C++代码 16/12/11 更新 此博客基于安卓android studio 1.5所写,现在已经有了android studio2.2的 ...

  4. 【Android NDK 开发】Android Studio 使用 CMake 导入动态库 ( 构建脚本路径配置 | 指定动态库查找路径 | 链接动态库 )

    文章目录 I . CMake 引入动态库与静态库区别 II . Android Studio 中 CMake 引入动态库流程 III . 指定动态库查找路径 IV . 链接函数库 V . 完整代码示例 ...

  5. 【Android NDK 开发】Android.mk 配置静态库 ( Android Studio 配置静态库 | 配置动态库与静态库区别 | 动态库与静态库打包对比 )

    文章目录 I . Android Studio 中使用 Android.mk 配置静态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  6. 【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )

    文章目录 I . Android Studio 中使用 Android.mk 配置动态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  7. 【Android NDK 开发】NDK 交叉编译 ( Ubuntu 中交叉编译动态库 | Android Studio 中配置使用第三方动态库 )

    文章目录 I . 动态库 与 静态库 II . 编译动态库 III. Android Studio 使用第三方动态库 IV . Android Studio 关键代码 V . 博客资源 I . 动态库 ...

  8. 安卓逆向_15( 三 ) --- Android NDK 开发【 jni 静态注册、JNI_OnLoad 动态注册】

    Android Studio开发JNI示例:https://blog.csdn.net/wzhseu/article/details/79683045 JNI_动态注册_静态注册.zip : http ...

  9. Android NDK开发: 通过C/C++调用第三方so库

    文章目录 一.编写so库代码 二.安装Android NDK 三.编译so库 3.1 编辑Android.mk 3.2 编辑Application.mk 3.3 编译 四.集成到Android工程中 ...

最新文章

  1. NVIDIA安培架构
  2. Pots(poj-3414)bfs+输出路径
  3. hdu4975 行列和构造矩阵(dp判断唯一性)
  4. POJ-1094 Sorting it All Out
  5. 重新初始化k8s master节点
  6. mysql打开sql语句日志
  7. SAP UI5 Web Component React应用如何在Component之间跳转
  8. 网络编程——sockaddr 与 sockaddr_in
  9. APP视觉稿该怎么切图和标注
  10. mysql 异地备份工具_异地备份简单实现(mysql)
  11. 分布式面试 - 集群部署时的分布式 session 如何实现?
  12. .net core 常见设计模式-IChangeToken
  13. onnx 测试_pytorch onnx onnxruntime tensorrt踩坑 各种问题
  14. Stata:VAR(向量自回归)模型简介
  15. 颜色的前世今生14·RGB拾色器详解
  16. printf如何按二进制格式打印
  17. spark常见转换算子(transformation)的操作
  18. 各星座导演与他们的电影风格【转】]
  19. wpsppt页面卷曲在哪里_2013版ppt怎么制作页面卷曲动画效果_博客
  20. jquery返回上一页,前一页

热门文章

  1. Mybatis执行过程源码分析
  2. 【数学和算法】SVD奇异值分解原理、以及在PCA中的运用
  3. 【c++】0.C++笔记
  4. 基于 Zookeeper 的分布式锁实现
  5. Java 源码学习系列(三)——Integer
  6. 探索 OSGi 框架的组件运行机制
  7. Java反射最佳实践
  8. Java 数组转型和范型
  9. OpenCV之feature2d 模块. 2D特征框架(2)特征描述 使用FLANN进行特征点匹配 使用二维特征点(Features2D)和单映射(Homography)寻找已知物体 平面物体检测
  10. 推荐几个好玩又有难度的编程网站