Android JNI 使用assets加载dlib特征点文件shape_predictor
本文介绍如何在jni中加载apk的assets文件夹中的shape_predictor_68_face_landmarks.dat
在NDK中,google提供了AAssetManager_fromJava来获得Native中对应的AAssetManager,使用它的相关api可以将指针(char*)指向assets文件的内存地址
dlib有一个重载函数deserialize(serializable_type& item, std::istream& in)
,因此我们想要从内存中加载dlib特征定位文件的话,就可以先将char*转换为istream后使用这个函数加载
jni代码
#include <android/asset_manager_jni.h>
struct membuf : std::streambuf {
membuf(char* begin, char* end) {
this->setg(begin, begin, end);
}
};
dlib::shape_predictor pose_model;
extern "C"
JNIEXPORT void JNICALL
Java_com_gavinandre_demo_MainActivity_loadShapePredictor(
JNIEnv *env, jclass type, jobject assetManager, jstring fileName) {
const char *file_name = env->GetStringUTFChars(fileName, nullptr);
env->ReleaseStringUTFChars(fileName, file_name);
//get AAssetManager
AAssetManager *native_asset = AAssetManager_fromJava(env, assetManager);
//open file
AAsset *assetFile = AAssetManager_open(native_asset, file_name, AASSET_MODE_BUFFER);
//get file length
size_t file_length = static_cast<size_t>(AAsset_getLength(assetFile));
char *model_buffer = (char *) malloc(file_length);
//read file data
AAsset_read(assetFile, model_buffer, file_length);
//the data has been copied to model_buffer, so , close it
AAsset_close(assetFile);
//LOGI("asset file length %d", file_length);
//char* to istream
membuf mem_buf(model_buffer, model_buffer + file_length);
std::istream in(&mem_buf);
//load shape_predictor_68_face_landmarks.dat from memory
dlib::deserialize(pose_model,in);
//free malloc
free(model_buffer);
}
在java端使用
//声明jni函数
public native void loadShapePredictor(AssetManager assetManager, String fileName);
//使用方式
loadShapePredictor(getAssets(), "shape_predictor_68_face_landmarks.dat");
参考
https://www.cnblogs.com/willhua/p/9692529.html
https://stackoverflow.com/questions/52610460/android-jni-load-dlib-shape-predictor-file
https://stackoverflow.com/questions/7781898/get-an-istream-from-a-char/7782037#7782037