Ask Your Question
13

How to get and modify the pixel of Mat in Java?

asked 2012-06-08 08:47:00 -0500

Kirill Kornyakov gravatar image

updated 2017-08-20 04:02:00 -0500

I want to read and modify some pixels in my matrix. How can I do that in Java? Is there any equivalent for the C++ Mat::at method?

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
20

answered 2012-06-08 14:02:54 -0500

Andrey Pavlenko gravatar image

updated 2012-06-08 14:03:38 -0500

In Java you can use Mat::get() and Mat::put() methods. One pixel can be read by

double[] Mat::get(int row, int col)

One or few pixels can be written by

Mat::put(int row, int col, double... data)

But if you're going to work with many pixels, it's better to get all the Mat data at once to Java primitive array, work with it in Java, and then put it back to Mat with a single JNI call. 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 look like following:

Mat m = ...  // assuming it's of CV_8U type
byte buff[] = new byte[m.total() * m.channels()];
m.get(0, 0, buff);
// working with buff
// ...
m.put(0, 0, buff);
edit flag offensive delete link more

Comments

Thanks for the answer. However I don't quite understand the use of the byte array. I tried, based on the above suggestion, using m.get(0, 0, buff), and m.get(0,0)[0] (for a grayscale image). The latter resulted in the expected value; the former however (using the byte array) gave a large value (exceeding 255) that I don't understand. My image is of type CV_8U.

user1446598 gravatar imageuser1446598 ( 2013-03-10 12:51:16 -0500 )edit

Not working for me too....

jishnu gravatar imagejishnu ( 2015-02-10 05:04:23 -0500 )edit

Role of an array in Mat Pixel access/modify:

Consideran Mat 2*2 with single channel of type byte.Represent it with by m

get the image data m.rows->2; m.cols->2; m.typ->8uc1;

suppose elements in m are,

5 10 15 20

m.get(0,0)[0] -->5;;//returns only specified location element.

Means we have to call m.get() 4 times to get all elements in m.

Use af array in accessing;

Suppose byte [] b=new byte[2];//size is 2 here

m.get(0,b)--> {5,10};//retuns the row of length specified by byte b

where 0--> id for row of mat ..To get next row we should use 1

now, b[0]-->5; b[1]-->10;

Means we have to call m.get() 2 times to get all elements in m.

"m.get() 2 times" is speeder than "m.get() 4 times ...(more)

Venky009 gravatar imageVenky009 ( 2015-11-18 00:36:42 -0500 )edit
1

Is there a way to just actually use the underlying native array instead of making a copy to a new byte array?

nic gravatar imagenic ( 2016-09-19 13:48:00 -0500 )edit

How do I get the value of R, G and B from the Mat of type CV_8UC3?

ImGladYouCame gravatar imageImGladYouCame ( 2017-10-10 08:43:51 -0500 )edit

To separate from serial to parallel arrangement of the channels, for example to get R, B, and B from the Mat of type CV_8UC3

   public static byte[][] getMultiChannelArray(Mat m) {
    //first index is pixel, second index is channel
    int numChannels=m.channels();//is 3 for 8UC3 (e.g. RGB)
    int frameSize=m.rows()*m.cols();
    byte[] byteBuffer= new byte[frameSize*numChannels];
    m.get(0,0,byteBuffer);

    //write to separate R,G,B arrays
    byte[][] out=new byte[frameSize][numChannels];
    for (int p=0,i = 0; p < frameSize; p++) {
        for (int n = 0; n < numChannels; n++,i++) {
            out[p][n]=byteBuffer[i];
        }
    }
    return out;
}

Note: signed byte in java may need to be promoted to int

tkaczyk gravatar imagetkaczyk ( 2017-12-16 11:30:13 -0500 )edit
-2

answered 2019-01-17 03:42:15 -0500

sherylbrock gravatar image

updated 2019-01-18 02:32:39 -0500

berak gravatar image

simple and working solution...

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
edit flag offensive delete link more

Comments

2

sorry, but no, (while being techincally correct !) that's terribly inefficient.

get() and put() are random access operators, those should NEVER be use for operations on the whole image !

  • you could just multiply() the whole Mat by 2 (that's the preferred solution)
  • you could get() all the pixes into a byte[] buffer, modify those, and put() them back, like in @Andrey Pavlenko 's answer.
berak gravatar imageberak ( 2019-01-17 03:46:56 -0500 )edit

@sherylbrock i also downvoted but sometimes a wrong answer could be useful to know what is wrong so please don't modify your answer and continue to contribute.(+1 inside of me)

sturkmen gravatar imagesturkmen ( 2019-01-17 04:04:52 -0500 )edit

@sherylbrock -- i removed your spam link. please don't do that ;(

berak gravatar imageberak ( 2019-01-18 02:33:08 -0500 )edit

I tried OpenCV 3.x and OpenCV 4.x. There is no class Highgui. There is a class HighGui which can not load images. Which API do you use?

hunter3 gravatar imagehunter3 ( 2019-02-22 04:32:24 -0500 )edit

@hunter3, please don't comment on unrelated questions, but ask your own, thank you.

berak gravatar imageberak ( 2019-02-22 05:01:39 -0500 )edit

use Highgui.selectROI("Title", matName); instead of imshow and Imgcodecs.imwrite("Image.jpg", matName); instead of Highgui.imwrite("Output.jpg", img);

SRG-FTL gravatar imageSRG-FTL ( 2019-02-23 18:43:23 -0500 )edit
Login/Signup to Answer

Question Tools

3 followers

Stats

Asked: 2012-06-08 08:47:00 -0500

Seen: 49,453 times

Last updated: Feb 22