在JNI中修改的Mat不会反映Java中的更改

时间:2016-06-29 16:28:50

标签: java android opencv java-native-interface

我应该注意到我是一个JNI新手,而且对于android来说并不是更好,所以请耐心等待我。

根据答案here我传递了一个"输入"和"输出"将JNI称为jlong​​s,并对两者进行类型转换。但是我的输出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();
}

这是我的日食输出

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): []

...所以我错过了什么?

1 个答案:

答案 0 :(得分:0)

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

以下是有效的,并且为了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());
}