如何在没有 Matlab 内置函数的情况下编写 3D 直方图代码?

How do I write a 3D histogram code without the Matlab built in functions?

我想创建一个直方图代码,知道它将计算一个像素的 3 个值的出现次数。 我的想法是我有 3 个矩阵(L1im、L2im、L3im)表示从图像中提取的信息,每个矩阵的大小为 256*226,我想计算(52、6、40)组合的次数) 发生(每个数字对应于一个 matrix/component 但它们都是相同的像素)。

我已经试过了,但没有产生正确的结果:

for i = 1 : 256
    for j = 1 : 256
        for k = 1 : 256
            if  (L1im == i) &  (L2im == j) & (L3im == k)
                myhist(i,j,k)= myhist(i,j,k)+1;
            end
        end
    end
end

颜色三元组直方图

请记住,制作完整的 RGB 三元组直方图是一项艰巨的任务,因为您可以拥有 256 × 256 × 256 = 16,777,216 种可能的独特颜色组合。我认为一个稍微更易于管理的任务是计算图像中唯一 RGB 值的直方图(因为其余部分无论如何都是零)。这仍然是一项相当大的任务,但如果图像相当小,这可能是合理的。在下面,我认为合并的一个不错的替代方法是将图像的大小调整为较小的像素数。这可以通过使用 imresize 函数来完成。我相信这会降低图像的保真度并且几乎充当可以“有点”模拟合并行为的舍入函数。在此示例中,我将矩阵字符串数组转换为连接图像的通道 L1imL2imL3im。下面是一个演示,其中我使用了名为 saturn.png 的 MATLAB 内置图像。一个 Resize_Factor 为 1 将导致最高数量的箱子,并且箱子的数量将随着 Resize_Factor 的增加而减少。请记住,如果使用 Resize_Factor.

调整图像大小时,直方图可能需要缩放

Resize_Factor = 200;
RGB_Image = imread("saturn.png");
[Image_Height,Image_Width,Number_Of_Colour_Channels] = size(RGB_Image);
Number_Of_Pixels = Image_Height*Image_Width;

RGB_Image = imresize(RGB_Image,[Image_Height/Resize_Factor Image_Width/Resize_Factor]);
L1im = RGB_Image(:,:,1);
L2im = RGB_Image(:,:,2);
L3im = RGB_Image(:,:,3);

L1im_String = string(L1im);
L2im_String = string(L2im);
L3im_String = string(L3im);

RGB_Triplets = L1im_String + "," + L2im_String + "," + L3im_String;
Unique_RGB_Triplets = unique(RGB_Triplets);

for Colour_Index = 1: length(Unique_RGB_Triplets)
    RGB_Colour = Unique_RGB_Triplets(Colour_Index);
    Unique_RGB_Triplets(Colour_Index,2) = nnz(RGB_Colour == RGB_Triplets); 
end

Counts = str2double(Unique_RGB_Triplets(:,2));
Scaling_Factor = Number_Of_Pixels/sum(Counts);
Counts = Counts.*Scaling_Factor;

if sum(Counts) == Number_Of_Pixels
    disp("Sum of histogram is equal to the number of pixels");
end

bar(Counts);
title("RGB Triplet Histogram");
xlabel("RGB Triplets"); ylabel("Counts");

Current_Axis = gca;
Scale = (1:length(Unique_RGB_Triplets));
set(Current_Axis,'xtick',Scale,'xticklabel',Unique_RGB_Triplets);
Angle = 90;
xtickangle(Current_Axis,Angle);