Get notified about new tutorials
RECEIVE NEW TUTORIALS

First 15 Minutes Free

305 sessions given

since Jul 09, 2014

since Jul 09, 2014

Likelihood of Reply:
80%

Response Time:
within an hour

Ray Phan

Jul 02, 2015

<p>In terms of calculating the histogram, the computation of the frequency per intensity is correct though there is a slight error... more on that later. Also, I would personally avoid using loops here. See my small note at the end of this post.</p>
<p>Nevertheless, there are three problems with your code:</p>
<h1>Problem #1 - Histogram is not initialized properly</h1>
<p><code>histogram_values</code> should contain your histogram, yet you are initializing the histogram by a vector of <code>0:255</code>. Each intensity value should <strong>start with a count of 0</strong>, and so you actually need to do this:</p>
<pre><code>histogram_values = zeros(256,1);
</code></pre>
<h1>Problem #2 - Slight error in <code>for</code> loop</h1>
<p>Your intensities range from 0 to 255, yet MATLAB starts indexing at 1. If you ever get intensities that are 0, you will get an out-of-bounds error. As such, the proper thing to do is to take <code>p</code> and add it with 1 so that you start indexing at 1. However, one intricacy I need to point out is that if you have a <code>uint8</code> precision image, adding 1 to an intensity of 255 will simply saturate the value to 255. It won't go to 256.... so it's also prudent that you cast to something like <code>double</code> to ensure that 256 will be reached.</p>
<p>Therefore:</p>
<pre><code>histogram_values = zeros(256,1);
for i = 1:rows
for j = 1:cols
p = double(openImage(i,j)) + 1;
histogram_values(p) = histogram_values(p) + 1;
end
end
</code></pre>
<h1>Problem #3 - Not calling <code>histogram</code> right</h1>
<p>You should override the behaviour of <code>histogram</code> and include the edges. Basically, do this:</p>
<pre><code>histogram(histogram_values, 0:255);
</code></pre>
<p>The second vector specifies where we should place bars on the <code>x</code>-axis.</p>
<h1>Small note</h1>
<p>You can totally implement the histogram computation yourself without any <code>for</code> loops. You can try this with a combination of <a href="http://www.mathworks.com/help/matlab/ref/bsxfun.html" rel="nofollow"><code>bsxfun</code></a>, <a href="http://www.mathworks.com/help/matlab/ref/permute.html" rel="nofollow"><code>permute</code></a>, <a href="http://www.mathworks.com/help/matlab/ref/reshape.html" rel="nofollow"><code>reshape</code></a> and two <a href="http://www.mathworks.com/help/matlab/ref/sum.html" rel="nofollow"><code>sum</code></a> calls:</p>
<pre><code>mat = bsxfun(@eq, permute(0:255, [1 3 2]), im);
h = reshape(sum(sum(mat, 2), 1), 256, 1);
</code></pre>
<hr>
<p><em>If you'd like a more detailed explanation of how this code works under the hood, see this conversation between kkuilla and myself: <a href="http://chat.stackoverflow.com/rooms/81987/conversation/explanation-of-computing-an-images-histogram-vectorized">http://chat.stackoverflow.com/rooms/81987/conversation/explanation-of-computing-an-images-histogram-vectorized</a></em></p>
<p>However, the gist of it as below.</p>
<hr>
<p>The first line of code creates a 3D vector of 1 column that ranges from 0 to 255 by <code>permute</code>, and then using <code>bsxfun</code> with the <code>eq</code> (equals) function, we use broadcasting so that we get a 3D matrix where each slice is the same size as the grayscale image and gives us locations that are equal to an intensity of interest. Specifically, the first slice tells you where elements are equal to 0, the second slice tells you where elements are equal to 1 up until the last slice where it tells you where elements are equal to 255. </p>
<p>For the second line of code, once we compute this 3D matrix, we compute two sums - first summing each row independently, then summing each column of this intermediate result. We then get the total sum per slice which tells us how many values there were for each intensity. This is consequently a 3D vector, and so we <code>reshape</code> this back into a single 1D vector to finish the computation.</p>
<hr>
<p>In order to display a histogram, I would use <code>bar</code> with the <code>histc</code> flag. Here's a reproducible example if we use the <code>cameraman.tif</code> image:</p>
<pre><code>%// Read in grayscale image
openImage = imread('cameraman.tif');
[rows,cols] = size(openImage);
%// Your code corrected
histogram_values = zeros(256,1);
for i = 1:rows
for j = 1:cols
p = double(openImage(i,j)) + 1;
histogram_values(p) = histogram_values(p) + 1;
end
end
%// Show histogram
bar(0:255, histogram_values, 'histc');
</code></pre>
<p>We get this:</p>
<p><img src="http://i.stack.imgur.com/W6mqw.png" alt="enter image description here"></p>
<p>This tip was originally posted on <a href="http://stackoverflow.com/questions/31129945/Image%20histogram%20implementation%20with%20Matlab/31130595">Stack Overflow</a>.</p>