直方图匹配又称为直方图规定化,是指将一幅图像的直方图变成规定形状的直方图而进行的图像增强方法,即将某幅影像或某一区域的直方图匹配到另一幅影像上。
直方图匹配的步骤如下:
假设原始图像为img,目标图像为target,则
举例说明一下(该示例来源于《https://www.cnblogs.com/picassooo/p/11504937.html》),假设图像总共有3289个像素,把这些像素分成10个灰度级。首先统计两张图像的直方图(左图为img,右图为target),
接着计算两张图片的累积直方图,
接下来统计两张累积直方图中不同灰度级下的像素数量,如,
img_accu_g=[1: 927, 2: 1617, 3: 1252, 4: 2602, 5: 2936, 6: 3157, 7: 3269, 8: 3289, 9: 3289, 10: 3289],
target_accu_G=[1: 0, 2: 0, 3: 20, 4: 132, 5: 353, 6: 687, 7: 1137, 8: 1672, 9: 2362, 10: 3289],
从target_accu_G找出与img_accu_g中的不同灰度级像素个数最接近的灰度级,如,img_accu_g中灰度级为1的像素个数为927,target_accu_G中与这个数值最接近的像素个数是1137,该数值对应的灰度级为7,也就是说img_accu_g中的灰度级1应该与target_accu_G中的灰度级7进行匹配,同理,img_accu_g中的灰度级2(1617)应该与target_accu_G中的灰度级8(1672)进行匹配,以此类推,便可得到两张图片灰度级的对应关系,
得到灰度级的对应关系后,就可进行直方图匹配,
import cv2
import numpy as np
# BGR转灰度
img = cv2.cvtColor(img_path, cv2.COLOR_BGR2GRAY)
target= cv2.cvtColor(target_path, cv2.COLOR_BGR2GRAY)
# 统计直方图
img_hist = cv2.calcHist([img], [0], None, [256], [0, 256])
target_hist = cv2.calcHist([target], [0], None, [256], [0, 256])
# 统计累积直方图
img_hist_accu = np.cumsum(img_hist, axis=0)
target_hist_accu = np.cumsum(target_hist, axis=0)
# 定义输出图片
out = np.zeros_like(img)
# 将两张图片的灰度级进行匹配
for j in range(256):
tmp = abs(img_hist_accu[j] - target_hist_accu)
tmp = tmp.tolist()
# 找出最接近的灰度级并进行匹配
out[img[:, :] == j] = tmp.index(min(tmp))
# 保存输出图片
cv2.imwrite(out_path, out)