Android NDK开发——Android studio使用JNI调用OpenCV处理图像
生活随笔
收集整理的這篇文章主要介紹了
Android NDK开发——Android studio使用JNI调用OpenCV处理图像
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
這里要演示的是使用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的代碼:
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处理图像的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ STL容器——序列式容器(arr
- 下一篇: 使用深度学习解决拍照文档复杂背景二值化问