从C ++转换的OpenCV code到JavaOpenCV、code、Java

2023-09-06 02:52:56 作者:灵魂摆渡

目前,我正在试图一点点遗留code,从iPhone移植到Android。这code使用了OpenCV库做一些图像处理。总体而言,它顺利,但我坚持在同一行的code我不知道如何可以被转换成Java code:

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];
}

现在的问题是 - 什么应该被用来代替+ =运算符在Java中code为标对象添加到垫?

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

选项1:

最直接的方法,如果你只打算处理几个像素,是使用 your_mat.put(行,列,数据)和 your_mat.get(行, COL)

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

由于该的put()方法不接受对象作为数据参数,就必须转换来放东西,()接受。

Because the put() method does not accept Scalar objects as the data parameter, you have to convert the Scalar to something that put() accepts.

所以,如果你的为(1,2,3)也许一个int数组的 INT []标= {1,2,3}; 应该做的伎俩。

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:

但建议的方式,进行了大量的像素处理的,是先转换来一个Java原始,工艺原始,然后将其转换回。这是为了避免太多的JNI调用,这种方法并2 JNI调用,而前者使每放一/搞定了。

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.

对应的Java基本数组类型取决于垫类型:

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[];

所以,code将是这样的:

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

方法3:

好了,所以这些解决方案是pretty的丑陋的,这个人是不是最有效的,但它是一个少一点丑陋,在Java方式:

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

现在,我想它选项3 颇为相似选项2 ,如果OpenCV的的转换工作相似内部的选项2 的转换。

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.