mskuratowski
mskuratowski

Reputation: 4124

Get a vector of gray levels

I wrote a matlab function that accepts image and returns the vector of historgam. I would like to also return a vector of gray levels ranging from 0 to 255.

Here's my code:

function h = myimhist(im)
histogram=zeros(1,256);
h = imread(im);
[row,col]=size(h);

for x=1:1:row
    for y=1:1:col
        if h(x,y) < 1
            continue;
        else
            t=h(x,y);
        end
        histogram(t)=histogram(t)+1;
    end
end

subplot(1,2,1);
imshow(uint8(h));
title('Original Image');

subplot(1,2,2);
bar(histogram);
title('Histogarm of image');
end

How can I get a vector of gray level ? I think the header should be

function [h,c] = myimhist(im)

Upvotes: 0

Views: 192

Answers (1)

rayryeng
rayryeng

Reputation: 104535

If you just want to return a 256 element vector that goes from 0 to 255, do this:

c = 0 : 255;

However, if you want c to contain only those intensities that exist in the image, try doing the following:

c = 0 : 255;
c(histogram == 0) = [];

This removes the intensities in c where there was no histogram count.


If I can nitpick your code, a more efficient way of computing the histogram would be to loop over every possible intensity, use logical indexing and compute the sum. Also, I think you meant to return the histogram, and not the image. Your image is stored in h, yet your histogram is stored in histogram. Therefore, your function declaration should return histogram and not h.

As such, try something like this:

function [histogram,c] = myimhist(im)

h = imread(im);

%// Change
histogram = zeros(1, 256);
for idx = 0 : 255
    histogram(idx) = sum(sum(h == idx));
end

c = 0 : 255;
% c(histogram == 0) = []; %// Depending on what you want

subplot(1,2,1);
imshow(h);
title('Original Image');

subplot(1,2,2);
bar(histogram);
title('Histogram of image');
end

You have an unnecessary casting to uint8 when you're showing the image. Your image will already be of type uint8. This is of course assuming that your histogram calculation is only restricted to [0-255], which should be the case as that is what your code is assuming.

The above code will loop over every possible intensity, find those locations in your image that are equal to that intensity and sum up all occurrences. We need to use two sum calls as calling sum on a matrix will find the sum over every column. To find the total sum of the matrix, we would call sum on this result.


If you want to escape using loops all together, consider using bsxfun with two sum calls:

function [histogram,c] = myimhist(im)

h = imread(im);
pix_counts = bsxfun(@eq, h, permute(c, [3 1 2]));
histogram = squeeze(sum(sum(pix_counts, 1), 2));

c = 0 : 255;
% c(histogram == 0) = []; %// Depending on what you want

subplot(1,2,1);
imshow(h);
title('Original Image');

subplot(1,2,2);
bar(histogram);
title('Histogram of image');
end

bsxfun with the eq function is used such that we create a 3D matrix of counts where each slice tells you the locations of those pixels in your image that match a particular intensity. Therefore, the first slice tells you those locations that match intensity 0, the second slice tells you those locations that match intensity 1 and so on. When we're done, all we need to do is add up the elements in each slice individually. This can be done by summing over the rows of each slice first, followed by summing over the columns last. It doesn't matter what operation you do first. You could even sum over the columns first, followed by the rows last. What will result is a single 3D vector, and we want this to be a 1D vector, which is why squeeze is used.

Upvotes: 1

Related Questions