import cv2
import numpy as np
import matplotlib.pyplot as plt
L = 256
def histeq(img, L=256,target=None):
"""
Histogram equalization or matching of a grayscale image.
:param img: input image
:param target: target image
:return: equalized image
"""
def cdf_round(image: np.ndarray):
hist = cv2.calcHist([image], [0], None, [L], [0, L])
hist /= np.sum(hist)
cdf = np.cumsum(hist)
return np.round(cdf * (L - 1)).astype(np.uint8)
cdf = cdf_round(img)
if target is None:
return cdf[img]
else:
cdf_target = cdf_round(target)
lut = np.zeros(L, dtype=np.uint8) # r->z
for i in range(L):
lut[i] = np.argmin(np.abs(cdf[i] - cdf_target))
return lut[img]
Satsuma dogs are white, and the corresponding histogram has a peak at the white end of the color distribution.
img_satsuma = cv2.imread("../../img/image-processing/satsuma_1.jpg", cv2.IMREAD_GRAYSCALE)
plt.imshow(img_satsuma, cmap="gray")
plt.show()
hist_satsuma = cv2.calcHist([img_satsuma], [0], None, [L], [0, L])
plt.plot(hist_satsuma)
plt.bar(np.arange(L), hist_satsuma.flatten())
plt.show()
Background of the satsuma dog is dark, refering to the peak at the black end of the histogram. After histogram equalization, the background is lighter and the distribution of the color is more uniform.
img_satsuma_eq = histeq(img_satsuma)
plt.imshow(img_satsuma_eq, cmap="gray")
plt.show()
hist_satsuma_eq = cv2.calcHist([img_satsuma_eq], [0], None, [L], [0, L])
plt.plot(hist_satsuma_eq)
plt.bar(np.arange(L), hist_satsuma_eq.flatten())
plt.show()
img_bernese = cv2.imread("../../img/image-processing/bernese_1.jpg", cv2.IMREAD_GRAYSCALE)
plt.imshow(img_bernese, cmap="gray")
plt.show()
hist_bernese = cv2.calcHist([img_bernese], [0], None, [L], [0, L])
plt.plot(hist_bernese)
plt.bar(np.arange(L), hist_bernese.flatten())
plt.show()
The bernese mountain dog is black, and the corresponding histogram has a peak at the middle of the color distribution, which means that the color is gray. If the image of the satsuma dog is matched to the histogram of the bernese mountain dog, the color of the satsuma dog will be darker as follows.
img_match = histeq(img_satsuma, target=img_bernese)
plt.imshow(img_match, cmap="gray")
plt.show()
hist_satsuma_match = cv2.calcHist([img_match], [0], None, [L], [0, L])
plt.plot(hist_satsuma_match)
plt.bar(np.arange(L), hist_satsuma_match.flatten())
plt.show()
If we match the histogram of the bernese mountain dog to the satsuma dog, the color of the bernese mountain dog will be lighter and the high-value pixels will increase.
img_match = histeq(img_bernese, target=img_satsuma)
plt.imshow(img_match, cmap="gray")
plt.show()
hist_bernese_match = cv2.calcHist([img_match], [0], None, [L], [0, L])
plt.plot(hist_bernese_match)
plt.bar(np.arange(L), hist_bernese_match.flatten())
plt.show()