1. 程式人生 > 程式設計 >基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

程式碼連結:

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

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

環境:

windows10

Android studio 3.6

Sdk:android10 api 29

Ndk:r15c

Ncnn:20200226

Linux下的程式碼測試:

cd mtcnn_linux/build
cmake ..
make
./mtcnn

如果可以跑通,輸出正確結果,證明mtcnn程式碼的準確性。

實際操作的時候,首先基於linux把c++程式碼除錯通,方便後續的android除錯。

Android進行c++除錯時,使用__android_log_print

函式進行log的輸出,

開發:

(1)工程建立

新建android工程,選擇Native C++,工程名為mtcnn,C++ Standard選擇c++11

(2)資原始檔res修改:

src/main/res/drawable下面隨便複製一張帶有人臉的照片,比如這裡,複製了一張beauty.png

基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

src/main/res/layout下面新加main.xml。

基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

詳細內容,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 
 <LinearLayout
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <Button
   android:id="@+id/buttonImage"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="選圖" />
  <Button
   android:id="@+id/buttonDetect"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="檢測" />
 
 </LinearLayout>
 
 <TextView
  android:id="@+id/infoResult"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="" />
 <ImageView
  android:id="@+id/imageView"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:layout_weight="1" />
</LinearLayout>

(3)增加ncnn的lib檔案

src/main下面新加jniLibs資料夾,加入對應平臺的libncnn.a

基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

(4)增加網路模型檔案assets

在main下面新建assets資料夾,裡面放入mtcnn的3個網路結構的模型檔案。

基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

(5)修改java檔案,

修改src/main/java/com/example/mtcnn下面的MainActivity,

主要操作,包括在onCreate函式中對mtcnn這個類進行初始化。然後監聽buttonImage,buttonDetect按鈕,分別進行實現。

然後在該路徑下增加MTCNN類,主要需要實現的方法如下,

package com.example.mtcnn;
 
public class MTCNN {
 //人臉檢測模型匯入
 public native boolean FaceDetectionModelInit(byte[] det1_param,byte[] det1_bin,byte[] det2_param,byte[] det2_bin,byte[] det3_param,byte[] det3_bin);
 //人臉檢測
 public native int[] FaceDetect(byte[] imageDate,int imageWidth,int imageHeight,int imageChannel);
 
 public native int[] MaxFaceDetect(byte[] imageDate,int imageChannel);
 //人臉檢測模型反初始化
 public native boolean FaceDetectionModelUnInit();
 //檢測的最小人臉設定
 public native boolean SetMinFaceSize(int minSize);
 //執行緒設定
 public native boolean SetThreadsNumber(int threadsNumber);
 //迴圈測試次數
 public native boolean SetTimeCount(int timeCount);
 static {
  System.loadLibrary("mtcnn");
 }
}

(6)修改cpp檔案,

首先將ncnn的include資料夾包含進來。

將模型的3個id.h檔案包含進來,det1.id.h,det2.id.h,det3.id.h

mtcnn_jni.cpp負責對人臉檢測的幾個native方法進行實現。

mtcnn.h,mtcnn.cpp分別定義了一個MTCNN類,然後進行了相關方法的實現。

基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

需要注意,

這裡讀取的模型檔案是通過二進位制的方式讀取的assets下面的模型。所以模型檔案一定要首先進行加密處理(ncnn2mem)。

然後ncnn讀取加密後文件和未加密檔案是有一些區別的。主要包含2個地方。

第一個區別就是匯入模型的區別,詳細的用法看下圖。

基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

未加密的:

load_param
load_model

已經加密的:

load_param_bin
load_model

如果使用load_param,load_model載入已經加密的檔案,返回值為讀取的位元組數

基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能

其餘情況下,正常載入模型會返回0,錯誤返回其他值。

第二個區別就是,就是模型讀取輸入節點和輸出節點的區別,

未加密的:

ex.input("data",in);
ncnn::Mat score_,location_;
ex.extract("prob1",score_);
ex.extract("conv4-2",location_);

已經加密的:

ex.input(det1_param_id::BLOB_data,location_;
ex.extract(det1_param_id::BLOB_prob1,score_);
ex.extract(det1_param_id::BLOB_conv4_2,location_);

(7)修改cpp下面的CMakeLists,增加ncnnlib的引用。

cmake_minimum_required(VERSION 3.4.1)
 
#include標頭檔案目錄
include_directories(include)
#source directory原始檔目錄
file(GLOB MTCNN_SRC *.h
     *.cpp)
set(MTCNN_COMPILE_CODE ${MTCNN_SRC})
#新增ncnn庫
add_library(libncnn STATIC IMPORTED )
set_target_properties(libncnn
 PROPERTIES IMPORTED_LOCATION
  ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libncnn.a)
#編譯為動態庫
add_library(mtcnn SHARED ${MTCNN_COMPILE_CODE})
#新增工程所依賴的庫
find_library( log-lib log )
target_link_libraries( mtcnn
      libncnn
      android
      jnigraphics
      z
      ${log-lib} )

(8)修改app/build.gradle下,defaultConfig裡面加入下面的程式碼,

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人臉檢測mtcnn功能

總結

到此這篇關於基於Android studio3.6的JNI教程之ncnn人臉檢測mtcnn功能的文章就介紹到這了,更多相關android studio3.6 ncnn人臉檢測mtcnn內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!