【问题标题】:Unable to return Open CV mat from native C++ to Java in Android无法在 Android 中将 Open CV mat 从本机 C++ 返回到 Java
【发布时间】:2018-09-13 07:37:52
【问题描述】:

我正在开发一个需要进行图像处理的 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.util 中的 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)

我的代码有什么问题,我该如何解决?

【问题讨论】:

  • 我相信 newMat.create(mat.rows, mat.rows, mat.type()); 应该是 mat.rows, mat.cols 除非您的图像是方形的。您可以将 logcat 过滤器设置为 NO FILTER 并查找崩溃报告(其中包含 SEGFAULT),本机崩溃的显示方式与 java 的不同。 Example of what you should see as error
  • @DmitriiZ。我尝试了你的解决方案,它仍然抛出错误。但是我现在可以记录错误并更新问题。

标签: java android c++ opencv java-native-interface


【解决方案1】:

stitchPhotos() 调用发生之前,Java 调用堆栈就指向了这一行:

mat.put(0, 0, jpeg);

根据错误消息,jpeg 的尺寸有误。 put() 似乎希望接收一个大小为 3 倍数的数组(因为 mat 被声明为类型 CV_8UC3,它是 8 位、无符号、每个像素有 3 个通道)。

附:在 C++ 中将Mat 复制到另一个的更简单方法是copyTo,或赋值运算符。例子:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-12
    • 2017-10-07
    • 1970-01-01
    • 2012-05-10
    • 2016-11-05
    • 1970-01-01
    相关资源
    最近更新 更多