【问题标题】:Error passing a cv::Mat to JNI using OpenCV on Android在 Android 上使用 OpenCV 将 cv::Mat 传递给 JNI 时出错
【发布时间】:2013-07-04 21:32:02
【问题描述】:

我正在使用 OpenCV 和 JNI 开发一个 Android 项目。

实际上我正在更改面部检测示例。

我遇到的问题是,当我传递一个 cv::Mat 引用时,它会给出一些 strane 输出,但传递得不好。

为了让您了解情况,我的 FdActivity.java 中有这个,这是我的 android 应用程序的主要活动:

 public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    rgb = inputFrame.rgba();
    Mat res = mNativeDetector.process(rgb);
    return res;
}

流程函数是这样的:

public Mat process(Mat rgb) {
    Mat n = null;
    if(rgb.empty()) {
        System.out.println("Empty Image");
    }
    else {
        System.out.println("The image is " + rgb.rows() + "x" + rgb.cols());
        n = nativeSkinFilter(mNativeObj, rgb.getNativeObjAddr());
    }   
    return n;
}

nativeSkinFilter 是带有此声明的本机函数

private static native Mat nativeSkinFilter(long thiz, long inputImage);

在 C++ 端我有函数声明 (DetectionBasedTracker.h):

JNIEXPORT jlong JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSkinFilter (JNIEnv *, jclass, jlong);

我唯一想做的就是返回相同的图像,只是通过 C++ 函数传递(一旦我知道我可以正确传递矩阵,就会出现更复杂的实现),所以代码就是这样(DetectionBasedTracker .cpp):

JNIEXPORT jlong JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSkinFilter (JNIEnv * jenv,jclass,jlong rgb)
{
    Mat* rgba = (Mat*) rgb;
    if(rgb == 0) {
        LOGD("Null matrix");
    }
    else {
        LOGD("The matrix is not null. It has %i rows and %i columns", (*rgba).rows, (*rgba).cols);
    }

    return (jlong)rgb;
}

我的输出如下:

07-07 13:00:07.671: I/Choreographer(14980): Skipped 55 frames!  The application may be doing too much work on its main thread.
07-07 13:00:07.701: E/BufferQueue(14980): [unnamed-14980-0] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=6 undequeudCount=0)
07-07 13:00:07.741: I/JavaCameraView(14980): Preview Frame received. Need to create MAT and deliver it to clients
07-07 13:00:07.741: I/JavaCameraView(14980): Frame size  is 576000
07-07 13:00:07.761: I/System.out(14980): The image is 480x800
07-07 13:00:07.761: D/FaceDetection/DetectionBasedTracker(14980): The matrix is not null. It has 1937716000 rows and 0 columns
07-07 13:00:07.761: E/cv::error()(14980): OpenCV Error: Assertion failed (src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols) in void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean), file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/java/generator/src/cpp/utils.cpp, line 97
07-07 13:00:07.761: E/org.opencv.android.Utils(14980): nMatToBitmap catched cv::Exception: /home/reports/ci/slave_desktop/50-SDK/opencv/modules/java/generator/src/cpp/utils.cpp:97: error: (-215) src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean)
07-07 13:00:07.761: A/libc(14980): Fatal signal 11 (SIGSEGV) at 0x0000000a (code=1), thread 15115 (Thread-5379)
07-07 13:00:07.791: E/BufferQueue(14980): [unnamed-14980-0] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=5 undequeudCount=1)
07-07 13:00:07.801: I/JavaCameraView(14980): Preview Frame received. Need to create MAT and deliver it to clients
07-07 13:00:07.801: I/JavaCameraView(14980): Frame size  is 576000

我想我已经尝试了所有方法,但这似乎是正确的方法,但仍然失败。 你能帮帮我吗?

非常感谢您的宝贵时间!非常感谢您的帮助。

【问题讨论】:

    标签: c++ opencv java-native-interface parameter-passing mat


    【解决方案1】:

    这个

    JNIEXPORT jlong JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSkinFilter (JNIEnv *, jclass, jlong);
    

    应该是这样的

    JNIEXPORT jlong JNICALL Java_org_opencv_samples_facedetect_DetectionBasedTracker_nativeSkinFilter (JNIEnv *, jclass, jobject, jlong);
    

    因为在java中这样的调用

    n = nativeSkinFilter(mNativeObj, rgb.getNativeObjAddr());
    

    需要 4 个参数:

    • JNEnv(明显)
    • jclass 是类。或者,如果您从实例调用方法,它将是 jobject
    • jobject,因为你正在传递一些对象
    • jlong​​ 现在这是您正在寻找的实际矩阵

    在c++端,在第二个参数之后,传递你在Java端传入的参数。换句话说,在 c++ 端通过 Java->C++(无论是实例还是静态函数)的每次调用,前两个参数都是强制性的。然后在 Java 代码中的“(”和“)”之间跟随您的参数。

    【讨论】:

    • 是的!这是正确的。我前段时间想通了,但我忘了发布解决方案。非常感谢! :D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    相关资源
    最近更新 更多