Java Android JNI-加载dlib形状预测器文件 使用普通VisualStudioC++项目,我使用以下代码将形状预测器文件加载到DLIB SpuleSubor变量: dlib::shape_predictor spredictor; //calling the file with a relative path dlib::deserialize("sp68fl.dat") >> spredictor;
然而,在Android中使用JNI,我从我的活动中加载这个文件,并将其作为字节数组传递。所以我有一个jbyteArray,它是shape_predictor_68_face_landmarks.dat文件,用于Dlib人脸检测 我发现了一个重载的反序列化方法(serializable_type&item,std::istream&in),但不知道如何使用它(可能我必须将jbyteArray转换为这个istream) 如何从jbyteArray将此文件加载到dlib::shape_预测器 编辑: 这就是我迄今为止所尝试的:Java Android JNI-加载dlib形状预测器文件 使用普通VisualStudioC++项目,我使用以下代码将形状预测器文件加载到DLIB SpuleSubor变量: dlib::shape_predictor spredictor; //calling the file with a relative path dlib::deserialize("sp68fl.dat") >> spredictor;,java,android,android-ndk,java-native-interface,dlib,Java,Android,Android Ndk,Java Native Interface,Dlib,然而,在Android中使用JNI,我从我的活动中加载这个文件,并将其作为字节数组传递。所以我有一个jbyteArray,它是shape_predictor_68_face_landmarks.dat文件,用于Dlib人脸检测 我发现了一个重载的反序列化方法(serializable_type&item,std::istream&in),但不知道如何使用它(可能我必须将jbyteArray转换为这个istream) 如何从jbyteArray将此文件加载到dlib::shape_预测器 编辑:
#include <jni.h>
#include <dlib\image_processing.h>
#include <dlib\image_processing\frontal_face_detector.h>
#include <dlib\image_processing\render_face_detections.h>
#include <dlib\image_processing\generic_image.h>
#include <dlib\image_processing\full_object_detection.h>
#include <dlib\opencv.h>
#include <dlib\geometry.h>
#include <dlib\image_transforms.h>
#include <dlib\serialize.h>
#include <dlib\gui_widgets.h>
#include <dlib\image_io.h>
extern "C" {
struct membuf : std::streambuf
{
membuf(char* begin, char* end) {
this->setg(begin, begin, end);
}
};
JNIEXPORT jstring JNICALL
Java_br_edu_infnet_test16_MainActivity_stringFromJNI(JNIEnv *env, jobject daobj,
jbyteArray fileBytes,
jint fileSize) {
dlib::shape_predictor spredictor;
jboolean isCopy = true;
jbyte * a = env->GetByteArrayElements(fileBytes, &isCopy);
char* teste = (char *) a;
std::ifstream in;
//stream is not loading? stream size is zero after read method
in.read(teste, fileSize);
try {
dlib::deserialize(spredictor, in);
} catch (dlib::serialization_error &serializationError) {
//deserialize method fails. Dlib error: deserializing object of type int
std::cout << "ERROR: " << serializationError.what();
}
in.close();
env->ReleaseByteArrayElements(fileBytes, a, JNI_ABORT);
const char *cppString = "Diego";
jstring javaString = env->NewStringUTF(cppString);
return javaString;
}
}
看起来问题在于ifstream没有使用变量teste加载,teste是一个char指针。这个文件有大约100MB大小。
你可以在C++中打开文件。问题是,在Android中,您需要文件名的完整路径,而不是您可以依赖的当前目录。使用java API来准备完整的路径,并将字符串传递给C++而不是发送缓冲区,可能会更容易。
如果不可能,您必须将jbyteArray转换为char[](请参阅),然后创建一个std::istream。我也遇到了同样的问题,我只授予了在存储上读写的权限,并且工作正常。 尝试加载项清单: 并要求许可 requestPermissions(新字符串[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},REQUEST_permission)
我将文件保存在根目录下,并使用绝对路径定位。谢谢,Alex。我无法使用istream或ifstream使反序列化程序工作。我曾尝试将istream与建议的membuf结构一起使用,但没有成功。
package br.edu.infnet.test16;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
// tv.setText(stringFromJNI());
byte[] buffer = null;
try {
InputStream inputStream = getAssets().open("sp68fl.dat");
int size = inputStream.available();
buffer = new byte[size];
inputStream.read(buffer);
inputStream.close();
stringFromJNI(buffer, size);
} catch (Exception e) {
e.printStackTrace();
Log.e("ERRO", "DEU EEEEEEERRO: " + e.getMessage());
}
}
public native String stringFromJNI(byte[] fileBytes, int fileSize);
}