电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

基于Android studio3.6的JNI教程之ncnn之語義分割ENet

瀏覽:94日期:2022-09-25 10:31:39

代碼鏈接:

https://github.com/watersink/enet-as-linux

本代碼可以在模擬器下進行跑。

環境:

Android studio 3.6

Sdk:android10 api 29

Ndk:r15c

Ncnn:20200226

Opencv:Opencv3.4.1 android sdk

Linux下的代碼測試:

mkdir buildcd buildcmake ..make./enet

運行效果,

基于Android studio3.6的JNI教程之ncnn之語義分割ENet

Android開始:

(1)新建工程,

New->New Project->選擇Native c++ ->工程名enet->c++11

(2)app/src/cpp下面增加opencv和ncnn的頭文件,include

基于Android studio3.6的JNI教程之ncnn之語義分割ENet

(3)app/src/main下面增加ncnn 和opencv的靜態庫文件和動態庫文件,

基于Android studio3.6的JNI教程之ncnn之語義分割ENet

(4)app/src/main下面增加模型文件assets

基于Android studio3.6的JNI教程之ncnn之語義分割ENet

(5)修改布局文件,app/src/main/res/layout/ activity_main.xml

<?xml version='1.0' encoding='utf-8'?><RelativeLayout xmlns:android='http://schemas.android.com/apk/res/android' xmlns:app='http://schemas.android.com/apk/res-auto' xmlns:tools='http://schemas.android.com/tools' android:layout_width='match_parent' android:layout_height='match_parent' tools:context='.MainActivity'> <LinearLayout android: android:layout_alignParentBottom='true' android:layout_width='match_parent' android:layout_height='wrap_content' android:orientation='horizontal'> <Button android: android:layout_weight='1' android:layout_width='0dp' android:layout_height='wrap_content' android:text='選圖'/> <Button android: android:layout_weight='1' android:layout_width='0dp' android:layout_height='wrap_content' android:text='分割'/> </LinearLayout> <ImageView android: android:layout_width='match_parent' android:layout_height='match_parent' android:layout_above='@id/btn_ll' android:layout_alignParentTop='true' android:layout_marginTop='1dp' android:layout_marginBottom='-1dp' /></RelativeLayout>

(6) app/src/main/java/com/example/enet增加ENET類,

public class ENET { public native boolean Init(byte[] param, byte[] bin); public native float[] Process(Bitmap bitmap); // Used to load the ’native-lib’ library on application startup. static { System.loadLibrary('ENET'); }}

(7) app/src/main/cpp/enet-jni.cpp實現其jni方法,

extern 'C'JNIEXPORT jboolean JNICALLJava_com_example_enet_ENET_Init(JNIEnv *env, jobject thiz, jbyteArray param, jbyteArray bin) { // TODO: implement Init() ncnn::Mat ncnn_param; ncnn::Mat ncnn_bin; // init param { int len = env->GetArrayLength(param); ncnn_param.create(len, (size_t) 1u); env->GetByteArrayRegion(param, 0, len, (jbyte *) ncnn_param); } // init bin { int len = env->GetArrayLength(bin); ncnn_bin.create(len, (size_t) 1u); env->GetByteArrayRegion(bin, 0, len, (jbyte *) ncnn_bin); } ncnn_net = new ENET(ncnn_param,ncnn_bin); return JNI_TRUE;}extern 'C'JNIEXPORT jfloatArray JNICALLJava_com_example_enet_ENET_Process(JNIEnv *env, jobject thiz, jobject bitmap) { // TODO: implement Process() // ncnn from bitmap ncnn::Mat in; { AndroidBitmapInfo info; AndroidBitmap_getInfo(env, bitmap, &info); int width = info.width; int height = info.height; if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) return NULL; void* indata; AndroidBitmap_lockPixels(env, bitmap, &indata); // 把像素轉換成data,并指定通道順序 // 因為圖像預處理每個網絡層輸入的數據格式不一樣一般為300*300 128*128等等所以這類需要一個resize的操作可以在cpp中寫,也可以是java讀入圖片時有個resize操作 //in = ncnn::Mat::from_pixels_resize((const unsigned char*)indata, ncnn::Mat::PIXEL_RGBA2RGB, width, height,300,300); in = ncnn::Mat::from_pixels(static_cast<const unsigned char *>(indata), ncnn::Mat::PIXEL_RGBA2BGR, width, height); // 下面一行為debug代碼 __android_log_print(ANDROID_LOG_DEBUG, 'ENetJniIn', 'enet_process_has_input1, in.w: %d; in.h: %d in.c:%d ', in.w, in.h,in.c); //AndroidBitmap_unlockPixels(env, bitmap); } { ncnn::Mat out = ncnn_net->process(in); __android_log_print(ANDROID_LOG_DEBUG, 'ENetJniIn', 'enet_process_has_output, in.w: %d; in.h: %d in.c:%d ', out.w, out.h,out.c); int output_wsize = out.w; int output_hsize = out.h; //輸出整理 float *output[output_wsize * output_hsize]; // float類型 for(int i = 0; i< out.h; i++) { for (int j = 0; j < out.w; j++) { output[i*output_wsize + j] = &out.row( i)[j]; } } //建立float數組 長度為 output_wsize * output_hsize,如果只是ouput_size相當于只有一行的out的數據那就是一個object檢測數據 jfloatArray jOutputData = env->NewFloatArray(output_wsize * output_hsize); if (jOutputData == nullptr) return nullptr; env->SetFloatArrayRegion(jOutputData, 0, output_wsize * output_hsize,reinterpret_cast<const jfloat *>(*output)); return jOutputData; }}

(8) app/src/main/java/com/example/enet中MainActivity做具體的調用實現,

public class MainActivity extends AppCompatActivity { private ENET enet = new ENET(); //java接口實例化 下面直接利用java函數調用NDK c++函數 private Bitmap yourSelectedImage = null; private static final int SELECT_IMAGE = 1; private static final String TAG = MainActivity.class.getName(); private ImageView show_image; private boolean load_result = false; private int[] ddims = {1, 3, 512, 288}; //這里的維度的值要和train model的input 一一對應 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { initENet();//初始化模型 Log.e('MainActivity', 'initENet ok'); } catch (IOException e) { Log.e('MainActivity', 'initENet error'); } init_view();//檢測+view畫圖 } // initialize view private void init_view() { show_image = (ImageView) findViewById(R.id.show_image); Button use_photo = (Button) findViewById(R.id.use_photo); use_photo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Intent i = new Intent(Intent.ACTION_PICK); i.setType('image/*'); startActivityForResult(i, SELECT_IMAGE); } }); Button detect_photo = (Button) findViewById(R.id.detect_photo); detect_photo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { if (yourSelectedImage == null) return; predict_image(yourSelectedImage); } }); } private void initENet() throws IOException { byte[] param = null; byte[] bin = null; { //用io流讀取二進制文件,最后存入到byte[]數組中 InputStream assetsInputStream = getAssets().open('enet_512288.param.bin');// param: 網絡結構文件 int available = assetsInputStream.available(); param = new byte[available]; int byteCode = assetsInputStream.read(param); assetsInputStream.close(); } { //用io流讀取二進制文件,最后存入到byte上,轉換為int型 InputStream assetsInputStream = getAssets().open('enet_512288.bin');//bin: model文件 int available = assetsInputStream.available(); bin = new byte[available]; int byteCode = assetsInputStream.read(bin); assetsInputStream.close(); } load_result = enet.Init(param, bin);// 再將文件傳入java的NDK接口(c++ 代碼中的init接口 ) Log.d('load model', 'ENet_load_model_result:' + load_result); } @Override protected 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 bitmap = decodeUri(selectedImage); Bitmap rgba = bitmap.copy(Bitmap.Config.ARGB_8888, true); // resize to 512x288 yourSelectedImage = Bitmap.createScaledBitmap(rgba, ddims[2], ddims[3], false); show_image.setImageBitmap(yourSelectedImage); } } catch (FileNotFoundException e) { Log.e('MainActivity', 'FileNotFoundException'); return; } } } private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException { // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o); // The new size we want to scale to final int REQUIRED_SIZE = 600; // 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 inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; return BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2); } // predict image private void predict_image(Bitmap bmp) { // picture to float array Bitmap rgba = bmp.copy(Bitmap.Config.ARGB_8888, true); // resize Bitmap input_bmp = Bitmap.createScaledBitmap(rgba, ddims[2], ddims[3], false); try { // Data format conversion takes too long // Log.d('inputData', Arrays.toString(inputData)); long start = System.currentTimeMillis(); // get predict result float[] result = enet.Process(input_bmp); // time end long end = System.currentTimeMillis(); Log.d(TAG, 'origin predict result:' + Arrays.toString(result)); long time = end - start; Log.d('result length', 'length of result: ' + String.valueOf(result.length)); // 畫布配置 Canvas canvas = new Canvas(input_bmp); //圖像上畫矩形 Paint paint = new Paint(); //continue to draw rect Log.d(TAG, 'result :' + result.length); Log.d(TAG, 'result :' + Arrays.toString(result)); for(int num = 0; num < result.length; num++){ // 畫框 int row =num%ddims[2]; int col = num/ddims[2]; if (result[num]==1){ paint.setColor(Color.RED); paint.setStyle(Paint.Style.STROKE);//不填充 canvas.drawCircle(row, col, 1, paint); } if (result[num]==2){ paint.setColor(Color.BLUE); paint.setStyle(Paint.Style.STROKE);//不填充 canvas.drawCircle(row, col, 1, paint); } if (result[num]==3){ paint.setColor(Color.GREEN); paint.setStyle(Paint.Style.STROKE);//不填充 canvas.drawCircle(row, col, 1, paint); } } show_image.setImageBitmap(input_bmp); } catch (Exception e) { e.printStackTrace(); } }}

(9) app/src/main/cpp下面修改CMakeLists

cmake_minimum_required(VERSION 3.4.1)include_directories(include)file(GLOB ENET_SRC *.h *.cpp)set(ENET_COMPILE_CODE ${ENET_SRC})add_library(libopencv_java3 SHARED IMPORTED)set_target_properties(libopencv_java3 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libopencv_java3.so) add_library(libncnn STATIC IMPORTED )set_target_properties(libncnn PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libncnn.a)add_library( # Sets the name of the library. ENET ## 為生成.so的文字最好直接和.c名字一樣,需要更改 # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). ${ENET_COMPILE_CODE})##cpp文件的namefind_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log )target_link_libraries( # Specifies the target library. ENET libncnn libopencv_java3 jnigraphics android # Links the target library to the log library # included in the NDK. ${log-lib} )

(10) app/src/下面修改build.gradle,增加下面的設置,

externalNativeBuild { cmake { arguments '-DANDROID_TOOLCHAIN=clang' cFlags '-fopenmp -O2 -fvisibility=hidden -fomit-frame-pointer -fstrict-aliasing -ffunction-sections -fdata-sections -ffast-math ' cppFlags '-fopenmp -O2 -fvisibility=hidden -fvisibility-inlines-hidden -fomit-frame-pointer -fstrict-aliasing -ffunction-sections -fdata-sections -ffast-math ' arguments '-DANDROID_STL=c++_shared', '-DANDROID_CPP_FEATURES=rtti exceptions' cppFlags '' cppFlags '-std=c++11' cppFlags '-frtti' cppFlags '-fexceptions' } } ndk { abiFilters ’armeabi-v7a’// , ’arm64-v8a’ //,’x86’, ’x86_64’, ’armeabi’ stl 'gnustl_static' }

整體目錄結構:

基于Android studio3.6的JNI教程之ncnn之語義分割ENet

最終效果:

基于Android studio3.6的JNI教程之ncnn之語義分割ENet

總結

到此這篇關于基于Android studio3.6的JNI教程之ncnn之語義分割ENet的文章就介紹到這了,更多相關android studio 語義分割enet內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Android
相關文章:
主站蜘蛛池模板: 北京网站建设公司_北京网站制作公司_北京网站设计公司-北京爱品特网站建站公司 | 北京森语科技有限公司-模型制作专家-展览展示-沙盘模型设计制作-多媒体模型软硬件开发-三维地理信息交互沙盘 | 电缆接头_防水接头_电缆防水接头 - 乐清市新豪电气有限公司 | 螺旋压榨机-刮泥机-潜水搅拌机-电动泥斗-潜水推流器-南京格林兰环保设备有限公司 | 济南展厅设计施工_数字化展厅策划设计施工公司_山东锐尚文化传播有限公司 | 昆明化妆培训-纹绣美甲-美容美牙培训-昆明博澜培训学校 | 深圳善跑体育产业集团有限公司_塑胶跑道_人造草坪_运动木地板 | 螺旋丝杆升降机-SWL蜗轮-滚珠丝杆升降机厂家-山东明泰传动机械有限公司 | 盘煤仪,盘料仪,盘点仪,堆料测量仪,便携式激光盘煤仪-中科航宇(北京)自动化工程技术有限公司 | 无锡网站建设-做网站-建网站-网页设计制作-阿凡达建站公司 | 泰兴市热钻机械有限公司-热熔钻孔机-数控热熔钻-热熔钻孔攻牙一体机 | 振动筛,震动筛,圆形振动筛,振动筛价格,振动筛厂家-新乡巨宝机电 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 | 呼末二氧化碳|ETCO2模块采样管_气体干燥管_气体过滤器-湖南纳雄医疗器械有限公司 | 成都治疗尖锐湿疣比较好的医院-成都治疗尖锐湿疣那家医院好-成都西南皮肤病医院 | 灌装封尾机_胶水灌装机_软管灌装封尾机_无锡和博自动化机械制造有限公司 | 警用|治安|保安|不锈钢岗亭-售货亭价格-垃圾分类亭-移动厕所厂家-苏州灿宇建材 | 喷码机,激光喷码打码机,鸡蛋打码机,手持打码机,自动喷码机,一物一码防伪溯源-恒欣瑞达有限公司 | 全自动定氮仪-半自动凯氏定氮仪厂家-祎鸿仪器 | 防弹玻璃厂家_防爆炸玻璃_电磁屏蔽玻璃-四川大硅特玻科技有限公司 | 2025黄道吉日查询、吉时查询、老黄历查询平台- 黄道吉日查询网 | 不锈钢电动球阀_气动高压闸阀_旋塞疏水调节阀_全立阀门-来自温州工业阀门巨头企业 | 窖井盖锯圆机_锯圆机金刚石锯片-无锡茂达金刚石有限公司 | 锥形螺带干燥机(新型耙式干燥机)百科-常州丰能干燥工程 | 丝印油墨_水性油墨_环保油墨油漆厂家_37国际化工 | 谷梁科技| 美国HASKEL增压泵-伊莱科elettrotec流量开关-上海方未机械设备有限公司 | SDI车窗夹力测试仪-KEMKRAFT方向盘测试仪-上海爱泽工业设备有限公司 | 酒吧霸屏软件_酒吧霸屏系统,酒吧微上墙,夜场霸屏软件,酒吧点歌软件,酒吧互动游戏,酒吧大屏幕软件系统下载 | 膜结构停车棚-自行车棚-膜结构汽车棚加工安装厂家幸福膜结构 | 本安接线盒-本安电路用接线盒-本安分线盒-矿用电话接线盒-JHH生产厂家-宁波龙亿电子科技有限公司 | 电竞馆加盟,沈阳网吧加盟费用选择嘉棋电竞_售后服务一体化 | 工业电炉,台车式电炉_厂家-淄博申华工业电炉有限公司 | 纳米二氧化硅,白炭黑,阴离子乳化剂-臻丽拾科技 | 学习安徽网| 泰兴市热钻机械有限公司-热熔钻孔机-数控热熔钻-热熔钻孔攻牙一体机 | 刹车盘机床-刹车盘生产线-龙口亨嘉智能装备 | 塑木弯曲试验机_铜带拉伸强度试验机_拉压力测试台-倾技百科 | 基业箱_环网柜_配电柜厂家_开关柜厂家_开关断路器-东莞基业电气设备有限公司 | 青州开防盗门锁-配汽车芯片钥匙-保险箱钥匙-吉祥修锁店 | 乙炔气体报警装置|固定式氯化氢检测仪|河南驰诚电气百科 | 焊锡丝|焊锡条|无铅锡条|无铅锡丝|无铅焊锡线|低温锡膏-深圳市川崎锡业科技有限公司 |