使用get()和put()来访问OpenCV for Java中的像素值

我是使用OpenCV for JAVA的初学者。 我想访问一个图像matrix的个别像素值。 因为OpenCV的JAVA jar没有像C ++那样提供很好的function,所以遇到了一些麻烦。 经过大量的search,我find了两种不同的方法来做这件事,虽然他们没有正确解释(甚至没有文档)。 我们可以使用get()和put()函数,或者通过将mat数据转换为诸如数组等原始javatypes来实现。 我试了两次,但得到不同的输出结果! 请帮助解释我做错了什么。 我用他们错了还是其他一些愚蠢的问题。 我还是一个新手,所以请原谅,如果它是一个愚蠢的问题。 🙂

情况1:使用get()函数

Mat A = Highgui.imread(image_addr); \\"image_addr" is the address of the image Mat C = A.clone(); Size sizeA = A.size(); for (int i = 0; i < sizeA.height; i++) for (int j = 0; j < sizeA.width; j++) { double[] data = A.get(i, j); data[0] = data[0] / 2; data[1] = data[1] / 2; data[2] = data[2] / 2; C.put(i, j, data); } 

情况2:使用数组

 Mat A = Highgui.imread(image_addr); \\"image_addr" is the address of the image Mat C = A.clone(); int size = (int) (A.total() * A.channels()); byte[] temp = new byte[size]; A.get(0, 0, temp); for (int i = 0; i < size; i++) temp[i] = (byte) (temp[i] / 2); C.put(0, 0, temp); 

根据我的理解,他们都应该做同样的事情。 他们都访问个别像素值(全部3个通道),并使其成为一半。 运行后我没有错误。 但是,我得到的输出图像在这两种情况下是不同的。 有人可以请解释是什么问题? 可能我不明白get()函数是如何工作的? 这是因为字节()铸造? 请帮忙。

谢谢!

Solutions Collecting From Web of "使用get()和put()来访问OpenCV for Java中的像素值"

这是因为byte()铸造而发生的。 我在第二种情况下将mat图像的数据types更改为* CV_64FC3 *,以便我可以使用double []而不是byte [],并解决了问题。

 Mat A = Highgui.imread(image_addr); //"image_addr" is the address of the image Mat C = A.clone(); A.convertTo(A, CvType.CV_64FC3); // New line added. int size = (int) (A.total() * A.channels()); double[] temp = new double[size]; // use double[] instead of byte[] A.get(0, 0, temp); for (int i = 0; i < size; i++) temp[i] = (temp[i] / 2); // no more casting required. C.put(0, 0, temp); 

仅供参考,我也做了一些时间测量,使用第二种方法比第一种方法快。

find了一个简单而有效的解决scheme,

 Mat img = Highgui.imread("Input.jpg"); //Reads image from the file system and puts into matrix int rows = img.rows(); //Calculates number of rows int cols = img.cols(); //Calculates number of columns int ch = img.channels(); //Calculates number of channels (Grayscale: 1, RGB: 3, etc.) for (int i=0; i<rows; i++) { for (int j=0; j<cols; j++) { double[] data = img.get(i, j); //Stores element in an array for (int k = 0; k < ch; k++) //Runs for the available number of channels { data[k] = data[k] * 2; //Pixel modification done here } img.put(i, j, data); //Puts element back into matrix } } Highgui.imwrite("Output.jpg", img); //Writes image back to the file system using values of the modified matrix 

注意:在线任何地方都没有提到的一个重要的一点是put方法不会将像素写入Input.jpg 。 它只是更新matriximg的值。 因此,上面的代码不会改变input图像中的任何内容。 为了产生可见的输出,matriximg需要被写入文件,即在这种情况下的Output.jpg 。 此外,使用img.get(i, j)似乎是处理matrix元素的一种更好的方式,而不是使用上面接受的解决scheme,因为这有助于以更好的方式可视化和处理图像matrix,并且不需要大的连续的内存分配。