Unable to return Open CV mat from native C++ to Java in Android
up vote
0
down vote
favorite
I am developing an Android application that needs to do some image processing. I am calling c++ code through JNI from java for it. I am using OpenCV for image processing. First, I confess that I just started using OpenCv and learning image processing. What I am trying to do now is trying to return open CV mat data from the native C++ to Java.
I am not a C++ developer as well. I am following this link- http://answers.opencv.org/question/12090/returning-a-mat-from-native-jni-to-java/.
This is my native C++ code
#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());
As you can see, this line
memcpy(newMat.data, mat.data , mat.step * mat.rows);
will pass the new value to the mat in the java. This is my Java code.
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());
According to my code, when I call native function from Java, newMat variable in java should get the other mat variable value. Right? But when I run that code, my application crashes.
It is giving me this error
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)
What is wrong with my code and how can I fix it?
java android c++ opencv jni
add a comment |
up vote
0
down vote
favorite
I am developing an Android application that needs to do some image processing. I am calling c++ code through JNI from java for it. I am using OpenCV for image processing. First, I confess that I just started using OpenCv and learning image processing. What I am trying to do now is trying to return open CV mat data from the native C++ to Java.
I am not a C++ developer as well. I am following this link- http://answers.opencv.org/question/12090/returning-a-mat-from-native-jni-to-java/.
This is my native C++ code
#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());
As you can see, this line
memcpy(newMat.data, mat.data , mat.step * mat.rows);
will pass the new value to the mat in the java. This is my Java code.
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());
According to my code, when I call native function from Java, newMat variable in java should get the other mat variable value. Right? But when I run that code, my application crashes.
It is giving me this error
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)
What is wrong with my code and how can I fix it?
java android c++ opencv jni
I believenewMat.create(mat.rows, mat.rows, mat.type());
should bemat.rows, mat.cols
unless your image is square. You can set logcat filter toNO FILTER
and look for crash report (something with SEGFAULT in it), native crashes are shown differently from java ones. Example of what you should see as error
– Dmitrii Z.
Apr 3 at 21:15
@DmitriiZ. I tried your solution and it is still throwing error. Bu I am able to log the error now and updated the question.
– Wai Yan Hein
Apr 3 at 22:01
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I am developing an Android application that needs to do some image processing. I am calling c++ code through JNI from java for it. I am using OpenCV for image processing. First, I confess that I just started using OpenCv and learning image processing. What I am trying to do now is trying to return open CV mat data from the native C++ to Java.
I am not a C++ developer as well. I am following this link- http://answers.opencv.org/question/12090/returning-a-mat-from-native-jni-to-java/.
This is my native C++ code
#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());
As you can see, this line
memcpy(newMat.data, mat.data , mat.step * mat.rows);
will pass the new value to the mat in the java. This is my Java code.
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());
According to my code, when I call native function from Java, newMat variable in java should get the other mat variable value. Right? But when I run that code, my application crashes.
It is giving me this error
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)
What is wrong with my code and how can I fix it?
java android c++ opencv jni
I am developing an Android application that needs to do some image processing. I am calling c++ code through JNI from java for it. I am using OpenCV for image processing. First, I confess that I just started using OpenCv and learning image processing. What I am trying to do now is trying to return open CV mat data from the native C++ to Java.
I am not a C++ developer as well. I am following this link- http://answers.opencv.org/question/12090/returning-a-mat-from-native-jni-to-java/.
This is my native C++ code
#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());
As you can see, this line
memcpy(newMat.data, mat.data , mat.step * mat.rows);
will pass the new value to the mat in the java. This is my Java code.
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());
According to my code, when I call native function from Java, newMat variable in java should get the other mat variable value. Right? But when I run that code, my application crashes.
It is giving me this error
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)
What is wrong with my code and how can I fix it?
java android c++ opencv jni
java android c++ opencv jni
edited Nov 11 at 23:03
halfer
14.3k758107
14.3k758107
asked Apr 3 at 21:09
Wai Yan Hein
2,40443996
2,40443996
I believenewMat.create(mat.rows, mat.rows, mat.type());
should bemat.rows, mat.cols
unless your image is square. You can set logcat filter toNO FILTER
and look for crash report (something with SEGFAULT in it), native crashes are shown differently from java ones. Example of what you should see as error
– Dmitrii Z.
Apr 3 at 21:15
@DmitriiZ. I tried your solution and it is still throwing error. Bu I am able to log the error now and updated the question.
– Wai Yan Hein
Apr 3 at 22:01
add a comment |
I believenewMat.create(mat.rows, mat.rows, mat.type());
should bemat.rows, mat.cols
unless your image is square. You can set logcat filter toNO FILTER
and look for crash report (something with SEGFAULT in it), native crashes are shown differently from java ones. Example of what you should see as error
– Dmitrii Z.
Apr 3 at 21:15
@DmitriiZ. I tried your solution and it is still throwing error. Bu I am able to log the error now and updated the question.
– Wai Yan Hein
Apr 3 at 22:01
I believe
newMat.create(mat.rows, mat.rows, mat.type());
should be mat.rows, mat.cols
unless your image is square. You can set logcat filter to NO FILTER
and look for crash report (something with SEGFAULT in it), native crashes are shown differently from java ones. Example of what you should see as error– Dmitrii Z.
Apr 3 at 21:15
I believe
newMat.create(mat.rows, mat.rows, mat.type());
should be mat.rows, mat.cols
unless your image is square. You can set logcat filter to NO FILTER
and look for crash report (something with SEGFAULT in it), native crashes are shown differently from java ones. Example of what you should see as error– Dmitrii Z.
Apr 3 at 21:15
@DmitriiZ. I tried your solution and it is still throwing error. Bu I am able to log the error now and updated the question.
– Wai Yan Hein
Apr 3 at 22:01
@DmitriiZ. I tried your solution and it is still throwing error. Bu I am able to log the error now and updated the question.
– Wai Yan Hein
Apr 3 at 22:01
add a comment |
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
The Java call stack is pointing to this line before the stitchPhotos()
call even happens:
mat.put(0, 0, jpeg);
Based on the error message, jpeg
has the wrong dimensions. It appears that put()
expects to receive an array that is a multiple of 3 in size (since mat
is declared as type CV_8UC3
, which is 8 bit, unsigned, with 3 channels per pixel).
P.S. An easier way to copy one Mat
to another in C++ is copyTo
, or the assignment operator. Examples:
Mat& mat = *(Mat*)addrMat;
Mat& newMat = *(Mat*)addrNewMat;
mat.copyTo(newMat);
newMat = mat;
Yes. That worked. Thanks so much.
– Wai Yan Hein
Apr 4 at 10:03
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f49639189%2funable-to-return-open-cv-mat-from-native-c-to-java-in-android%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
The Java call stack is pointing to this line before the stitchPhotos()
call even happens:
mat.put(0, 0, jpeg);
Based on the error message, jpeg
has the wrong dimensions. It appears that put()
expects to receive an array that is a multiple of 3 in size (since mat
is declared as type CV_8UC3
, which is 8 bit, unsigned, with 3 channels per pixel).
P.S. An easier way to copy one Mat
to another in C++ is copyTo
, or the assignment operator. Examples:
Mat& mat = *(Mat*)addrMat;
Mat& newMat = *(Mat*)addrNewMat;
mat.copyTo(newMat);
newMat = mat;
Yes. That worked. Thanks so much.
– Wai Yan Hein
Apr 4 at 10:03
add a comment |
up vote
2
down vote
accepted
The Java call stack is pointing to this line before the stitchPhotos()
call even happens:
mat.put(0, 0, jpeg);
Based on the error message, jpeg
has the wrong dimensions. It appears that put()
expects to receive an array that is a multiple of 3 in size (since mat
is declared as type CV_8UC3
, which is 8 bit, unsigned, with 3 channels per pixel).
P.S. An easier way to copy one Mat
to another in C++ is copyTo
, or the assignment operator. Examples:
Mat& mat = *(Mat*)addrMat;
Mat& newMat = *(Mat*)addrNewMat;
mat.copyTo(newMat);
newMat = mat;
Yes. That worked. Thanks so much.
– Wai Yan Hein
Apr 4 at 10:03
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
The Java call stack is pointing to this line before the stitchPhotos()
call even happens:
mat.put(0, 0, jpeg);
Based on the error message, jpeg
has the wrong dimensions. It appears that put()
expects to receive an array that is a multiple of 3 in size (since mat
is declared as type CV_8UC3
, which is 8 bit, unsigned, with 3 channels per pixel).
P.S. An easier way to copy one Mat
to another in C++ is copyTo
, or the assignment operator. Examples:
Mat& mat = *(Mat*)addrMat;
Mat& newMat = *(Mat*)addrNewMat;
mat.copyTo(newMat);
newMat = mat;
The Java call stack is pointing to this line before the stitchPhotos()
call even happens:
mat.put(0, 0, jpeg);
Based on the error message, jpeg
has the wrong dimensions. It appears that put()
expects to receive an array that is a multiple of 3 in size (since mat
is declared as type CV_8UC3
, which is 8 bit, unsigned, with 3 channels per pixel).
P.S. An easier way to copy one Mat
to another in C++ is copyTo
, or the assignment operator. Examples:
Mat& mat = *(Mat*)addrMat;
Mat& newMat = *(Mat*)addrNewMat;
mat.copyTo(newMat);
newMat = mat;
answered Apr 4 at 2:23
Jack C.
5997
5997
Yes. That worked. Thanks so much.
– Wai Yan Hein
Apr 4 at 10:03
add a comment |
Yes. That worked. Thanks so much.
– Wai Yan Hein
Apr 4 at 10:03
Yes. That worked. Thanks so much.
– Wai Yan Hein
Apr 4 at 10:03
Yes. That worked. Thanks so much.
– Wai Yan Hein
Apr 4 at 10:03
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f49639189%2funable-to-return-open-cv-mat-from-native-c-to-java-in-android%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I believe
newMat.create(mat.rows, mat.rows, mat.type());
should bemat.rows, mat.cols
unless your image is square. You can set logcat filter toNO FILTER
and look for crash report (something with SEGFAULT in it), native crashes are shown differently from java ones. Example of what you should see as error– Dmitrii Z.
Apr 3 at 21:15
@DmitriiZ. I tried your solution and it is still throwing error. Bu I am able to log the error now and updated the question.
– Wai Yan Hein
Apr 3 at 22:01