IplImage/Mat to byte array and back with JavaCV 1.2

1.9k views Asked by At

It seems to be too many times "already answered" topic, but nonetheless I was not able to find a workable solution. I need to serialize IplImages and Mats with JavaCV. I cannot use the file system, ad I must stick to JavaCV 1.2/JavaCPP 1.2.4/OpenCV 3.1 (note: I cannot use the OpenCV's own Java wrapping - I have to work with JavaCV). I found a number of recommendations on Stackoverflow, but they all either: 1) use a deprecated method, or 2) use methods which no longer exist. I am aware that IplImages and Mats are easily interchangeable, so a solution for one would be readily applicable for the other. The ideal solution would be a way to convert IplImage/Mat to byte array and back. I hope you guys can help.

1

There are 1 answers

6
Andrew Scott Evans On

I have a solution for the most recent JavaCV. Actually, several. I was having trouble with some images so my second attempt at conversion to a byte array produced a more consistent result. The solutions here are in Scala.

To convert to a byte array with the image data, you need to get the bytes.

Mat m = new Mat(iplImage);
ByteBuffer buffer = this.image.asByteBuffer();
Mat m = new Mat(this.image);
int sz = (m.total() * m.channels());
byte[] barr = new byte[sz]();
m.data().get(barr);

Convert to a java.nio.ByteBuffer, use the total size from your image (I converted to a mat), and get the data. I forget whether m.total * m.channels returns a double, a long, an int or a float. I was using .toInt in Scala.

Another option is to use a BufferedImage. Some of my images were coming out a little odd using just JavaCV.

BufferedImage im = new Java2DFrameConverter().convert(new OpenCVFrameConverter.ToIplImage().convert(this.image))
BytearrayOutputstream baos = new ByteArrayOutputStream();
byte[] barr = null;
try{
    ImageIO.write(im,"jpg",baos);
    baos.flush();
    barr = baos.toByteArray();
}finally{
    baos.close();
}
//This could be try with resources but the original was in Scala.

To convert from a byte array to an IplImage, I actually use a Buffered Image for reliability.

ImplImage im = null;
InputStream in = new ByteArrayInputStream(bytes);
try {
    Mat m = new Mat(image.getHeight,image.getWidth,image.getType,new BytePointer(ByteBuffer.wrap(image.getRaster.getDataBuffer.asInstanceOf[DataBufferByte].getData)));
    im = new IplImage(m);
}finally{
    in.close();
}
//Again this could be try with resources but the original example was in Scala