Преобразование объекта OpenCV Mat в BufferedImage


Я пытаюсь создать вспомогательную функцию с помощью Java API OpenCV, которая будет обрабатывать входное изображение и возвращать выходной массив байтов. Входное изображение представляет собой файл jpg, сохраненный в компьютере. Входное и выходное изображение отображаются в интерфейсе Java с помощью Swing.

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// Load image from file
Mat rgba = Highgui.imread(filePath);

Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0);

// Convert back to byte[] and return
byte[] return_buff = new byte[(int) (rgba.total() * rgba.channels())];
rgba.get(0, 0, return_buff);
return return_buff;

Когда return_buff возвращается и преобразуется в BufferedImage я получаю NULL обратно. Когда я комментирую функцию Imgproc.cvtColor, return_buff должным образом преобразуется в Буферизованное изображение, которое я могу отобразить. Похоже, что Imgproc.cvtColor является возврат объекта Mat, который я не смог отобразить в Java.

Вот мой код для преобразования из byte[] в BufferedImage:

InputStream in = new ByteArrayInputStream(inputByteArray);
BufferedImage outputImage = ImageIO.read(in);

В приведенном выше коде outputImage равен NULL

У кого-нибудь есть какие-нибудь предложения или идеи?
2 5

2 ответа:

ImageIO.read(...) (и Пакет javax.imageio в целом) предназначен для чтения / записи изображений из / в форматы файлов. То, что у вас есть, - это массив, содержащий "сырые" пиксели. Невозможно для ImageIO определить формат файла из этого массива байтов. Из-за этого он вернется null.

Вместо этого вы должны создать BufferedImage непосредственно из байтов. Я не очень хорошо знаю OpenCV, но я предполагаю, что результатом Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0) будет изображение в оттенках серого (8 бит/образец, 1 образец/пиксель). Это тот же формат, что и BufferedImage.TYPE_BYTE_GRAY. Если это предположение верно, вы должны быть в состоянии сделать:

// Read image as before
Mat rgba = Highgui.imread(filePath);
Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0);

// Create an empty image in matching format
BufferedImage gray = new BufferedImage(rgba.width(), rgba.height(), BufferedImage.TYPE_BYTE_GRAY);

// Get the BufferedImage's backing array and copy the pixels directly into it
byte[] data = ((DataBufferByte) gray.getRaster().getDataBuffer()).getData();
rgba.get(0, 0, data);

Делая это таким образом, вы экономите одно выделение большого массива байтов и одну копию массива байтов в качестве бонуса. :- )

Я использовал этот код, чтобы преобразовать объект коврик для Буферизованные изображения.

static BufferedImage Mat2BufferedImage(Mat matrix)throws Exception {        
    MatOfByte mob=new MatOfByte();
    Imgcodecs.imencode(".jpg", matrix, mob);
    byte ba[]=mob.toArray();

    BufferedImage bi=ImageIO.read(new ByteArrayInputStream(ba));
    return bi;
}