Using get () and put () to access pixel values ​​in OpenCV for Java

I am starting to use OpenCV for JAVA. I want to access individual pixel values ​​of an image matrix. Since the JAVA jar for OpenCV does not offer nice features like C ++, I ran into some problems. After many searches, I found two different methods, although they are not explained properly (even in the documentation). We can do this either using the get () and put () functions, or by converting the mat data into a primitive java type, such as arrays. I tried both, but got different output results! Please help explain what I'm doing wrong. I use them incorrectly or some other stupid problem. I'm still a beginner, so please excuse me if this is a stupid question. :)

CASE 1: Using the get () Function

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

CASE 2: Using an Array

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

Now, according to my understanding, they both have to do the same. They both access individual pixel values ​​(all 3 channels) and make up half. After starting, I get no error. But the output images that I get are different in these two cases. Can someone explain what the problem is? Maybe I don’t understand how the get () function works? Is it because of byte casting ()? Please, help.

Thanks!

+8
java android image-processing opencv computer-vision
source share
2 answers

This was due to castte () casting. I changed the mat image data type in the second case to * CV_64FC3 *, so I can use double [] instead of byte [], and it solved the problem.

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

FYI, I also did some time measurement, and using the second method is much faster than the first method.

+9
source share

Found a simple and working solution after much searching -

 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 

Note. An important point that is not mentioned anywhere on the network is that the put method does not write pixels to Input.jpg . It just updates the img matrix values. Therefore, the above code does not change anything in the input image. To create a visible output, the img matrix must be written to a file, i.e. Output.jpg in this case. In addition, using img.get(i, j) seems to be the best way to process matrix elements, rather than using the decision made above, since it helps to better visualize and work with the image matrix and does not require a large adjacent memory allocation.

+1
source share

All Articles