代码之家  ›  专栏  ›  技术社区  ›  Wai Yan Hein

无法在Android中将Open CV mat从本机C++返回到Java

  •  0
  • Wai Yan Hein  · 技术社区  · 7 年前

    我正在开发一个Android应用程序,需要进行一些图像处理。我正在通过java中的JNI调用c++代码。我正在使用OpenCV进行图像处理。首先,我承认我刚刚开始使用OpenCv并学习图像处理。我现在要做的是尝试将打开的CV mat数据从本机C++返回到Java。

    我也不是一个C++开发人员。我正在关注此链接- http://answers.opencv.org/question/12090/returning-a-mat-from-native-jni-to-java/

    这是我的原生C++代码

    #include <jni.h>
    #include <string>
    
    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/features2d/features2d.hpp>
    
    using namespace std;
    using namespace cv;
    
    extern "C"
    JNIEXPORT jstring
    
    
    
    JNICALL
    Java_media_memento_memento_SphereCameraActivity_stitchPhotos(
            JNIEnv *env,
            jobject /* this */, jlong addrMat, jlong addrNewMat) {
    
    
    
    
        Mat& mat = *(Mat*)addrMat;
        Mat& newMat = *(Mat*)addrNewMat;
    
        newMat.create(mat.rows, mat.rows, mat.type());
        memcpy(newMat.data, mat.data , mat.step * mat.rows);
    
        std::string hello = "Stitching the photo in C++";
        return env->NewStringUTF(hello.c_str());
    }
    

    正如你所看到的,这条线

    memcpy(newMat.data、mat.data、mat.step*mat.rows);

    将新值传递给java中的mat。这是我的Java代码。

                   Mat mat;
    
                   bitmap.getHeight();
                   bitmap.getWidth();
                   mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_8UC3);
                   mat.put(0, 0, jpeg);
                   Mat newMat = new Mat();
                   stitchPhotos(mat.getNativeObjAddr(), newMat.getNativeObjAddr());
    

    根据我的代码,当我从Java调用本机函数时,Java中的newMat变量应该得到另一个mat变量值。正当但当我运行该代码时,我的应用程序崩溃了。 它给了我这个错误

    D/AndroidRuntime: Shutting down VM
    E/AndroidRuntime: FATAL EXCEPTION: main
                      Process: media.memento.memento, PID: 4823
                      java.lang.UnsupportedOperationException: Provided data element number (39397) should be multiple of the Mat channels count (3)
                          at org.opencv.core.Mat.put(Mat.java:1011)
                          at media.memento.memento.SphereCameraActivity$MyCameraListener$1.onBitmapReady(SphereCameraActivity.java:276)
                          at com.otaliastudios.cameraview.CameraUtils$1$1.run(CameraUtils.java:95)
                          at android.os.Handler.handleCallback(Handler.java:751)
                          at android.os.Handler.dispatchMessage(Handler.java:95)
                          at android.os.Looper.loop(Looper.java:154)
                          at android.app.ActivityThread.main(ActivityThread.java:6119)
                          at java.lang.reflect.Method.invoke(Native Method)
                          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
    

    我的代码有什么问题,如何修复?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Jack C.    7 年前

    Java调用堆栈在 stitchPhotos() 即使发生呼叫:

    mat.put(0, 0, jpeg);

    根据错误消息, jpeg 具有错误的尺寸。看来 put() 预期接收的数组大小为3的倍数(自 mat 声明为类型 CV_8UC3 ,即8位,无符号,每像素3个通道)。

    P、 一种更简单的复制方法 Mat C++中的另一个是 copyTo ,或赋值运算符。示例:

    Mat& mat = *(Mat*)addrMat;
    Mat& newMat = *(Mat*)addrNewMat;
    mat.copyTo(newMat);
    newMat = mat;