First time here? Check out the FAQ!

Ask Your Question
3

Returning a Mat from native JNI to Java

asked Apr 22 '13

peanutman gravatar image

updated Apr 22 '13

I have a question about mixing OpenCV's C++ and Java API. I'm using the new desktop Java API to do some processing on images, but due to Java limitations I am forced to capture the images in C++. The images are in an OS-dependant format, so I thought it would be best to convert them to the OpenCV format before handing it to the OS-independant Java code. In the android tutorials (Tutorial 2 Advanced) I saw that they instantiate a Mat on the Java side, and use getNativeObjAddr() to pass a pointer to C++, where it is used as a native C++ object. However, since I can not make any assumptions on the dimensions or channels of the images, I can not take this approach. I want Java to be able to receive the Mat object without knowing anything about it beforehand. I have nu clue how to do this correctly. I have two ideas:

1) I create a Java Mat object from the C++ side ((*env)->NewObject), use JNI to call getNativeObjAddr and work with the returned pointer. While this might work, it seems so backwards... Maybe there's a better way?

2) I create a C++ Mat, and return the pointer to Java. I'm hoping there's some kind of functionality that allows me to wrap it in a Java Mat object. The documentation mentions the Mat(long addr) constructor, but there's no further explanation, and I have no idea what it's for. Can it be used to create a Mat object from a pointer to a native Mat object?

TL;DR: How do I get a Mat created in C++ to Java ?

Thank you for reading!

Preview: (hide)

1 answer

Sort by » oldest newest most voted
5

answered Apr 22 '13

Vladislav Vinogradov gravatar image

updated Apr 22 '13

You can create an empty Mat in Java part and then call create method from C++:

// Java
Mat m = new Mat();
jni_func(m.getNativeObjAddr());

// C++
void jni_func(jlong matPtr)
{
    Mat* mat = (Mat*) matPtr;
    mat->create(rows, cols, type);
    memcpy(mat->data, data, mat->step * mat->rows);
}
Preview: (hide)

Comments

1

Hah, I feel stupid now... I like this approach, as it doesn't require the bridge to be crossed once we're in the function. Thanks for that!

peanutman gravatar imagepeanutman (Apr 23 '13)edit

Can you expand on this? I'm facing the same issue as the poster but I'm having trouble with the implementation.

I understand things on the java side. The first line in C++ makes sense. The second line corresponds to making the image (in my example case im loading it from a file with imread, long term ill get the data delivered over Ethernet, read in C++, altered by openCV in C++ then passed to java for display in a GUI).

The third line I don't understand at all. What is the second argument of memcpy?

Here is my C++ code:

void getCVMat(long matPtr) { cv::Mat * image; image = new cv::Mat(); image = (cv::Mat*) matPtr;

std::string filepath = "C:\\temp\\java.jpg";
(*image) = cv::imread(filepath);

}

This is functional, until its integrated with the main GUI where it crashed the JVM.

MattM gravatar imageMattM (Feb 4 '14)edit

Question Tools

Stats

Asked: Apr 22 '13

Seen: 11,850 times

Last updated: Apr 22 '13