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

后端 未结 2 1325
生来不讨喜
生来不讨喜 2020-12-28 10:11

I am a beginner in using OpenCV for JAVA. I want to access individual pixel values of an image matrix. Since, JAVA jar for OpenCV doesn\'t offer nice functions like C++, I r

相关标签:
2条回答
  • 2020-12-28 10:38

    Found a simple and working solution after a lot of 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 has not been mentioned anywhere online is that the method put does not write pixels onto Input.jpg. It merely updates the values of the matrix img. Therefore, the above code does not alter anything in the input image. For producing a visible output, the matrix img needs to be written onto a file i.e., Output.jpg in this case. Also, using img.get(i, j) seems to be a better way of handling the matrix elements rather than using the accepted solution above as this helps in visualizing and working with the image matrix in a better way and does not require a large contiguous memory allocation.

    0 讨论(0)
  • 2020-12-28 10:43

    It was happening because of byte() casting. I changed the data type of mat image in second case to *CV_64FC3* so that 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 second method is way faster than first method.

    0 讨论(0)
提交回复
热议问题