ThisaruG
ThisaruG

Reputation: 3412

Create histograms for three color channels separately in MATLAB

I have an assignment where I have to get a RGB image as the input and then draw histograms for three different channels (Red, Green, and Blue) separately using MATLAB.

Here is the code I wrote first:

function histogram_rgb(image)
    values1 = zeros(1, 256);    
    values2 = zeros(1, 256); 
    values3 = zeros(1, 256);

    [rows, cols, c] = size(image);

    for c1 = 1:rows
        for c2 = 1:cols
            values1(1, image(c1, c2, 1)) = values1(1, image(c1, c2, 1)) + 1;
            values2(1, image(c1, c2, 2)) = values2(1, image(c1, c2, 2)) + 1;
            values3(1, image(c1, c2, 3)) = values3(1, image(c1, c2, 3)) + 1;
        end
    end

    figure;
    subplot(1, 3, 1);
    bar((1:256), values1);
    title('Histogram for the Image - Red');

    subplot(1, 3, 2);
    bar((1:256), values2);
    title('Histogram for the Image - Green');

    size(values3)
    subplot(1, 3, 3);
    bar((1:256), values3);
    title('Histogram for the Image - Blue');
end

But this gave me the following error:

Subscript indices must either be real positive integers or logicals.

I've searched for this error and found that it happens when array indexing goes wrong. Then I edited my code, which fixed that error. The only thing I did was edit the following line:

values3(1, image(c1, c2, 3)) = values3(1, image(c1, c2, 3)) + 1;

where the error was. All I did was to add 1 to the index, as follows:

values3(1, image(c1, c2, 3) + 1) = values3(1, image(c1, c2, 3) + 1) + 1;

My question is why does this happens? I mean, this index works fine for the first two arrays, then why not this one Why does it run when I add 1 to the index?

Thanks in advance.

Upvotes: 0

Views: 455

Answers (2)

rayryeng
rayryeng

Reputation: 104474

For posterity, the answer is that your image spans in intensity between [0,255] for some of the channels, but because MATLAB starts indexing at 1, any intensities in a channel that have the value of 0 will give you an out of bounds error. This only happens for some of your channels and so that's why you don't see the error for the other channels. Therefore, you actually need to shift the intensity per channel by 1 to access the right element to populate in the matrix. It should also be noted that if your image is an integer type, like uint8. If you simply added 1, intensities that were already 255 will saturate to 255 and not go to 256. Therefore, it's important that you temporarily cast the image to double when calculating the histogram before adding 1.

Therefore, in your double for loop, do this:

for c1 = 1:rows
    for c2 = 1:cols
        pix = double(image(c1, c2, :)) + 1; %  New
        values1(1, pix(1)) = values1(1, pix(1)) + 1; % Change
        values2(1, pix(2)) = values2(1, pix(2)) + 1; % Change
        values3(1, pix(3)) = values3(1, pix(3)) + 1; % Change
    end
end

What is nice with the above is that we convert all of the channels at a single location to double then add 1 to this after. We can then use each of the channels in this pixel to populate the histogram.

Upvotes: 2

Israel Unterman
Israel Unterman

Reputation: 13510

This is a very simple task, provided using the hist function from matlab:

function histogram_rgb(image)
titles = {'R', 'G', 'B'};
for i=1:3
    subplot(1, 3, i);
    values = image(:, :, i);
    hist(values(:), 1:10:256);
    title(titles{i});
end

Upvotes: -1

Related Questions