Matlab: преобразовать матрицу uint8 (состоящую из 0 и 1) для экспорта в виде двоичных данных.

Моя проблема :

У меня есть матрица uint8 1920x1080, сделанная из нулей и единиц в Matlab. Назовем это моим «образом». Что я хочу сделать, так это экспортировать это изображение как двоичное, что означает, что каждый байт вывода должен содержать информацию о 8 пикселях. Короче говоря: я хочу 1 бит на пиксель.

Если я правильно понял, я не могу просто преобразовать его в двоичный файл в Matlab с помощью функции «logical(...)», потому что логические значения по-прежнему хранятся в памяти как 8 бит (хотя их значение может быть только 0 или 1, конечно) .

Зачем мне это нужно?

Я хочу экспортировать изображение через «.dll», который принимает изображение в определенном формате (для более быстрой передачи на USB-устройство).

Формат вывода:

Вот что ожидает «.dll»: (1 байт = 8 последовательных битов)

  • изображение читается слева направо, затем сверху вниз (обычное соглашение)
  • every byte of data represents 8 pixels, e.g.
    • (1st byte) = [px8|px7|...|px1]
    • (2-й байт) = [px16|px15|...|px9]
    • и так далее.
  • обратите внимание, что каждая строка изображения имеет 1920 пикселей (которые можно разделить на 8, 1920/8 = 240), поэтому на строку изображения приходится 240 байтов.

Мой вопрос :

Как мне реорганизовать данные? Я думаю, это зависит от того, как Matlab хранит данные в памяти (а затем отправляет их в любую «.dll»)? Я понятия не имею об этом...

Вот код, который я бы использовал, если бы не ожидалось никаких трюков с памятью. Идея состоит в том, чтобы взять каждые 8 ​​пикселей и построить из них 8-битное значение в правильном порядке, например. эти значения пикселей (1 0 0 0 0 0 1 0) станут равными 65 (выражены в десятичном виде). Затем я бы отправил новую матрицу в «.dll» и надеюсь, что это сработает.

FinalImage=zeros(1920,240); % 240 = number of bytes per line
for myRow=1:1080
    for myByte=1:240 
        currentByte=0;
        for myBit=0:7
            currentByte=currentByte + 2^(7-myBit) * Image(myRow, 1 + 8*(myByte-1) + myBit );
        end
        FinalImage(myRow, myByte) = currentByte;
    end
end

Решение :

С помощью Divakar я, наконец, забыл о циклах и предпочел этот простой код:

% convert every 8 pixels (values 0 or 1) in a row to one single pixel (value 0 to 255)
% (bi2de option used : "left most significant bit" in my case)
% (make sure the width of your image is a multiple of 8)

vect=bi2de(reshape(input_img',8,[])','left-msb');
img=reshape(vect,img_width/8,[])';

Это решение может быть полезно для кого-то еще, в тот или иной день!


person Ghislain Bugnicourt    schedule 03.06.2014    source источник


Ответы (1)


Предполагая, что input_image — это входная двоичная матрица, а output_dll_filepath — путь к выходному dll файлу, вы можете попробовать этот cell-array подход:

Код

%// Convert to 8-bit data
[M,N] = size(input_image)
cell1 = mat2cell(input_image,ones(1,M),8.*ones(1,N/8))
output_data = cellfun(@(x) bin2dec(num2str(fliplr(x),'%1d')),cell1);
output_data = reshape(output_data',[],1)

%// Write the 8-bit data as a dll file
fid = fopen(output_dll_filepath , 'w');
fwrite(fid, output_data, 'uint8');
fclose(fid);

Или используйте -

output_data = bin2dec(fliplr(num2str(reshape(input_image',8,[])','%1d')))

а затем используйте Write the 8-bit data as a dll file, использованный ранее, как это было.


Или просто это -

fid = fopen(output_dll_filepath , 'w');
fwrite(fid, reshape(input_image',8,[]), 'ubit1');
fclose(fid);
person Divakar    schedule 03.06.2014
comment
Спасибо за Ваш ответ. Я сделал ошибку, сказав, что использовал dll, на самом деле я использую библиотеку, связанную с dll. Я вызываю его функции из Matalb с помощью calllib(...). Мои выходные данные должны быть аргументом этого вызова calllib. (поэтому fopen и fwrite не подходят для этого случая) В любом случае, ваше второе решение мне очень помогло, но код все еще довольно медленный для матрицы 1080 * 1920 (у меня есть 1024 таких матрицы для загрузки). Я продолжаю искать. :) - person Ghislain Bugnicourt; 04.06.2014
comment
@GhislainBugnicourt Второе решение должно быть быстрым, поскольку оно позволяет избежать массивов ячеек, которые использовались в более ранних подходах, но если вы работаете с 1024 такими матрицами, то вы вызываете такой код много раз и выполняете 1024 операции ввода-вывода для медленного жесткого водить машину. Вы не можете записать в один файл все эти 1024 матрицы вместе взятые? - person Divakar; 04.06.2014
comment
В конце концов я сделал несколько изменений (в том числе объединил все матрицы с функцией cat() перед отправкой их в один блок в библиотеку, как вы предложили), но ключом к проблеме была эта строка: vect=bi2de(reshape(input_img ',8,[])','left-msb');. Он адаптирован из вашего ответа, поэтому я выбираю ваше решение, но добавляю реальный ответ в сам вопрос. Спасибо ! - person Ghislain Bugnicourt; 06.06.2014