1

我有一个 RGB 图像(uint8 类型),我想执行以下过程:

  1. 将图像量化为 16 级(每层)
  2. 计算每个RGB 组合的直方图:首先我需要一个 16*16*16 矩阵来保存这些值 - 即,如果我们表示直方图矩阵hist,那么hist(2,9,3)应该保存直方图中的像素数量,强度级别为 r=2,g= 9, b=3 etc. 下一阶段是将其重塑为 4096*1 向量(但这是最简单的部分)

现在我有以下实现:

function hist = compRGBHist(I)
    I = I./16 % quantize to 16 color levels
    hist = zeros(16,16,16);
    [m, n, ~] = size(I);
    for i=1:m
        for j = 1:n
            rgb = impixel(I,j,i);
            r = rgb(1);
            g = rgb(2);
            b = rgb(3);
            A(r,g,b) = A(r,g,b) + 1;
        end
    end
    hist = reshape(hist, 4096, 1);
end

此实现有效,但速度非常慢 - 我需要重复该过程 100 次(作为实现粒子过滤器的一部分),即使在尺寸为 ~80*40 的非常小的图像(实际上是图像部分)上执行它需要很长时间。我正在寻找一种更有效的方法来做到这一点。谢谢!

4

3 回答 3

4

您可以使用位移将 RGB 的 4 位值转换为 12 位值:

I = uint16(bitshift(I,-4));   % make sure the integer is large enough
twelvebit = bitshift(I(:,:,1),8) + bitshift(I(:,:,2)),4) + I(:,:,3);

这将产生如下所示的值:

0 0 0 0   R R R R   G G G G   B B B B
-------   -------   -------   -------
 unused     red      green      blue

现在您的值在 [0..4095] 范围内,您可以计算 4096 个 bin 的直方图。

于 2017-05-09T20:17:47.680 回答
3

我喜欢accumarray这里:

function hist = compRGBHist(I)
    I = bitshift(I, -4); % quantize to 16 color levels
    R = I(:,:,1) + 1; % +1 to be in [1..16]
    G = I(:,:,2) + 1;
    B = I(:,:,3) + 1;
    A = accumarray([R(:), G(:), B(:)], 1, [16,16,16]);
    hist = reshape(A, 4096, 1);
end

PS:烧杯的bitshift解决方案可能是最好的。

于 2017-05-09T20:37:56.137 回答
1

如果将 uint8 (0..255) 除以 2^4,则最终得到的范围是 (0..16) 而不是 (0..15)。我认为您应该首先减去 2^3,以确保您最终得到 16 个垃圾箱。

I = randi([0 255],512,512,3,'uint8'); %example data
I = (I-2^3)./2^4;
I = uint16(I);
I(:,:,2)=I(:,:,2)*2^4;
I(:,:,3)=I(:,:,3)*2^8;
I = sum(I,3,'native');
h=hist(I(:),[0:4095]);
h=reshape(h,[16 16 16]);
于 2017-05-09T20:21:04.300 回答