日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Android NDK开发——Android studio使用JNI调用OpenCV处理图像

發(fā)布時(shí)間:2025/3/21 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android NDK开发——Android studio使用JNI调用OpenCV处理图像 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

這里要演示的是使用Android studio 做APP開發(fā),使用JNI與C++交互的demo。

一.創(chuàng)建工程

1.創(chuàng)建一個(gè)Native C++工程。

2.命令工程和指定交互語(yǔ)言。

3.指定C++ 語(yǔ)法版本。

4.創(chuàng)建完成之后打開cpp目錄下的CMakeLists.txt文件,這里有IDE默認(rèn)生成的鏈接路徑。

5.把編譯好的opencv庫(kù)(ndk r21d,android api 24)復(fù)制到CPP目錄下,添加依賴。(我這里用的OpenCV是nihui大佬的opencv-mobile,因?yàn)樾?#xff08;不到20M)而且不用自己編譯)。

二.實(shí)現(xiàn)代碼

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.添加一個(gè)Java類用來(lái)寫交互接口

2.添加兩個(gè)接口, 一個(gè)是本地讀取圖像,一個(gè)是從資源里面讀取圖像。
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流讀取二進(jìn)制文件,最后存入到byte[]數(shù)組中InputStream in = getAssets().open("template.jpg");//模板圖像文件int length = in.available();byte[] buffer = new byte[length];in.read(buffer);//轉(zhuǎn)換為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轉(zhuǎn)化成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++圖片轉(zhuǎn)成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目錄下添加一張用來(lái)測(cè)試(這里是為了測(cè)試從資源目錄讀入圖像,可以不用)。

6.運(yùn)行測(cè)試Demo。

總結(jié)

以上是生活随笔為你收集整理的Android NDK开发——Android studio使用JNI调用OpenCV处理图像的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。