我目前正在编写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
。我所有的测试都导致崩溃。
任何人都知道如何使用自制的JNI库来回传递org.bytedeco.javacpp
对象吗?
编辑:
我发现了一种从opencv_mat.Mat
创建cv::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));
Mat
作为jlong
返回Java,而Java端将返回值声明为opencv.Mat
。
相同类型的代码似乎不适用于Rect(我改用了构造函数Rect(x,y,w,h))。