计算图像中的颜色数

Count the number of colors in images

我是一名 MATLAB 程序员新手。我需要使用 RGB 计算图像中的颜色数并显示在直方图中。 x 轴将从 0 到 7,因为它有 8 种颜色,与从二进制 000 到 111(总共 8 种颜色)相同。 y 轴将是图像中的颜色值。这是我的程序,但还不完整。

count = zeros (1,8);
img = imread ('peppers.png');
[r,c,h] = size(img);

for i=1:5
    for j= 1:c

    a= img(i,j,1);
    b= img(i,j,2);
    d= img(i,j,3);

    if a >128,
        a2 =1;
    else
        a2 =0;

    if b > 128,
        b2 = 1;
    else
        b2 = 0;

    if d > 128,
        d2 = 1;
    else
        d2 = 0;




        index = 4*a2 + 2*b2 + d2 + 1;
        count(index) = count(index)+1;
    end

    end
end 

您的代码实际上没有问题(除了一些语法错误)。您只需确保您的 if-else 语句正确结束(请参阅上面问题中丹尼尔的评论)。例如,您需要为其中之一执行此操作:

if a >128,
    a2 =1;
else
    a2 =0;
end %// CHANGE

您的代码末尾有一个额外的 end 语句。确保删除它并将 end 语句正确放置在 if-else 语句所在的位置。因此,您的代码将是:

count = zeros (1,8);
img = imread ('onion.png');
[r,c,h] = size(img);

for i=1:r
    for j= 1:c

    a= img(i,j,1);
    b= img(i,j,2);
    d= img(i,j,3);

    if a >128,
        a2 =1;
    else
        a2 =0;
    end

    if b > 128,
        b2 = 1;
    else
        b2 = 0;
    end

    if d > 128,
        d2 = 1;
    else
        d2 = 0;
    end

    index = 4*a2 + 2*b2 + d2 + 1;
    count(index) = count(index)+1;

    end
end 

您似乎只计算了前 5 行。我对此进行了更改,以便您查看所有行。


但是,如果我可以建议另一种方法,您可以通过完全避免循环来实现。您可以简单地将整个 RGB 数组阈值设置为 128,这将分别为每个颜色平面生成 1 和 0。然后,您可以应用 bsxfun, permute, sum and accumarray 的组合来获得所需的结果。具体来说:

t = img > 128;
out = sum(bsxfun(@times, double(t), permute([4 2 1], [3 1 2])), 3);
count = accumarray(out(:) + 1, 1, [8 1]);

上面三行代码很紧凑,但是内容却很多。第一行遍历 RGB 图像的每个元素,如果值大于 128,则将每个平面位置的输出设置为 1,否则设置为 0。接下来我们看一下这行代码:

bsxfun(@times, double(t), permute([4 2 1], [3 1 2]))

有点啰嗦,不过解释起来没问题。让我们先进入这部分:

permute([4 2 1], [3 1 2])

permute 获取矩阵或向量并对元素重新排序,使维度发生变化。因此,我们采用向量 [4 2 1](它允许我们为每个可能的位串计算一个唯一的以 10 为底的数字)并采用第三维并将其放入输出的第一维。接下来我们采用第一个维度(行)并将它们放入输出的第二个维度。最后,我们将第二个维度(列)放入输出的第三个维度中。结果将是单个 3D 列,其中第一个切片包含 4,下一个切片包含 2,最后一个切片包含 1。

现在,bsxfun 的工作是获取二进制 3D 矩阵 t 并与第二个 3D 矩阵逐点相乘,其中第一个平面完全由 4 组成,下一个平面由 2 组成,最后一个平面由 1 组成。我们需要将 t 转换为 double,因为 t 最初是一个 logical 矩阵。因为 [4 2 1] 是一个数值数组,如果要使用 times 函数,两个输入的 class 需要相同。 bsxfun 本质上将 复制 3D 列向量,直到它与二进制 3D 矩阵匹配相同的形状,其大小与彩色图像相同。这样做的结果是,任何超过阈值的红色分量都被赋予 4 的值,否则为 0,同样对于绿色,我们得到 2 和蓝色 1。

要像您的代码中那样计算索引,我们只需使用 sum 并在第三维求和。这意味着对于矩阵中的每个 3D 列,我们将所有组件相加以生成我们的索引号。因此,out 将是一个二维矩阵,表示图像中每个位置的索引。最后一行代码使用 accumarray,我们检查 out 中的所有元素并累积它们的所有出现。将矩阵 运行 转换为单个列向量很重要,因此我们使用 (:) 展开矩阵。我们还加 1,因为生成的索引 运行 在 0 到 7 之间。因为 MATLAB 索引数组从 1 开始,这就是我们添加这个值的原因。

结果应该等同于使用 for 循环的上述代码。事实上,我只是 运行 一些结果,它确实匹配。


祝你好运!