I'm currently trying to migrate a bit of legacy code from iPhone to Android. This code uses the OpenCV library to do some image processing. Overall it goes well, but I'm stuck on one line of code I have no idea how can be converted into Java code:
Scalar dMean;
Scalar scalar;
std::vector<Mat> channels;
split(mat, channels);
for(int i=0; i<3; ++i) {
channels[i] += dMean[i];
}
The question is - what should be used instead of the += operator in Java code to add a Scalar object to a Mat?
Note: take this answer with a grain of salt, I haven't fully tested this ;)
OPTION1:
The most direct way, and if you are only going to process a few pixels, is by using your_mat.put(row, col, data) and your_mat.get(row, col).
Because the put()
method does not accept Scalar
objects as the data parameter, you have to convert the Scalar
to something that put()
accepts.
So if your Scalar
is (1,2,3) maybe an int array int[] scalar = {1,2,3}; should do the trick.
int[] scalar = ... // convert from Scalar object
// assuming the result of get() is an int[], sum both arrays:
int[] data = your_mat.get(row, col) + scalar // <- pseudo-code alert :D
your_mat.put(row, col, data);
OPTION2:
But the recommended way, for a lot of pixel processing, is to first convert a Mat
to a Java primitive, process the primitive and then convert it back to Mat
. This is to avoid too many JNI calls, this method does 2 JNI calls while the former makes one per put/get.
The corresponding Java primitive array type depends on the Mat type:
CV_8U and CV_8S -> byte[];
CV_16U and CV_16S -> short[];
CV_32S -> int[];
CV_32F -> float[];
CV_64F-> double[];
So the code will be something like this:
// assuming Mat it's of CV_32S type
int buff[] = new int[your_mat.total() * your_mat.channels()];
your_mat.get(0, 0, buff);
// buff is now Mat converted to int[]
your_mat.put(0, 0, buff); // after processing buff, convert it back to Mat type
OPTION 3:
Ok so those solutions are pretty ugly, this one is not the most effective but it's a little less ugly, in a Java way:
List<Integer> scalarList = ... // your conversion from a Scalar to a List
List<Integer> channelsList = new ArrayList<Integer>();
Converters.Mat_to_vector_int(channels, channelsList); // this is an existing OpenCV4Android converter
// process channelsList and scalarList, store in channelsList
channels = Converters.vector_int_to_Mat(channelsList); // after processing, convert it back to Mat type
Now that I think about it option 3 is quite similar to option 2, if OpenCV's Converters
work similar internally as the option 2 conversion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With