Matlab: Как правильно использовать класс Java ImageIO для получения буферного изображения

#java #matlab #javax.imageio

#java #matlab #javax.imageio

Вопрос:

Я пытаюсь создать макет в Matlab для некоторых данных изображения в базе данных. Данные изображения взяты из Java, выводятся в виде массива байтов в кодировке base64. Я не знаком с форматом [java image]. Тем не менее, я написал следующий код Matlab на основе некоторой java, написанной кем-то, кто работает со мной. Они следуют одной и той же базовой схеме, и Java-код способен отлично считывать изображение. Код Matlab выглядит следующим образом:

 function [ result ] = queryDb( theQuery )
  conn   = database( ... ); % connect to the database
  result = fetch( exec( conn, theQuery ) );
  result = result.Data;

  close( conn );
end

data = queryDb( 'sql query to get the data' );
data = uint8( data{1,1} );
data = org.apache.commons.codec.binary.Base64.decodeBase64( data );
data = uint8( 127   data ); % the base64 decoder returns signed int8

import javax.imageio.ImageIO;
import java.io.ByteArrayInputStream;

dataStream    = ByteArrayInputStream( data );
bufferedimage = ImageIO.read( dataStream );
  

При проверке bufferedimage это пустой массив double , в отличие от экземпляра java BufferedImage .

Я провел несколько тестов на dataStream , чтобы увидеть, работает ли он так, как ожидалось; своего рода мини-модульный тест в духе:

 for jj = 1:10
  for kk 1:10
    assert( dataStream.read() == data(kk) );
  end;

  dataStream.reset();
end;
  

Он проверен, так что это наводит меня на мысль, что проблема связана с ImageIO или моим использованием его.

К сожалению, ни один из примеров, которые я нашел для использования ImageIO (и некоторых других API), не используется так, как я описываю здесь (то есть в Matlab).

Этот код использует java.io.ByteArrayInputStream таким же образом — в том смысле, что предоставленные данные представляют собой массив байтов.

Этот код, по сути, является тем, что я хочу сделать — преобразовать изображение Java в массив Matlab. К сожалению, они обманывают, беря изображение Matlab, превращая его в изображение java, а затем возвращая его обратно.

Этот код использует ImageIO, но он делает это путем чтения из файлового потока. Я попытался записать данные в файл, а затем прочитать их в using java.io.File , но в любом случае я получаю тот же результат.

Итак, я в растерянности.

Комментарии:

1. Каковы определения данных, потока данных и BufferedImage?

2. Matlab не является декларативным языком. Способ написания кода в сочетании с моими комментариями пояснит, что они представляют. Данные — это изображение Java, хранящееся в виде массива int8. Я не знаком с форматом. Если вы достаточно знакомы с Java, то это может быть более очевидным. Проблема в самой последней строке. До того момента, когда возникает поток данных, все ведет себя так же, как java-версия этого кода. Чтение из потока возвращает одинаковые данные с обеих сторон. Однако ImageIO.read() некорректно работает из Matlab, и я не уверен, почему.

Ответ №1:

Подход, изложенный в вопросе, работает… единственное, что у меня есть, что каким-либо образом отличается от приведенного выше кода, это то, что я не добавляю 127 в массив uint8:

 % Do all the imports
% sql query to get the data
dataStream    = ByteArrayInputStream( decodeBase64( rows.data{1} ) );
bufferedImage = ImageIO.read( dataStream );
[w h] = deal( theWidth, theHeight );
imageData     = uint8( bufferedImage.getData.getPixels( 0,0,w,h,[] ) );
imageData     = permute( reshape( imageData, [3 w h] ), [2 3 1] );

imshow( imageData );
% voila
  

отредактируйте, включив текст @kchja, на который дана ссылка, на случай, если эта ссылка станет недействительной:

Тема: Как я могу преобразовать объект «Java Image» в матрицу изображений MATLAB?

Описание проблемы: Функция IM2JAVA доступна для преобразования изображения MATLAB в изображение Java. Я хотел бы преобразовать изображение Java в изображение MATLAB.

Решение: Нет встроенной функции для преобразования изображений Java в изображения MATLAB. Однако, используя Java API, вы можете извлечь данные из изображения Java и сохранить их в виде матрицы, которая является представлением изображения MATLAB.

Ниже приведен пример преобразования изображения MATLAB в Java и обратно в изображение MATLAB. Изображение, используемое в этом примере, является частью демонстрационных версий MATLAB и находится по пути MATLAB. В этом примере функция «getPixels» Java-класса «Raster» возвращает значения RGB для изображения.

В зависимости от формата вашего Java-образа может потребоваться дополнительная работа. Изображения Java могут храниться в одном из многих форматов; функция «getPixels» возвращает пиксельные данные в этом формате. Для получения дополнительной информации смотрите страницу javadoc для java.awt.image.Класс Raster в http://java.sun.com/j2se/1.5.0/docs/api/java/awt/image/Raster.html

 % create java image
I = imread('office_3.jpg');
javaImage = im2java(I);

% get image properties
H=javaImage.getHeight;
W=javaImage.getWidth;

% repackage as a 3D array (MATLAB image format)
B = uint8(zeros([H,W,3]));
pixelsData = uint8(javaImage.getBufferedImage.getData.getPixels(0,0,W,H,[]));
for i = 1 : H
base = (i-1)*W*3 1;
B(i,1:W,:) = deal(reshape(pixelsData(base:(base 3*W-1)),3,W)');
end

% display image
imshow(B);
  

Ниже приведены два других способа реализовать это (в более
оптимизированный способ):

Пример 1: (Более быстрое выполнение)

 pixelsData = reshape(typecast(jImage.getData.getDataStorage, 'uint8'), 4, w, h);
imgData = cat(3, ...
        transpose(reshape(pixelsData(3, :, :), w, h)), ...
        transpose(reshape(pixelsData(2, :, :), w, h)), ...
        transpose(reshape(pixelsData(1, :, :), w, h)));
  

Пример 2:

 imgData = zeros([H,W,3],'uint8');
pixelsData = reshape(typecast(javaImage.getBufferedImage.getData.getDataStorage,'uint32'),W,H).';
imgData(:,:,3) = bitshift(bitand(pixelsData,256^1-1),-8*0);
imgData(:,:,2) = bitshift(bitand(pixelsData,256^2-1),-8*1);
imgData(:,:,1) = bitshift(bitand(pixelsData,256^3-1),-8*2);
  

Комментарии:

1. Просто для полноты картины, если кто-то собирается решить и эту проблему, MathWorks предлагает другое решение , как преобразовать BufferedImage в изображение Matlab uint8. Он также выдает изображения в правильной ориентации (когда я тестировал код Брайана Ванденберга, изображения были повернуты на 90 градусов).

2. ::nod::, Мне не нужно было слишком беспокоиться об ориентации, так что это даже не пришло мне в голову.