下面介绍在AS中集成dlib,通过CMakeList.txt方式
建议看这个GitHub - bookzhan/bzdlib: dlib demo for android,face tracker,face landmark
一、新建工程1. 在创建工程的对话框中选择Include C++ support,如下图所示:
创建工程
2. 一直点击Next,直到最后一步。选择Exception Support(-fexceptions)和Runtime Type Information Support(-frtti),便于出错时的调试。如下图所示:
调试支持
为了防止错误提示:Installed Build Tools revision 32.0.0 is corrupted. Remove and install again using the SDK Manager.
SDK选择30
Project/build.gradle增加阿里云
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
maven{url "https://maven.aliyun.com/repository/central"}
maven{url "https://maven.aliyun.com/repository/public"}
maven{url "https://maven.aliyun.com/repository/google"}
maven{url "https://maven.aliyun.com/repository/gradle-plugin"}
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.1"
}
}
allprojects {
repositories {
maven{url "https://maven.aliyun.com/repository/central"}
maven{url "https://maven.aliyun.com/repository/public"}
maven{url "https://maven.aliyun.com/repository/google"}
maven{url "https://maven.aliyun.com/repository/gradle-plugin"}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Module/build.gradle设置编译的sdk
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.hc.facetest2"
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ''
abiFilters "armeabi-v7a", "arm64-v8a", "x86_64", "x86"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.10.2'
}
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
- 配置文件
将opencv或dlib-19.22解压后整个文件夹,拷贝到main/cpp文件夹下面
AndroidManifest.xml文件,打开摄像头,和文件读写权限
package="com.tzutalin.dlibtest">
android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
android:name=".MainActivity_" android:configChanges="orientation|screenSize" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar">
- 配置CMakeLists文件
Main/cpp/CMakeList.txt文件
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.10.2)
project("cmaketest2")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
include(./dlib-19.22/dlib/cmake)
# Include headers
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# links the target library to the log library
# included in the NDK.
dlib ${log-lib} )
增加的dlib库名在dlib-19.22dlibCMakeList.txt文件夹找
project(dlib) 这个文件夹名就是
四、配置app/build.gradle1. 添加CPU架构的支持
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
如下:
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.hc.facetest2"
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ''
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.10.2'
}
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
#includeMain/java/com/hc/facetest2/MainActivy.java#include #include "dlib/dnn.h" #include "dlib/clustering.h" #include "dlib/string.h" #include "dlib/image_io.h" #include "dlib/image_processing/frontal_face_detector.h" using namespace dlib; using namespace std; template class, int, typename> class block, int N, template class BN, typename SUBNET> using residual = add_prev1 >>; template class, int, typename> class block, int N, template class BN, typename SUBNET> using residual_down = add_prev2>>>>>; template class BN, int stride, typename SUBNET> using block = BN >>>>; template using ares = relu >; template using ares_down = relu >; template using alevel0 = ares_down<256, SUBNET>; template using alevel1 = ares<256, ares<256, ares_down<256, SUBNET>>>; template using alevel2 = ares<128, ares<128, ares_down<128, SUBNET>>>; template using alevel3 = ares<64, ares<64, ares<64, ares_down<64, SUBNET>>>>; template using alevel4 = ares<32, ares<32, ares<32, SUBNET>>>; using anet_type = loss_metric >>>>>>>>>>>; //正向人脸检测器 frontal_face_detector detector; // We will also use a face landmarking model to align faces to a standard pose: (see face_landmark_detection_ex.cpp for an introduction) shape_predictor sp; // And finally we load the DNN responsible for face recognition.#生成面部识别器 anet_type net; bool isInit = 0; int i=0; matrix img; struct membuf : std::streambuf { membuf(char* begin, char* end) { this->setg(begin, begin, end); } }; string getstring(const int n) { std::stringstream newstr; newstr< GetStringUTFChars(lString, NULL); if (lStringTmp == NULL) return NULL; str = lStringTmp; env->ReleaseStringUTFChars(lString, lStringTmp); return str; } void initLib(){ if(!isInit){ deserialize("/sdcard/Android/data/com.hc.facetest2/files/shape_predictor_68_face_landmarks.dat") >> sp; deserialize("/sdcard/Android/data/com.hc.facetest2/files/dlib_face_recognition_resnet_model_v1.dat") >> net; //load_image(img, imagenamePath); load_image(img, "/sdcard/Android/data/com.hc.facetest2/files/6.jpg"); isInit = 1; } } extern "C" JNIEXPORT jstring JNICALL Java_com_hc_facetest2_MainActivity_stringFromJNI( JNIEnv* env, jobject ) { i+=1; std::string hello = "Hello from C++" +getstring(i); return env->NewStringUTF(hello.c_str()); } extern "C" JNIEXPORT jfloatArray JNICALL Java_com_hc_facetest2_MainActivity_getLibFacevalue( JNIEnv* env, jobject, jstring imagePath) { initLib(); //正向人脸检测器 detector = get_frontal_face_detector(); //string image = convertJStrToString(env, imagePath); // and centered. 图片放大到150x150,旋转居中。人脸对齐 std::vector > faces; for (auto face : detector(img)) { auto shape = sp(img, face); matrix face_chip; extract_image_chip(img, get_face_chip_details(shape, 150, 0.25), face_chip); faces.push_back(move(face_chip)); } if (faces.size() == 0) { cout << "No faces found in image!" << endl; return NULL; } //提取特征 - 图像中的68个关键点转换为128D面部描述符,其中同一人的图片被映射到彼此附近,并且不同人的图片被远离地映射。 std::vector > face_descriptors = net(faces); if (face_descriptors.size() > 0) { float dx[128]{}; matrix xx = face_descriptors[0]; //遍历行 for (size_t _rowIdx = 0; _rowIdx < xx.nr(); _rowIdx++) { //遍历列,由于它只有128行,1列,所以不遍历列 // for (size_t _colIdx = 0; _colIdx < xx.nc(); _colIdx++) // { dx[_rowIdx] = xx(_rowIdx, 0); //} } jfloatArray faceFeatureArray = env->NewFloatArray(128); env->SetFloatArrayRegion(faceFeatureArray, 0, 128, dx); return faceFeatureArray; } return NULL; }
package com.hc.facetest2;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.os.Build;
import android.os.Bundle;
import android.widget.TextView;
import com.hc.facetest2.databinding.ActivityMainBinding;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup. static{ System.loadLibrary("native-lib"); } private static Handler handler=new Handler(); private ActivityMainBinding binding; private Button testBtn; TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); // Example of a call to a native method tv = binding.sampleText; // tv = findViewById(R.id.sample_text); tv.setText(stringFromJNI()); testBtn = binding.buttonTest;// = findViewById(R.id.button_test); testBtn.setonClickListener(v -> { getvalue(); }); } @Override protected void onResume() { super.onResume(); requestPermission(); } public void getvalue(){ tv.setText("开始计时"); Log.i("MainActivity","点击按钮2"); new Thread("Thread#1") { @Override public void run() { //tv.setText(stringFromJNI()); long begintime = System.currentTimeMillis(); float[] xxs = getLibFacevalue(""); for (float xx : xxs) { Log.i("MainActivity", String.valueOf(xx)); } handler.post(new Runnable() { @Override public void run() { tv.setText("用时"+(System.currentTimeMillis() - begintime) / 1000+""+xxs); } }); } }.start(); } private boolean requestPermission() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1); return true; } public native String stringFromJNI(); public native float[] getLibFacevalue(String imagePath);
}
六、配置测试环境将下面两个文件(Index of /files),以及一个名叫6.jpg的人脸图片,拷贝到虚拟机设备sd卡,根目录中。
dlib_face_recognition_resnet_model_v1.dat
shape_predictor_68_face_landmarks.dat
手工拷贝会出错,应该用adb工具拷贝命令格式如下:
多设备查询
>adb devices
>adb -s 2557fe09 push d:/pics/6.jpg /sdcard/ 上传文件命令
查看模拟器的文件夹
#adb shell 单设备控制端
#adb -s 2557fe09 shell 多设备控制端
2021-12-28 14:49:05.498 23866-23866/com.hc.facetest2 I/System.out: -0.09826109
2021-12-28 14:49:05.498 23866-23866/com.hc.facetest2 I/System.out: 0.10588784
2021-12-28 14:49:05.498 23866-23866/com.hc.facetest2 I/System.out: 0.03188623
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)