【问题标题】:Android JNI - Load dlib shape predictor fileAndroid JNI - 加载 dlib 形状预测器文件
【发布时间】:2019-03-07 16:55:54
【问题描述】:

对于普通的 Visual Studio C++ 项目,我使用以下代码将形状预测器文件加载到 dlib shape_predictor 变量中:

    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 进行人脸检测。

我发现了一个重载的方法 deserialize(serializable_type& item, std::istream& in) 但不知道如何使用它(也许我必须将 jbyteArray 转换为这个 istream)。

如何将此文件从 jbyteArray 加载到 dlib::shape_predictor?

编辑:

这是我迄今为止尝试过的:

#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;
}
}

发送字节数组的活动:

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);
}

看起来问题是 ifstream 没有使用变量 teste 加载,它是一个 char 指针。此文件大小约为 100MB。

【问题讨论】:

    标签: java android android-ndk java-native-interface dlib


    【解决方案1】:

    我遇到了同样的问题,我只获得了在存储上读写的权限,并且可以正常工作。 尝试添加清单:

    并请求许可

    requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_PERMISSION);

    我将文件保存在根目录并使用绝对路径定位。

    【讨论】:

      【解决方案2】:

      您可以在 C++ 中打开该文件。问题是,在 Android 中,您需要文件名的完整路径,而不是您可以依赖的 当前目录。使用 Java API 准备完整路径并将字符串传递给 C++ 而不是发送缓冲区可能更容易。

      如果这不可能,您必须将 jbyteArray 转换为 char[](参见 How to convert jbyteArray to native char* in jni?),然后创建一个 >std::istreamGet an istream from a char*

      【讨论】:

      • 谢谢,亚历克斯。我无法使用 istream 和 ifstream 来让反序列化器工作。我曾尝试将 istream 与建议的 membuf 结构一起使用,但没有奏效。
      猜你喜欢
      • 2019-02-18
      • 2019-07-19
      • 2019-05-28
      • 2018-10-01
      • 2015-03-04
      • 2019-06-06
      • 1970-01-01
      • 2015-12-20
      • 1970-01-01
      相关资源
      最近更新 更多