As promised in the previous post, we will talk about the image's histogram.
Plotting data obtained from images is helpful to study and understand them. One plot type that can be helpful for any image processing practitioner is the grey-level histogram. The grey-level histogram of an image gives us, as it's easy to deduce, the grey-level distribution of the pixels within the image.
The histogram of an image is the set of numbers M, the value of which representing what percentage of the image is at that grey level. The following formula defines the histogram of an image:
hi = ni/nt for i = 0 to (M-1)
in which ni is the number of pixels within the image at the ith grey level value and nt is the total number of pixels in the image.
The following function implements a grey-level histogram for a greyscale image:
def histogram(input_image):
if input_image.mode != 'L' and input_image.mode != 'P':
return None
else:
IHIST = [0 for i in range(256)]
HIST = [0 for i in range(256)] ## histogram array
SUM = 0
for x in range(input_image.width):
for y in range(input_image.height):
pix = input_image.getpixel((x, y))
IHIST[pix] = IHIST[pix]+1
SUM += 1
for i in range(256):
HIST[i] = float(IHIST[i]/SUM)
return HIST
The picture below shows the image and its grey-level histogram:
Histogram interpretation
Histogram interpretation deserves a tutorial of its own, especially if we want to talk also about colour images histogram.
For now, we should understand at least that by examining the histogram of an image is possible to detect some problem caused during its acquisition, as poor or excessive contrast, or a low dynamic range.
We should also be aware of the existence of some techniques involving histograms that can help us to improve our images, as histogram equalization, which we'll discuss in the next post.
The complete code:
from PIL import Image, ImageTk
import tkinter as tk
def histogram(input_image):
if input_image.mode != 'L' and input_image.mode != 'P':
return None
else:
IHIST = [0 for i in range(256)]
HIST = [0 for i in range(256)]
SUM = 0
for x in range(input_image.width):
for y in range(input_image.height):
pix = input_image.getpixel((x, y))
IHIST[pix] = IHIST[pix]+1
SUM += 1
for i in range(256):
HIST[i] = float(IHIST[i]/SUM)
return HIST
def draw_histogram(canvas, IHIST, hist_w, hist_h):
## A bin is a bar of the histogram
bin_w = round(float(hist_w/512))
offset = hist_w + 20 ## where we draw the first bin
for i in range(256):
canvas.create_line(bin_w*i+offset, hist_h,
bin_w*i+offset, hist_h-IHIST[i])
if __name__=="__main__":
root = tk.Tk()
root.title("IMAGE GREY-LEVEL HISTOGRAM")
img = Image.open("retriver_gray.png")
width = img.width*2
height = img.height
root.geometry(f'{width}x{height}')
IHIST = histogram(img)
if IHIST != None:
hist_w = img.width
hist_h = img.height
hist_max = max(IHIST) ## get the max value
## Normalize between 0 and hist_h
for i in range(256):
IHIST[i] = float(IHIST[i]/hist_max) * hist_h
input_im = ImageTk.PhotoImage(img)
canvas = tk.Canvas(root, width=width, height=height, bg="#ffffff")
canvas.create_image(width/4-1, height/2-1, image=input_im, state="normal")
draw_histogram(canvas, IHIST, hist_w, hist_h)
canvas.place(x=0, y=0)
canvas.pack()
root.mainloop()
else:
print("Input image's mode must be 'L' or 'P'"\
"Check https://pillow.readthedocs.io/en/"\
"latest/handbook/concepts.html#concept-modes")
No comments:
Post a Comment