【问题标题】:matlab packing bits into byte arraymatlab将位打包成字节数组
【发布时间】:2013-01-07 14:18:14
【问题描述】:

在 Matlab 中,我试图将任意位长度的无符号整数(例如,3 位整数数组)打包到 uint8 数组中。给定提示here,我可以生成适用于“小”数组(例如 10,000 个元素)的代码,但它会占用大型数组(例如 1600 万个元素)的所有内存。我使用的代码如下,借用以前的帖子:

function x_bytes = stuff_bits(x, n)
    r = dec2bin(x,n);                 % bitstring for each uint in x
    s = reshape(r',[],1);             % one continuous string of bits
    t = reshape(str2num(s),8,[])';    % array of 8-bit numbers (stuffed)
    u = t*(2.^(size(t,2)-1:-1:0))';   % array of bytes representing all the bits stuffed together
    x_bytes = uint8(u);              % should be compressed byte stream
end

我意识到我正在使用一个 uint,将其转换为字符串,然后将其转换回位;我还读到 dec2bin 效率不高。

当我尝试使用 1600 万个元素(在具有 8 GB 内存的 64 位 Windows 机器上)时,所有内存都被消耗掉了。废话。所以我循环遍历小节,完成 1600 万个元素大约需要 10 分钟。所以,有些东西效率很低。

有人有更好的方法来生成像 python 的 BitArray 这样的位字符串吗?

谢谢,

【问题讨论】:

  • 所以你从一个由x十进制数组成的数组开始,你想把每一个转换成一个恒定长度(3位)的二进制数,然后你想压缩所有的将 3 位数字转换为位序列,然后将其分成 uint8s?所以x=[6 2 5 4] -> [110,010,101,100] -> [110010101100] ->[00001100,10101100] -> [12,172]?还是我不明白这个问题?
  • 另外,您正在将t 转换为 8 个非常大的数字,而不是一堆 8 位数字。试试u=(2.^(7:-1:0))*t;

标签: matlab bitarray


【解决方案1】:

似乎类似于this onethis one

在第一个中,建议在 for 循环中使用 dec2bitvec。这对你来说可能已经足够了(虽然很慢)。

第二个建议使用 bitget 创建一个查找表,然后使用它(而不是使用 dec2bit 或 dec2bitvec)

您可以尝试使用“中间”的东西。

B = 3; % Number of bits per int.
A = randi(7, 16000000, 1); % 16M random elements between 1 and 7 (3bits).

tic
% get each group of bits in a column of K.
K = cell2mat(arrayfun(@(bit)bitget(A, B+1-bit), 1:B, 'UniformOutput', 0))';
% reshape to have them in 8 packs
K = reshape(K, [8, numel(K)/8])';
% get the uint8 vec.
U = K*(2.^(size(K,2)-1:-1:0))';
toc

我的用时 3.5 秒。 (Win8 64 位,i5 4GB 内存)

此代码不是创建查找表,而是创建一个矩阵 (K),其中包含每个整数的位值(存储在列中),对其进行整形(以创建 8bin 值),然后使用与之前相同的数学创建 uint8 向量。

【讨论】:

  • 优秀的解决方案 - 谢谢。转换为字符串并返回一定会终止该进程。您的解决方案保持一切二进制。由于我在输入数组中没有固定位数(有时我有 3 位数字,有时是 5 位,有时是 12 位),我需要一些通用的。
  • @rocketman 我刚刚注意到,由于 reshape 功能,这仅在总位数可被 8 整除(例如 3bits * 16M 元素)时才有效。为了使其在任何情况下都能正常工作,您可能需要将其转换为向量 (1 x N),然后在重塑之前在其左侧填充一些位。
  • 是的 - 我同意它只适用于 B*numel(A)/8,但这很容易确保。该应用程序用于图像数据的独特压缩算法。显着提高速度……从 450 秒到 0.23 秒。非常感谢!
【解决方案2】:

这是我为将位矩阵转换为 n 位长数字而创建的代码:

function [ uD10 ] = bits_to_n_bit_integers( A, n)
%bits_to_n_bit_integersTurns vector matrix of bits in A into a vector matrix of 
%n bits long numbers. 
%B is 1 for a bit matrix
%   Detailed explanation goes here

B = 1;
% get each group of bits in a column of K.
K = cell2mat(arrayfun(@(bit)bitget(A, B+1-bit), 1:B, 'UniformOutput', 0))';
%make sure there is multiple of B
K = K(:);
while ~(mod(numel(K),n) == 0)
    K = [0;K];
end
K = K(:);
% reshape to have them in 8 packs
K = reshape(K, [n, numel(K)/n])';
% get the uint8 vec.
UD = K*(2.^(size(K,2)-1:-1:0))';

uD10=bi2de(K);

end

:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多