Ask Your Question
0

Converting BufferedImage to Mat in Java

asked 2014-02-13 10:55:51 -0600

Hinesh gravatar image

I've tried this link and have the code below. My program imports images in a BufferedImage format and then displays it to the users. I'm using the matchingTemplate function in OpenCV which requires me to convert it to a Mat format.

The code works if I import the image -> convert it to Mat then save the image using imwrite. The program also allows the user to crop an image and then use the Template matching to compare it to another image. The issue come when I tried to convert the cropped image to Mat I need to convert it from Int to Byte using this code:

im = new BufferedImage(im.getWidth(), im.getHeight(),BufferedImage.TYPE_3BYTE_BGR);

This however results in a black image. But if I get rid of it it only works with imported images and not cropped. What is going on here? I'm certain it is something to do with the coversion process as I have tested the template matching function using read in images.

// Convert image to Mat
public Mat matify(BufferedImage im) {
    // Convert INT to BYTE
    //im = new BufferedImage(im.getWidth(), im.getHeight(),BufferedImage.TYPE_3BYTE_BGR);
    // Convert bufferedimage to byte array
    byte[] pixels = ((DataBufferByte) im.getRaster().getDataBuffer())
            .getData();

    // Create a Matrix the same size of image
    Mat image = new Mat(im.getHeight(), im.getWidth(), CvType.CV_8UC3);
    // Fill Matrix with image values
    image.put(0, 0, pixels);

    return image;

}
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2019-07-24 05:30:24 -0600

This is probably a little late, but may be others can benefit from this answer:

Ok, in the line

//im = new BufferedImage(im.getWidth(), im.getHeight(),BufferedImage.TYPE_3BYTE_BGR);

just an empty instance of BufferedImage is created, resulting output of a black image.

The cause of the problems is that depending on the case either a DataBufferedByte or DataBufferInt is created. A look in class Robot's method createScreenCapture() reveals the encoding. A case distinction is needed here, converting a DataBufferInt if necessary. I have added a (very crude) conversion routine to your method above:

public Mat matify(BufferedImage sourceImg) {

    long millis = System.currentTimeMillis();

    DataBuffer dataBuffer = sourceImg.getRaster().getDataBuffer();
    byte[] imgPixels = null;
    Mat imgMat = null;

    int width = sourceImg.getWidth();
    int height = sourceImg.getHeight();

    if(dataBuffer instanceof DataBufferByte) {      
            imgPixels = ((DataBufferByte)dataBuffer).getData();
    }

    if(dataBuffer instanceof DataBufferInt) {

        int byteSize = width * height;      
        imgPixels = new byte[byteSize*3];

        int[] imgIntegerPixels = ((DataBufferInt)dataBuffer).getData();

        for(int p = 0; p < byteSize; p++) {         
            imgPixels[p*3 + 0] = (byte) ((imgIntegerPixels[p] & 0x00FF0000) >> 16);
            imgPixels[p*3 + 1] = (byte) ((imgIntegerPixels[p] & 0x0000FF00) >> 8);
            imgPixels[p*3 + 2] = (byte) (imgIntegerPixels[p] & 0x000000FF);
        }
    }

    if(imgPixels != null) {
        imgMat = new Mat(height, width, CvType.CV_8UC3);
        imgMat.put(0, 0, imgPixels);
    }

    System.out.println("matify exec millis: " + (System.currentTimeMillis() - millis));

    return imgMat;
}

The runtime measurement can be omitted obviously.

Greetings

edit flag offensive delete link more

Question Tools

Stats

Asked: 2014-02-13 10:55:51 -0600

Seen: 12,619 times

Last updated: Feb 13 '14