Opencv将Mat从Android传递到JNI错误

Posted

技术标签:

【中文标题】Opencv将Mat从Android传递到JNI错误【英文标题】:Opencv passing Mat from Android to JNI error 【发布时间】:2016-03-29 07:56:01 【问题描述】:

我查看了所有内容,但我不明白为什么会收到致命信号 11。

Java端:

mRgba = inputFrame.rgba();

String nativeTesting = mNativeDetector.getFeatures(mRgba);
Log.e(TAG, nativeTesting);    

// In another class
public String getFeatures(Mat image) 
    Log.e("FRAME", " Rows:" +image.rows());    // This correctly returns the number of rows
    String resultMsg = nativeFeatures(mNativeObj, image.getNativeObjAddr());
    return resultMsg;

C++ 方面:

JNIEXPORT jstring JNICALL Java_com_example_myfacedetection_DetectionBasedTracker_nativeFeatures (JNIEnv* env, jclass, jlong image)

LOGD("NativeFeatures enter");

try 
    Mat* frame = (Mat*) image;
//        if (frame.empty())              // This also results in Fatal Signal
//            LOGD("EMPTY FRAME");


    LOGD("Size: %d", frame->rows);

catch(cv::Exception& e)

    LOGD("nativeCreateObject caught cv::Exception: %s", e.what());
    jclass je = env->FindClass("org/opencv/core/CvException");
    if(!je)
        je = env->FindClass("java/lang/Exception");
    env->ThrowNew(je, e.what());



return (env)->NewStringUTF("Hello from JNI !");

我正在尝试计算直方图,但对帧的任何访问都会导致 SegFault。我做错了什么?

【问题讨论】:

您的本机函数只接受一个参数(long),但您从 Java 代码中传递了两个参数。根据您向我们展示的代码,我看不出您如何没有收到 UnsatisfiedLinkError。 JNI 使用 C 链接(无名称修改),因此链接器只寻找 Java_com_example_myfacedetection_DetectionBasedTracker_nativeFeatures 并找到它就好了。 【参考方案1】:

问题

这里最可能的问题是您在 Java 中的本机方法声明(您没有列出)与 JNI 库中的签名不匹配。

你在叫它:

String resultMsg = nativeFeatures(mNativeObj, image.getNativeObjAddr())

所以你可能有(否则 javac 不会编译):

static native String nativeDetect(long thiz, long image);

但是在你的 JNI 库中你有:

JNIEXPORT jstring JNICALL Java_snip_nativeFeatures (JNIEnv* env, jclass, jlong image)

因此,您将 mNativeObj 传递给 image,将其转换为 Mat 并在实际尝试跟踪指针时获取 SIGSEGV。

解决方案

要解决此问题,请更新方法签名以匹配。例如,如果您不需要访问实例,请将静态方法设为 nativeDetect(long image)(并且不要将 mNativeObj 传递给它)。

注意

您有责任确保 Java 和 C/C++ 源文件之间的方法签名匹配。 Unless you have overloaded the native method (two signatures for the same name), the dynamic library loader is only looking for Java_packageName_className_methodName 并且无法判断参数或类型的数量不匹配。

【讨论】:

"你不能重载 JNI 方法。" 当然可以:"对于重载的本机方法,后跟两个下划线(“_”)通过损坏的参数签名“_ (source) 啊,没错,但显然这只适用于方法首先被重载(Java 端)的情况。

以上是关于Opencv将Mat从Android传递到JNI错误的主要内容,如果未能解决你的问题,请参考以下文章

将 YUV_420_888 中的图像从 Android 发送到 OpenCV Mat 中的 JNI 的最有效方法

使用 JNI 传递和返回 OpenCv Mat 对象

使用 jni 将位图从 android 相机传递到 C++

准备位图 byte[] 数据以传递给 jni

Android JNI:将cv :: Mat转换为jbyteArray

Android OpenCV VideoCapture::retrieve(&mat) 导致致命信号 11