Matlab:创建分箱RGB直方图

时间:2015-11-19 14:33:35

标签: arrays matlab image-processing histogram

我想实现以下Matlab函数:

function hist = binnedRgbHist(im, numChannelBins)

如果图片为im且数字介于1到256 numChannelBins之间,则应创建一个大小为(numChannelBins)^3的直方图。

例如,如果numChannelBins 2 ,则应生成以下8个大小的直方图:

  1. R < 128, G < 128, B < 128
  2. 的像素数
  3. R < 128, G < 128, B >= 128
  4. 的像素数
  5. R < 128, G >= 128, B < 128
  6. 的像素数
  7. R < 128, G >= 128, B >= 128
  8. 的像素数
  9. R > 128, G < 128, B < 128
  10. 的像素数
  11. R > 128, G < 128, B >= 128
  12. 的像素数
  13. R > 128, G >= 128, B < 128
  14. 的像素数
  15. R > 128, G >= 128, B >= 128
  16. 的像素数

    就像创建一个立方体,其中每个轴代表(R,G和B)之一,其中每个轴被分成2个bin =&gt;最后,立方体中有8个箱子。

    我的问题:

    • 它有内置功能吗?
    • 如果没有,那么使用GPU以runtinme的方式实现它会更好吗?我应该更好地迭代像素一次并手动创建直方图,还是应该更好地迭代这些箱子并且每次都计算满足箱子条件的像素数量?

2 个答案:

答案 0 :(得分:1)

accumarray非常适合这一点。让

  • im:输入图片;
  • N:每个颜色分量的分档数。

然后

result = accumarray(reshape(permute(ceil(im/255*N), [3 1 2]), 3, []).', 1, [N N N]);

工作原理

  1. ceil(im/255*N)将每种颜色值量化为12,...,N
  2. reshape(permute(..., [3 1 2]), 3, []).'将量化图像转换为三列矩阵,其中每行是一个像素,每列是(量化的)颜色分量。
  3. accumarray(..., 1, [N N N])将该矩阵的每一行视为3D索引,并计算每个索引出现的次数,并给出不带0的填充索引。
  4. 示例1

    数据:

    >> N = 2;
    >> im = randi(256,4,5,3)
    im(:,:,1) =
       113   152   157    65   229
       138    71   215    39    41
        13   108   230   160   153
       142   128   125   220   214
    im(:,:,2) =
       208   215   182    27   230
       205   161     8    95   180
       225    53    73   129    31
       103    97   160    83   255
    im(:,:,3) =
       242    29   185    89    55
       202   225   156   174    96
       160   197    35    87   113
       244   176   146    85   120
    

    结果:

    result(:,:,1) =
         1     1
         3     4
    result(:,:,2) =
         2     4
         3     2
    

    例如,可以检查只有1个像素,所有R,G,B小于128.

    示例2

    数据:

    >> im = repmat(150,20,30,3);
    >> N = 4;
    

    结果:

    result(:,:,1) =
         0     0     0     0
         0     0     0     0
         0     0     0     0
         0     0     0     0
    result(:,:,2) =
         0     0     0     0
         0     0     0     0
         0     0     0     0
         0     0     0     0
    result(:,:,3) =
         0     0     0     0
         0     0     0     0
         0     0   600     0
         0     0     0     0
    result(:,:,4) =
         0     0     0     0
         0     0     0     0
         0     0     0     0
         0     0     0     0
    

    在这种情况下,所有像素都属于同一个3D-bin:

答案 1 :(得分:1)

我看到@Luis Mendo在写这篇文章的过程中提供了一个很好的单行解决方案。如果它提供了更深刻的直觉,我的解决方案使用histcountsaccumarray

im             = randi([1 255],[10,5,3]);  %// A random 10-by-5 "image" 
numChannelBins = 2;

[~,~,binR]=histcounts(im(:,:,1),[1 ceil((1:numChannelBins)*(255/numChannelBins))]);
[~,~,binG]=histcounts(im(:,:,2),[1 ceil((1:numChannelBins)*(255/numChannelBins))]);
[~,~,binB]=histcounts(im(:,:,3),[1 ceil((1:numChannelBins)*(255/numChannelBins))]);
hist=accumarray([binR(:) binG(:) binB(:)],1,[numChannelBins,numChannelBins,numChannelBins])

<强>解释

  • 三次调用histcounts分别将红色,绿色,蓝色像素分开 - [~,~,binX]的第三个输出histcounts为每个像素提供了bin索引
  • accumarray累积所有唯一索引三元组