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?










share|improve this question























  • 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














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?










share|improve this question























  • 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












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?










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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
















  • 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















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












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;





share|improve this answer




















  • Yes. That worked. Thanks so much.
    – Wai Yan Hein
    Apr 4 at 10:03










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
);



);













draft saved

draft discarded


















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;





share|improve this answer




















  • Yes. That worked. Thanks so much.
    – Wai Yan Hein
    Apr 4 at 10:03














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;





share|improve this answer




















  • Yes. That worked. Thanks so much.
    – Wai Yan Hein
    Apr 4 at 10:03












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;





share|improve this answer












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;






share|improve this answer












share|improve this answer



share|improve this answer










answered Apr 4 at 2:23









Jack C.

5997




5997











  • 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




Yes. That worked. Thanks so much.
– Wai Yan Hein
Apr 4 at 10:03

















draft saved

draft discarded
















































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.




draft saved


draft discarded














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





















































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







這個網誌中的熱門文章

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3

Museum of Modern and Contemporary Art of Trento and Rovereto