Donnerstag, 23. Juni 2016

Java: Create OpenCV Mat from BufferedImage.TYPE_BYTE_BINARY

In some cases it is very easy to migrate BufferedImage to Open CV Mat and vice-versa. The reason is that certain OpenCV Mat types and corresponding BufferedImages types use an identical storage format in their internal byte buffer.

CvType.CV_8UC3 corresponding to BufferedImage.TYPE_3BYTE_BGR.
CvType.CV_8UC1 corresponding to BufferedImage.TYPE_GRAY

You can easily create an OpenCV Mat from a BufferedImage with the following code:

BufferedImage inputImage = ...
Mat mat = null;

if (inputImage.getType() == BufferedImage.TYPE_BYTE_GRAY) {

  mat = new Mat(inputImage.getHeight(), inputImage.getWidth(),
     CvType.CV_8UC1);

  mat.put(0, 0, ((DataBufferByte) inputImage.getRaster().
     getDataBuffer()).getData());

} else if (inputImage.getType() == BufferedImage.TYPE_3BYTE_BGR) {

  mat = new Mat(inputImage.getHeight(), inputImage.getWidth(),
     CvType.CV_8UC3);

  mat.put(0, 0, ((DataBufferByte) inputImage.getRaster().
     getDataBuffer()).getData());
}


This code only supports GRAYSCALE and 3BYTE_BGR BufferedImage.

To get a BufferedImage from an OpenCV Mat instance the code is quite simliar:

// Create BufferedImage with dimensions and type (corresponding to Mat)
BufferedImage img = new BufferedImage(mat.width(), mat.height(),
  BufferedImage.TYPE_BYTE_GRAY);
   
// BufferedImage internat byte[] storage
byte[] data = ((DataBufferByte) codeImage.getRaster().getDataBuffer()).getData();

// Write image data
mat.get(0, 0, data);


Dealing with BufferedImage.TYPE_BYTE_BINARY



There is no CvType corresponding to BufferedImage.TYPE_BYTE_BINARY - or at least I did not find it.
So I created a CvType.CV_8UC1 (Grayscale) Mat with dimensions of the BufferedImage. After that the code iterates cols and rows of the Image and writes 0 (black) or 255 (white) to the OpenCV Mat.



BufferedImage img = ...

Mat mat = new Mat(img.getHeight(), img.getWidth(), CvType.CV_8UC1);
   
byte[] white = new byte[] { (byte) 255 };
byte[] black = new byte[] { (byte) 0 };
   
for (int x=0; x<img.getWidth(); x++) {
  for (int y=0; y<img.getHeight(); y++) {
    if (img.getRGB(x, y) == Color.BLACK.getRGB()) {
      mat.put(y, x, black);
    } else {
      mat.put(y, x, white);
    }
  }
}


Please note: img.getRGB(x,y) but mat.put(y,x). Otherwise the resulting Mat is rotated by 90 degrees and cut.


Keine Kommentare:

Kommentar veröffentlichen