更快版本的dec2bin函数用于转换多个元素?

时间:2009-10-09 15:18:43

标签: matlab binary

我正在读取一个位图文件,并将每个的RGB值从0到255转换为二进制。

因此240 x 320位图将具有230400 RGB值进行转换。原来的dec2bin函数太慢了,所以我写了自己的函数,因为我知道我的值总是在0到255之间。

但是,通过230400值仍然需要大约。在我的机器上6秒,单色位图大约需要2.3秒。

无论如何,加速时间不到1秒甚至更好0.5秒,因为我的应用程序每毫秒计算一次?

这是我的代码:

function s = dec2bin_2(input)

if input == 255
    s = [1;1;1;1;1;1;1;1];
    return;
end

s = [0;0;0;0;0;0;0;0];

if input == 0
    return;
end

if input >= 128
    input = input - 128;
    s(1) = 1;
    if input == 0
        return;
    end
end

if input >= 64
    input = input - 64;
    s(2) = 1;
    if input == 0
        return;
    end
end

if input >= 32
    input = input - 32;
    s(3) = 1;
    if input == 0
        return;
    end
end

if input >= 16
    input = input - 16;
    s(4) = 1;
    if input == 0
        return;
    end
end

if input >= 8
    input = input - 8;
    s(5) = 1;
    if input == 0
        return;
    end
end

if input >= 4
    input = input - 4;
    s(6) = 1;
    if input == 0
        return;
    end
end

if input >= 2
    input = input - 2;
    s(7) = 1;
    if input == 0
        return;
    else
        s(8) = 1;
    end
end
end

我在想如果我在MATLAB中无法做到这一点,那么我可能会用C ++进行转换。这是可取的吗?

感谢。

4 个答案:

答案 0 :(得分:10)

更快的方法是使用查找表。由于您知道所有值都是0到255之间的强度,因此您可以构造每个值的二进制等值来加速该过程。

% build table (computed once) [using gnovice option#1]
lookupTable = cell2mat(arrayfun(@(i)bitget([0:255]',9-i),1:8,'UniformOutput',0));

% random' image
I = randi(256, [240 320])-1;

% decimal to binary conversion
binI = lookupTable(I(:)+1,:);

在我的机器上,它平均花费0.0036329秒(仅转换)。请注意,查找表几乎没有空间开销:

>> whos lookupTable
  Name               Size            Bytes  Class    Attributes
  lookupTable      256x8              2048  uint8 

答案 1 :(得分:4)

选项#1:遍历每个像素并使用BITGET

您可以循环覆盖图像中的每个像素(或RGB值),并使用BITGET获取0和1的向量。以下是如何使用BITGET的示例:

>> bitget(uint8(127),8:-1:1)  % Get bits 8 through 1 for a uint8 value

ans =

    0    1    1    1    1    1    1    1

选项#2:带BITGET的矢量化解决方案

可以创建一个矢量化解决方案,在其中循环每个而不是每个像素,每次通过循环对整个图像矩阵执行BITGET操作。以下是一个这样的实现:

function B = get_bits(A,N)
  % Gets the N lowest bits from each element of A
  B = zeros([size(A) 0]);
  nDims = ndims(A)+1;
  for iBit = N:-1:1
    B = cat(nDims,B,bitget(A,iBit));
  end
end

如果矩阵A是2-D(n-by-m)或3-D(n-by-m-by-p),矩阵B将更大一维。额外维度的大小为N,索引1中的位数最高。您可以索引此维度以获取位值,或将B转换为更容易可视化的形式。以下是用法示例:

>> A = uint8([126 128; 127 129]);  % A 2-by-2 matrix of uint8 values
>> B = get_bits(A,8);              % B is a 2-by-2-by-8 matrix
>> B(:,:,1)                        % Get bit 8 for each value in A

ans =

     0     1
     0     1

>> reshape(B,4,8)                  % Reshape B into a 4-by-8 matrix

ans =

     0     1     1     1     1     1     1     0
     0     1     1     1     1     1     1     1
     1     0     0     0     0     0     0     0
     1     0     0     0     0     0     0     1

答案 2 :(得分:0)

你不能用bitand直接得到这些位吗?

s(0) = 256 bitand input
s(1) = 128 bitand input
s(2) = 64 bitand input

等...

答案 3 :(得分:0)

这种问题(在大型数组上执行每元素操作,因为Matlab的内置代码太慢)有时会在Java中调用解决方案,因为Matlab在JRE上运行并且转换/传递数组参数是通常是一个相当快速的操作。

gnovice的解决方案听起来对你有用,但是如果你遇到一个你无法在纯Matlab中解决的情况,并且你精通Java,那么考虑编写一个自定义的JAR文件。这很容易。 (好吧,比试图将C ++与Matlab接口要容易得多!)