1

我目前正在编写一个 JNI 加速器库来替换某些系统(Linux x64 和 macOS)上的 Java 方法。

我有一个用JavaCV 3.4.2用 Kotlin/Java 编写的工作代码

我创建了一个 JNI 库,它执行相同的工作以避免 JVM 和 JNI 之间的多次来回。

例子:

Kotlin 端(JVM + JavaCV)没有加速:

override fun process(image: Mat): FeaturesDetectorResult {
    val faceDetection = Dlib.faceDetection(image)
    ...
}

JNI加速器部分:

科特林

@ByVal
protected external fun Process(imagePtr: Long, lines: List<opencv_core.Rect>): opencv_core.Mat?;

// method of class overriding the native method
override fun process(image: opencv_core.Mat): FeaturesDetectorResult {
    val lines = ArrayList<opencv_core.Rect>()
    val rotatedMat = Process(image.address(), lines)
    return FeaturesDetectorResult(rotatedMat, lines)
}

C++

JNIEXPORT jlong JNICALL Java_fr_tessi_bmd_image_accel_MserFeaturesDetectorNative_Process
  (JNIEnv *env, jobject self, jlong imagePtr, jobject list) {

在我的 C++ 方法结束时,我被困在将本机cv::Mat转换为其 Java 对应项opencv_core.Mat(不存在具有本机地址的构造函数)。

我查看了 javacpp 生成的源代码,似乎本机对象被视为jlong. 我以这种方式进行的所有测试都会导致崩溃。

有人知道如何org.bytedeco.javacpp使用自制的 JNI 库来回传递对象吗?

编辑:

我找到了一个部分解决方法来创建opencv_mat.Matcv::Mat

//Safety checks removed for simplicity
#define ptr_to_jlong(a) ((jlong)(uintptr_t)(a))
Mat* toReturnToJava;
jclass pointerClass = env->FindClass("org/bytedeco/javacpp/Pointer"); 
jfieldID addressFld = env->GetFieldID(pointerClass, "address", "J");
jobject pointerObj = env->AllocObject(pointerClass);
env->SetLongField(pointerObj, addressFld, ptr_to_jlong(toReturnToJava));

将在 Java 端将返回值声明为 时Mat返回给 Java 。jlongopencv.Mat

相同类型的代码似乎不适用于 Rect(我使用了构造函数 Rect(x, y, w, h) 代替)。

4

0 回答 0