java - 在 JNI 中修改的 Mat 不反射(reflect)在 Java 中的更改

标签 java android opencv java-native-interface

我应该指出,我是一个 JNI 新手,对 android 也好不到哪里去,所以请多多包涵。

根据答案here我将“输入”和“输出”Mat 作为 jlong​​ 传递给 JNI,并对两者进行类型转换。但是对我的输出 Mat 的更改似乎并没有在 Java 中出现……而且我不明白为什么。这是我的代码。

//SimpleJNI.java
Mat outputPoints = new Mat(); 
Native.getTagsDetails(image.getNativeObjAddr(), OutputPoints.getNativeObjAddr()); 
String Message = String.format("outputPoints.cols() = %d, outputPoints.rows() = %d, outputPoints.dims() = %d",
                                outputPoints.cols(),      outputPoints.rows(),      outputPoints.dims());
System.out.println(Message);
System.out.println("outputPoints.dump()");
System.out.println(outputPoints.dump());

//native.cpp
JNIEXPORT int JNICALL Java_com_example_android_simplejni_Native_getTagsDetails(JNIEnv*, jobject, jlong inputAddr,  jlong outputAddr)
{
    Mat inputImage = *(Mat*)inputAddr;
    Mat outputMat  = *(Mat*)outputAddr;
    Mat calcMat;
    TagCornerMap tagData = Chilitags().find(inputImage);

    for (const pair<int, Matx<float, 4, 2>> & tag : tagData)
    {
        int id = tag.first;
        Mat coords(tag.second);
        if (calcMat.empty())
            calcMat = coords;
        else
            hconcat(calcMat, coords, calcMat);
    }
    ALOGE("JET outputMat.total() = %i, outputMat.type() = %i, outputMat.dims = %i", 
     outputMat.total(),      outputMat.type(),      outputMat.dims);
    ALOGE("JET calcMat.total() = %i, calcMat.type() = %i, calcMat.dims = %i", 
               calcMat.total(),      calcMat.type(),      calcMat.dims);
    outputMat = calcMat.clone();
    ALOGE("JET outputMat.total() = %i, outputMat.type() = %i, outputMat.dims = %i", 
               outputMat.total(),      outputMat.type(),      outputMat.dims);
    return tagData.size();
}

这是我的 eclipse 输出

simplejni native.cpp(23056): JET outputMat.total() = 0, outputMat.type() = 0, outputMat.dims = 0
simplejni native.cpp(23056): JET calcMat.total() = 8, calcMat.type() = 5, calcMat.dims = 2
simplejni native.cpp(23056): JET outputMat.total() = 8, outputMat.type() = 5, outputMat.dims = 2
System.out(23056): outputPoints.cols() = 0, outputPoints.rows() = 0, outputPoints.dims() = 0
System.out(23056): outputPoints.dump()
System.out(23056): []

...那么我错过了什么?

最佳答案

你 Handlebars 指放在上面。谢谢亨利先生。

以下是有效的,并且为了 Google 的缘故更偏向于 MCVE。

//native.cpp
#include <jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;

JNIEXPORT int JNICALL Java_com_example_android_simplejni_Native_getTagsDetails(JNIEnv* env, jobject callingObject, jlong inputAddr,  jlongArray outputAddrs, jintArray tagValues)
{
    Mat * inputImage = (Mat*)inputAddr;
    Matx<float, 4, 2> tagData [2] = {Matx<float, 4, 2>( 1,  2,  3,  4,  5,  6,  7,  8), 
                                     Matx<float, 4, 2>(11, 12, 13, 14, 15, 16, 17, 18)};
    int ii = 0;
    jsize outputAddrsLen    = env->GetArrayLength(outputAddrs);
    jsize tagValuesLen      = env->GetArrayLength(tagValues);
    jlong * outputAddrsData = env->GetLongArrayElements(outputAddrs, 0);
    jint *    tagValuesData = env->GetIntArrayElements(tagValues, 0);
    for (Matx<float, 4, 2>  tag : tagData)
    {
        if ((ii >= outputAddrsLen) || (ii >= tagValuesLen))
            break;
        Mat * anOutputMat  = (Mat*)(outputAddrsData[ii]);
        tagValuesData[ii] = ii * -2;
        Mat coords(tag);
        *anOutputMat = coords.clone();
        ii++;
    }
    env->ReleaseLongArrayElements(outputAddrs, outputAddrsData, 0);
    env->ReleaseIntArrayElements(tagValues,   tagValuesData,   0);
    //return tagData.size();
    return 0;
} 

//simpleJNI.java
@Override
public void onManagerConnected(int status) 
{
    if (status == LoaderCallbackInterface.SUCCESS)
        System.out.println("OpenCV loaded successfully");
    super.onManagerConnected(status);
    Mat image = Imgcodecs.imread("/storage/emulated/0/myJNI/chilitag-screenshot.png"); 

    Mat outputPoints[] = {new Mat(), new Mat()};
    long outputAddrs[] = {  outputPoints[0].getNativeObjAddr(),
                                    outputPoints[1].getNativeObjAddr()};
    int tagValues[] = new int[2];
    Native.getTagsDetails(image.getNativeObjAddr(), outputAddrs, tagValues); 
    for (int ii = 0; ii < 2; ii++)
    {
        System.out.println("outputPoints[" + ii + "].dump():");
        System.out.println(outputPoints[ii].dump());    
        System.out.println("tagValues[" + ii + "] = " + tagValues[ii]);
    }
    tv.setText("chilitag results: " + outputPoints.toString());
}

关于java - 在 JNI 中修改的 Mat 不反射(reflect)在 Java 中的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38105302/

相关文章:

android - 在 android studio 中找不到 proguard-project.txt

java - Android应用程序登录抽屉导航无法点击 fragment

android - 在新版本的 Android 中使用支持类

python - 如何使用 Opencv 从网络摄像头获取最新帧?

java - 多级继承中的方法调用

java - 通过 IMAP 获取电子邮件详细信息

java - 如何让 Mockito 根据枚举返回不同的值?

java - 如何在 Java 中返回 5 个随机的 "Powerball"数字

opencv - 从技术绘图图像中删除圆圈

opencv - 主成分分析和旋转