




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】如何基于Androidstudio3.6的JNI教程之ncnn之語(yǔ)義分割ENet
在下給大家分享一下如何基于Androidstudio3.6的JNI教程之ncnn之語(yǔ)義分割ENet,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!Android是一種基于Linux內(nèi)核的自由及開(kāi)放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,由美國(guó)Google公司和開(kāi)放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開(kāi)發(fā)。本代碼可以在模擬器下進(jìn)行跑。環(huán)境:Androidstudio3.6Sdk:android10api29Ndk:r15cNcnn:20200226Opencv:Opencv3.4.1androidsdkLinux下的代碼測(cè)試:mkdirbuildcdbuildcmake..make./enetmkdirbuildcdbuildcmake..make./enet運(yùn)行效果,Android開(kāi)始:(1)新建工程,New->NewProject->選擇Nativec++
->工程名enet->c++11(2)app/src/cpp下面增加opencv和ncnn的頭文件,include(3)app/src/main下面增加ncnn和opencv的靜態(tài)庫(kù)文件和動(dòng)態(tài)庫(kù)文件,(4)app/src/main下面增加模型文件assets(5)修改布局文件,app/src/main/res/layout/activity_main.xml<?xml
version="1.0"
encoding="utf-8"?>
<RelativeLayout
xmlns:android="/apk/res/android"
xmlns:app="/apk/res-auto"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/btn_ll"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/use_photo"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="選圖"/>
<Button
android:id="@+id/detect_photo"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="分割"/>
</LinearLayout>
<ImageView
android:id="@+id/show_image"
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類(lèi),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實(shí)現(xiàn)其jni方法,extern
"C"
JNIEXPORT
jboolean
JNICALL
Java_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
JNICALL
Java_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);
//
把像素轉(zhuǎn)換成data,并指定通道順序
//
因?yàn)閳D像預(yù)處理每個(gè)網(wǎng)絡(luò)層輸入的數(shù)據(jù)格式不一樣一般為300*300
128*128等等所以這類(lèi)需要一個(gè)resize的操作可以在cpp中寫(xiě),也可以是java讀入圖片時(shí)有個(gè)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類(lèi)型
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數(shù)組
長(zhǎng)度為
output_wsize
*
output_hsize,如果只是ouput_size相當(dāng)于只有一行的out的數(shù)據(jù)那就是一個(gè)object檢測(cè)數(shù)據(jù)
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做具體的調(diào)用實(shí)現(xiàn),public
class
MainActivity
extends
AppCompatActivity
{
private
ENET
enet
=
new
ENET();
//java接口實(shí)例化下面直接利用java函數(shù)調(diào)用NDK
c++函數(shù)
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
一一對(duì)應(yīng)
@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();//檢測(cè)+view畫(huà)圖
}
//
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流讀取二進(jìn)制文件,最后存入到byte[]數(shù)組中
InputStream
assetsInputStream
=
getAssets().open("enet_512288.param.bin");//
param:
網(wǎng)絡(luò)結(jié)構(gòu)文件
int
available
=
assetsInputStream.available();
param
=
new
byte[available];
int
byteCode
=
assetsInputStream.read(param);
assetsInputStream.close();
}
{
//用io流讀取二進(jìn)制文件,最后存入到byte上,轉(zhuǎn)換為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));
//
畫(huà)布配置
Canvas
canvas
=
new
Canvas(input_bmp);
//圖像上畫(huà)矩形
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++){
//
畫(huà)框
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下面修改CMakeListscmake_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
relati
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 企業(yè)用工勞動(dòng)合同
- 2025年婁底考貨運(yùn)從業(yè)資格證
- 2025年隴南貨運(yùn)從業(yè)資格仿真考題
- 2025年揭陽(yáng)貨運(yùn)從業(yè)資格證考試內(nèi)容
- 2023年全國(guó)乙卷高考真題生物試卷解析
- 高壓水流清洗機(jī)產(chǎn)業(yè)分析報(bào)告
- 煙草、鹽加工機(jī)械市場(chǎng)分析及競(jìng)爭(zhēng)策略分析報(bào)告
- 浸漬、涂布或包覆處理紡織物競(jìng)爭(zhēng)策略分析報(bào)告
- 《天然藥物化學(xué)成分提取與分離》課程標(biāo)準(zhǔn)
- 上海市裝修設(shè)計(jì)合同范本
- 大樹(shù)移栽合同范本
- 柔性印刷技術(shù)探索-深度研究
- 【正版授權(quán)】 IEC 63310:2025 EN Functional performance criteria for AAL robots used in connected home environment
- 最終版附件1:“跨學(xué)科主題學(xué)習(xí)”教學(xué)設(shè)計(jì)(2025年版)
- 2025年度環(huán)保咨詢與評(píng)估服務(wù)合同范本模板
- 文化差異下的教育國(guó)外的小學(xué)音樂(lè)教育方式探討
- (2024)云南省公務(wù)員考試《行測(cè)》真題及答案解析
- 2022年“正確認(rèn)識(shí)新疆四史”《民族團(tuán)結(jié)鑄牢中華民族共同體意識(shí)》全文解讀
- 靜脈治療護(hù)理技術(shù)操作標(biāo)準(zhǔn)解讀
- 附件25:戶口登記非主項(xiàng)變更、更正告知承諾書(shū)
- 中國(guó)農(nóng)業(yè)銀行資金證明模板
評(píng)論
0/150
提交評(píng)論