如何将OpenCV Mat从本机代码返回到Android中的Java

时间:2016-07-27 17:47:24

标签: java android c++ opencv native

我在Android Studio项目中使用OpenCV,并且希望将在本机C ++方法中创建的Mat对象返回到java环境。我已经尝试this recommendation,但它对我没用。我收到以下错误:

07-27 12:10:48.433 11004-11004/com.visualdefence.mobileclient E/GLib: gst_app_sink_pull_sample: assertion 'GST_IS_APP_SINK (appsink)' failed
07-27 12:10:48.433 11004-11004/com.visualdefence.mobileclient E/cv::error(): OpenCV Error: Assertion failed (total() == 0 || data != NULL) in cv::Mat::Mat(cv::Size, int, void*, size_t), file src/main/jni/../opencvLib/include/opencv2/core/mat.inl.hpp, line 443

                                                                             --------- beginning of crash
07-27 12:10:48.434 11004-11004/com.visualdefence.mobileclient A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 11004 (ce.mobileclient)

本机类(相关方法是 native_get_screenshot ):

...

#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

GST_DEBUG_CATEGORY_STATIC (debug_category);
#define GST_CAT_DEFAULT debug_category

#define GET_CUSTOM_DATA(env, thiz, fieldID) (Player *)(gintptr)env->GetLongField (thiz, fieldID)
#define SET_CUSTOM_DATA(env, thiz, fieldID, data) env->SetLongField (thiz, fieldID, (jlong)(gintptr)data)

typedef struct _Player
{
  jobject java_player;
  GstPlayer *player;
  GstPlayerVideoRenderer *renderer;
  ANativeWindow *native_window;
} Player;

...
...
...

static void
native_get_screenshot (JNIEnv * env, jobject thiz, jlong matAddr)
{
  GstMapInfo mapInfo = {0, };
  Mat *matRgb = (Mat*)matAddr;
  Player *player = GET_CUSTOM_DATA (env, thiz, native_player_field_id);

  if (!player) {
    matRgb = NULL;
    return;
  }

  GstElement *pipeline, *app_sink;
  pipeline = gst_player_get_pipeline(player->player);
  app_sink = gst_bin_get_by_name(GST_BIN(pipeline), "sink");
  GstSample *gst_sample = gst_app_sink_pull_sample ((GstAppSink*)app_sink);
  GstBuffer *gst_buffer = gst_sample_get_buffer (gst_sample);

  gst_buffer_map (gst_buffer, &mapInfo, GST_MAP_READ);

  *matRgb = Mat(Size(640, 360), CV_8UC3, (char*)mapInfo.data);
  cvtColor(*matRgb, *matRgb, CV_RGB2BGR);
}

...
...
...

/* List of implemented native methods */
static JNINativeMethod native_methods[] = {
  {"nativeGetScreenshot", "(J)V", (void *) native_get_screenshot}
  ...
};

...
...
...

java类:

...
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;

public class Player implements Closeable {
    private static native void nativeClassInit();
    public static void init(Context context) throws Exception {
        System.loadLibrary("opencv_java3");
        System.loadLibrary("gstreamer_android");
        GStreamer.init(context);

        if (!OpenCVLoader.initDebug()) {
            Log.e("Player", "Initializing OpenCV failed");
        }

        System.loadLibrary("gstplayer");
        nativeClassInit();
    }

    private native void nativeGetScreenshot(long matAddr);
    public Mat getScreenshot() {
        Mat descriptor = new Mat();
        nativeGetScreenshot(descriptor.getNativeObjAddr());
        return descriptor;
    }
}

所以我在这里做的是将在java中创建的Mat指针作为参数发送到本机方法,以便我可以从C ++本机代码中分配它的内存。 看起来Mat构造函数中出现的错误来自它给出的行号。

如果我将指向Java Mat的指针传递给本机代码以将其作为Mat操作,会导致此错误?

0 个答案:

没有答案