What is the best way to pass OpenCV vector< std::vector<Point > > contours from a JNI C++ function to Java in Android? My current approach is to use arrays of doubles but this is very inefficient. Is there a way to use pointers maybe?
-
There are no pointers in java. You can store a pointer value into a java long but that only helps to keep the reference.Fildor– Fildor2014-12-02 06:14:06 +00:00Commented Dec 2, 2014 at 6:14
-
1Maybe this answer helps you stackoverflow.com/a/23116736/2455351 (It's done for passing a vector<KeyPoint>)migue02– migue022014-12-02 07:51:20 +00:00Commented Dec 2, 2014 at 7:51
-
1FYI, we can directly access that type in Java using JavaCPP: bytedeco.org/javacpp-presets/opencv/apidocs/org/bytedeco/…Samuel Audet– Samuel Audet2014-12-06 08:13:59 +00:00Commented Dec 6, 2014 at 8:13
-
@SamuelAudet your comment is closer to what I was looking for, but I've never used JavaCPP. If you post an answer where you elaborate more on this, I will select it.Jaime Ivan Cervantes– Jaime Ivan Cervantes2014-12-07 18:53:36 +00:00Commented Dec 7, 2014 at 18:53
2 Answers
Well, you can create a class at Java side equivalent to vector< std::vector<Point > > in C++ side. Then, write a serializer function in C++ and deserailizer method in Java.
Your serializer can be a String composed of double values which are seperated by , and ;, which can be deserialized easliy in Java.
In this way, instead of sending multiple arrays you can sen just one string. You need to be careful with the precision of double when converting it to double and converting it back.
Comments
Here's an efficient way to access contours with the wrapper from the JavaCPP Presets for OpenCV:
import org.bytedeco.javacpp.indexer.*;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
import static org.bytedeco.javacpp.opencv_highgui.*;
public class Contours {
public static void main(String[] args) {
Mat grayscaleImage = imread("lena.png", CV_LOAD_IMAGE_GRAYSCALE);
Mat binarizedImage = new Mat();
MatVector contours = new MatVector();
threshold(grayscaleImage, binarizedImage, 128, 255, THRESH_BINARY);
findContours(binarizedImage, contours, RETR_LIST, CHAIN_APPROX_NONE);
int contoursSize = (int)contours.size();
System.out.println("size = " + contoursSize);
for (int contourIdx = 0; contourIdx < contoursSize; contourIdx++) {
// compute center
float x = 0, y = 0;
Mat contour = contours.get(contourIdx);
IntIndexer points = contour.createIndexer(false);
int pointsSize = contour.rows();
for (int pointIdx = 0; pointIdx < pointsSize; pointIdx++) {
x += points.get(pointIdx, 0);
y += points.get(pointIdx, 1);
}
System.out.println("center = (" + x / pointsSize + ", " + y / pointsSize + ")");
}
}
}
For simplicity, I'm using Java SE, but we can do the same thing on Android.