2

I have plotted a histogram

of a grayscale image

with matplotlib. But the histogram does not look like what I want.

from matplotlib import pyplot as plt 
import numpy as np
from PIL import Image
im=Image.open("lena.pgm")
pxl=list(im.getdata())
print pxl
columnsize,rowsize=im.size

a = np.array(pxl)
plt.hist(a, bins = 255)
plt.title("histogram") 
plt.show()

I want the histogram like

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
MKS
  • 199
  • 1
  • 8
  • What features are you after, exactly? The number of bins? The colors? – Mad Physicist Jan 06 '19 at 08:22
  • @ MadPhysicist There is a blank vertical strip in the produced histogram. I don't want this. And the color of the vertical strip should be the same as the last image – MKS Jan 06 '19 at 08:26
  • See this SO answer, https://stackoverflow.com/a/23062183/4902099. Basically you need to map a range of colors to your data in order to generate the histogram you want. – hcheung Jan 06 '19 at 10:23

2 Answers2

2

The gaps in the histogram are due to a poor choice of bin size. If you call hist(..., bins=255), numpy will create 256 bins from the min-value to the max-value of your array. In other words, the bins will have non-integer width (in my tests: [ 24. , 24.86666667, 25.73333333, 26.6 , ....]).

Because you are dealing with an image with 255 levels, you should create 255 bins of width 1:

plt.hist(a, bins=range(256))

We have to write 256 because we need to include the right-most edge of the bins, otherwise points with a value of 255 would not be included.

As for the color, follow the examples in the question linked in the comments

from PIL import Image
im=Image.open("lena.pgm")
a = np.array(im.getdata())

fig, ax = plt.subplots(figsize=(10,4))
n,bins,patches = ax.hist(a, bins=range(256), edgecolor='none')
ax.set_title("histogram")
ax.set_xlim(0,255)


cm = plt.cm.get_cmap('cool')
norm = matplotlib.colors.Normalize(vmin=bins.min(), vmax=bins.max())
for b,p in zip(bins,patches):
    p.set_facecolor(cm(norm(b)))
plt.show()

enter image description here

Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75
1

You can use the plt.hist() method like so:

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('lena.png', 0)
plt.hist(img.ravel(), 256, (0, 256))
plt.show()

Output:

enter image description here

Red
  • 26,798
  • 7
  • 36
  • 58