Plot a Histogram for multiple images (full dataset)

alx: <p>Hi, I was able to plot a histogram for a single image as such:</p>
<pre><code class="lang-auto">from skimage import io
import matplotlib.pyplot as plt
image = io.imread('./1084_left.jpeg')

#_ = plt.hist(image.ravel(), bins = 256, color = 'orange', )
_ = plt.hist(image[:, :, 0].ravel(), bins = 256, color = 'red', alpha = 0.5)
_ = plt.hist(image[:, :, 1].ravel(), bins = 256, color = 'Green', alpha = 0.5)
_ = plt.hist(image[:, :, 2].ravel(), bins = 256, color = 'Blue', alpha = 0.5)
_ = plt.xlabel('Intensity Value')
_ = plt.ylabel('Count')
_ = plt.legend(['Total', 'Red_Channel', 'Green_Channel', 'Blue_Channel'])
plt.show()
</code></pre>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/5/2/520c0c05c15d1b8e8535983a7649bea5f63ed702.png" alt="Unknown" data-base62-sha1="bHOXI3T2F8QHMwF50bVKZQPT7b4" width="395" height="266"></p>
<p>Now, I would know like to see the color distribution of my whole datatset: one plot for all the images.</p>
<p>Does anyone know how to do this?</p>

ptrblck: <p>I assume you cannot load all images into your RAM, so you could instead calculate the bin count for each image and sum it together:</p>
<pre><code class="lang-python">nb_bins = 256
count_r = np.zeros(nb_bins)
count_g = np.zeros(nb_bins)
count_b = np.zeros(nb_bins)
for image in range(10):    
    x = np.random.randint(0, 256, (3, 244, 244))
    hist_r = np.histogram(x[0], bins=nb_bins, range=[0, 255])
    hist_g = np.histogram(x[1], bins=nb_bins, range=[0, 255])
    hist_b = np.histogram(x[2], bins=nb_bins, range=[0, 255])
    count_r += hist_r[0]
    count_g += hist_g[0]
    count_b += hist_b[0]

bins = hist_r[1]
fig = plt.figure()
plt.bar(bins[:-1], count_r, color='r', alpha=0.33)
plt.bar(bins[:-1], count_g, color='g', alpha=0.33)
plt.bar(bins[:-1], count_b, color='b', alpha=0.33)
</code></pre>
<p>You might a better answer in a <code>matplotlib</code> or <code>numpy</code> specific discussion board, but the method should work. <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=9" title=":wink:" class="emoji" alt=":wink:"></p>

alx: <p>Cool solution! it works but the plot is very different. I’ll check out a matplotlib forum, good idea!</p>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/2/b/2b1acb32b8cf8ecbcc1297059e9e1841f945e879.png" alt="download" data-base62-sha1="69jW484bCLmy3NLCJNKXIUSRf05" width="375" height="248"></p>

ptrblck: <p>Do you get this plot using my example code snippet?<br>
If so, something seems to be wrong.</p>
<p>Yeah, hearing from some <code>matplotlib</code> experts would be good and please share the solution here. <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>

alx: <p>Hey, yes, here’s what I used:</p>
<pre><code class="lang-auto">import numpy as np
from skimage import io
import matplotlib.pyplot as plt


nb_bins = 256
count_r = np.zeros(nb_bins)
count_g = np.zeros(nb_bins)
count_b = np.zeros(nb_bins)

root = './'
for image in os.listdir(root):  
  if image.endswith('.jpeg'):
    x = io.imread(root+image)
    hist_r = np.histogram(x[0], bins=nb_bins, range=[0, 255])
    hist_g = np.histogram(x[1], bins=nb_bins, range=[0, 255])
    hist_b = np.histogram(x[2], bins=nb_bins, range=[0, 255])
    count_r += hist_r[0]
    count_g += hist_g[0]
    count_b += hist_b[0]

bins = hist_r[1]
fig = plt.figure()
plt.bar(bins[:-1], count_r, color='r', alpha=0.33)
plt.bar(bins[:-1], count_g, color='g', alpha=0.33)
plt.bar(bins[:-1], count_b, color='b', alpha=0.33)

</code></pre>

ptrblck: <p>It seems the loaded image contains a lot of black pixels. Are you loading the same image as in your initial post?</p>

alx: <p>No! I was comparing two different ones. Here’s for the same image:<img src="https://discuss.pytorch.org/uploads/default/original/3X/2/b/2b8cc7ea3195cc44022e0f3cd30edbac77656781.png" alt="download-2" data-base62-sha1="6dg9tX5ZQ9iNXkTVFHiThJ3wuYN" width="375" height="248"> <img src="https://discuss.pytorch.org/uploads/default/original/3X/6/6/6631631e8a70ef384ac8a9b15fc7f517d2337185.png" alt="download-1" data-base62-sha1="eA2vQ3eOplOV93PTYe27jw0endP" width="395" height="262"></p>

ptrblck: <p>Would it be possible to upload this image here?</p>

alx: <p>Yes <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"> <div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/4/7/471fa3076f84e74506441400bcbc6f513ed92128.jpeg" data-download-href="https://discuss.pytorch.org/uploads/default/471fa3076f84e74506441400bcbc6f513ed92128" title="16_left-2"><img src="https://discuss.pytorch.org/uploads/default/original/3X/4/7/471fa3076f84e74506441400bcbc6f513ed92128.jpeg" alt="16_left-2" data-base62-sha1="a9bGhCeU6yJzJ9RBwHBSTgxvqRi" width="500" height="500" data-dominant-color="A07B68"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">16_left-2</span><span class="informations">512×512 22 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>

ptrblck: <p>I get quite the same results for this image using the “manual” approach and <code>plt.hist</code>:</p>
<p>Manual:<br>
<img src="https://discuss.pytorch.org/uploads/default/original/3X/9/5/957df1df0b305e5a279dd9cdf1a7f292c79d7534.png" alt="manual_hist" data-base62-sha1="lksYFLsPbHVcqGVILfwaXeemY0k" width="432" height="288"></p>
<p><code>plt.hist</code>:<br>
<img src="https://discuss.pytorch.org/uploads/default/original/3X/e/2/e2960a373ad8b79f87e8fe005a749b8b125a26ee.png" alt="plt_hist" data-base62-sha1="wktmM2qQXsil8UmbV93rqvTyuoC" width="432" height="288"></p>

alx: <p>So you used my code for plot one and your code for plot two? That’s odd.</p>
<p>Can you paste the code you used to plot your method by passing an image (and not rand)</p>
<p>Also! if you notice, the y axis values are quite different</p>

ptrblck: <p>Ah, I had an error in the code summing into <code>count_x</code> instead of resetting, as I used my code for multiple images. I get the same counts now for both approaches using this code:</p>
<pre><code class="lang-python">nb_bins = 256
count_r = np.zeros(nb_bins)
count_g = np.zeros(nb_bins)
count_b = np.zeros(nb_bins)

img = Image.open('./discuss_eye_test.jpeg')

# Calculate manual hist
x = np.array(img)
x = x.transpose(2, 0, 1)
hist_r = np.histogram(x[0], bins=nb_bins, range=[0, 255])
hist_g = np.histogram(x[1], bins=nb_bins, range=[0, 255])
hist_b = np.histogram(x[2], bins=nb_bins, range=[0, 255])
count_r = hist_r[0]
count_g = hist_g[0]
count_b = hist_b[0]

# Plot manual
bins = hist_r[1]
fig = plt.figure()
plt.bar(bins[:-1], count_r, color='r', alpha=0.5)
plt.bar(bins[:-1], count_g, color='g', alpha=0.5)
plt.bar(bins[:-1], count_b, color='b', alpha=0.5)

# Plot matplotlib
fig2 = plt.figure()
plt.hist(x[0].ravel(), bins = 256, color = 'red', alpha = 0.5)
plt.hist(x[1].ravel(), bins = 256, color = 'green', alpha = 0.5)
plt.hist(x[2].ravel(), bins = 256, color = 'blue', alpha = 0.5)
</code></pre>

alx: <p>Cool! I have the same result as well.</p>
<p>How can you now compute multiple images? Do you need something like:</p>
<pre><code class="lang-auto">for image in os.listdir('test_images'):
  img = Image.open(image)
  x = np.array(img)
</code></pre>
<p>That only seems to plot the histo of the last image.</p>

ptrblck: <p>My initial code snippet should accumulate the counts of all images into the <code>count_x</code> arrays, so that you could plot the histogram of all images.</p>

alx: <p>Got it, I changed it just a bit:</p>
<pre><code class="lang-auto">nb_bins = 256
count_r = np.zeros(nb_bins)
count_g = np.zeros(nb_bins)
count_b = np.zeros(nb_bins)

for image in os.listdir('./test/'):
  img = Image.open('./test/'+image)
  x = np.array(img)
  x = x.transpose(2, 0, 1)
  hist_r = np.histogram(x[0], bins=nb_bins, range=[0, 255])
  hist_g = np.histogram(x[1], bins=nb_bins, range=[0, 255])
  hist_b = np.histogram(x[2], bins=nb_bins, range=[0, 255])
  count_r += hist_r[0]
  count_g += hist_g[0]
  count_b += hist_b[0]

bins = hist_r[1]
fig = plt.figure()
plt.bar(bins[:-1], count_r, color='r', alpha=0.7)
plt.bar(bins[:-1], count_g, color='g', alpha=0.7)
plt.bar(bins[:-1], count_b, color='b', alpha=0.7)
</code></pre>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/6/a/6ad6ea6492599a0b2daeef7bafa6e2b1f51a69b3.png" alt="download-2" data-base62-sha1="ff947hyfGOZ7GUypCQhQYaXP7A7" width="393" height="248"></p>
<p>Any idea why the plotted curves break like that?</p>

saba: <p>Hi<br>
sorry , I am trying to have histogram of the tensor which is between 0 to 1. I used this command but it shows me nothing. I check the bins and Counter have numbers but show nothing.</p>
<pre><code class="lang-auto">        hist_r = np.histogram(kk.squeeze(0).view(-1).detach().numpy(),bins=100)
        fig = plt.figure()
        bins = hist_r[1]
        count_r=hist_r[0]
        plt.bar(bins[:-1], count_r, color='b', alpha=0.33)
</code></pre>

ptrblck: <p>Is my example code working for you or is the figure also empty?</p>

saba: <p>I redo it again it work. Would you please tell me how I can define the bins in the sequence of the numbers ? like that bins=[0:0.1:1] or [0:10:255]</p>

ptrblck: <p>You can pass the bin edges to the <code>bins</code> argument directly in <code>np.histogram</code>.<br>
From the docs:</p>
<blockquote>
<p><strong>bins</strong> int or sequence of scalars or str, optional<br>
If  <em>bins</em>  is an int, it defines the number of equal-width bins in the given range (10, by default). If  <em>bins</em>  is a sequence, it defines a monotonically increasing array of bin edges, including the rightmost edge, allowing for non-uniform bin widths.<br>
New in version 1.11.0.<br>
If  <em>bins</em>  is a string, it defines the method used to calculate the optimal bin width, as defined by <a href="https://numpy.org/doc/stable/reference/generated/numpy.histogram_bin_edges.html#numpy.histogram_bin_edges"> <code>histogram_bin_edges</code> </a>.</p>
</blockquote>

saba: <p>Hi Ptrblck,</p>
<p>Would you please help me with that which function I can use to give me the density function, the smooth version of the histogram? I used the current function but it gives me individual bins, I need a smoothed version.</p>