目录
3.1 灰度直方图
3.2 线性变换
3.3 直方图正规化
3.4 伽马变换
3.5 全局直方图均衡化
3.6 CLAHE
对比度增强是图像增强的一种,它主要解决的是图像的灰度级范围较小造成的对比度较低的问题,目的是将图像的灰度级增强到指定范围,使得图像变清晰。对比度增强:线性变换、分段线性变换、伽马变换、直方图正规化,直方图均衡化,局部自适应直方图均衡化。
3.1 灰度直方图
灰度直方图:是图像灰度级的函数,用来描述每个灰度级在图像矩阵中的像素个数或者占有率。
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) # 颜色变换
hist = cv2.calcHist(gray,[6],None,[155],[120,256]) # 原图、通道、掩模、直方图尺寸(x轴)、像素值范围
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]])
channels,是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道。
Mask,图像掩模,没有使用则填写None。
histSize,表示这个直方图分成多少份(即多少个直方柱)。
ranges,表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。
accumulate,为一个布尔值,用来表示直方图是否叠加。
3.2 线性变换
原理:假设输入图像为I,宽为W,高为H,输出图像为O。
线性变换公式定义:
当a=1,b=0时,O是I的一个副本;当a>1, 增大对比度;当a<1, 对比度的减小。b的值影响亮度:b>0,亮度增加,当b<0,亮度减小。
注:不同数据类型的常数对结果的影响(uint8、float64)uint8是一种无符号8位整数数据类型,它的取值范围是0到255,可以表示的整数数量为256个。float64是一种双精度浮点数数据类型,它的取值范围是从正负1.7976931348623157e+308到正负4.9406564584124654e-324,可以表示的浮点数数量非常大。
histI = cv2.calcHist(I,[0],None,[255],[0,256]) # 原图灰度图
# 线性变换
a = 2
O = float(a)*I
# 进行数据截断,大于255的值要截断为255
O[O>255] = 240
# 数据类型转换
O = np.round(O)
O = O.astype(np.uint8)
histO = cv2.calcHist(O,[0],None,[255],[0,255]) # 线性变换之后灰度图
cv2.calcHist(原图,直方图通道,掩膜,直方图大小,像素值范围,输出直方图=None,是否是累积直方图=None)
①直方图通道:需要计算直方图的通道,可以是一个整数或整数的列表。例如,如果输入图像是一个三通道的彩色图像,则可以选择计算蓝色通道的直方图、绿色通道的直方图、红色通道的直方图或者所有通道的直方图。
②掩膜:指定感兴趣区域,只对指定区域内部分进行直方图统计,如果不需要则输入 None
③直方图的大小(即直方图的区间数),可以是一个列表或元组,表示每个通道的直方图大小,例如 [256, 256, 256] 表示三个通道的直方图大小均为 256 个区间
④像素值的范围,可以是一个列表或元组,表示每个通道的像素值范围,例如 [0, 256, 0, 256, 0, 256] 表示三通道的像素值范围均为 0-255。对于单通道灰度图像,可以省略其中一个 0-256 的范围,例如 [0, 256] 表示像素值范围在 0-255 之间(包含 0 和 255)
3.3 直方图正规化
假设输入图像为I,宽为W,高为H,将I出现的最小灰度值记为Imin,最大灰度值记为Imax,为使输出图像)的灰度级范围为[Omin,Omax],I和O的映射为:
直方图正规化就是一种自动选取a和b值得线性变换方法。
histI = cv2.calcHist(I,[0],None,[255],[0,256])
# 求I的最小值和最大值
Imax = np.max(I)
Imin = np.min(I)
# 要输出的最小灰度级和最大灰度级
Omin,Omax = 0,255
# 计算a和b的值
a = float(Omax-Omin)/(Imax-Imin)
b = Omin-a*Imax
# 矩阵的线性变换
O = a*I + b
# 数据类型转换
O = O.astype(np.uint8)
histO = cv2.calcHist(O,[0],None,[255],[0,256])
# 直方图正规化
dst = cv2.normalize(img,255,0,cv2.NORM_MINMAX,cv2.CV_8U)
cv2.normalize(src[, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]])
①src-输入数组
②dst-输出数组,支持原地运算
③alpha-range normalization模式的最小值
④beta-range normalization模式的最大值,不用于norm normalization(范数归一化)模式。
⑤normType-归一化的类型,可以有以下的取值:
NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化,一般较常用。
NORM_INF: 此类型的定义没有查到,根据OpenCV 1的对应项,可能是归一化数组的C-范数(绝对值的最大值)
NORM_L1 : 归一化数组的L1-范数(绝对值的和)
NORM_L2: 归一化数组的(欧几里德)L2-范数
⑥dtype-dtype为负数时,输出数组的type与输入数组的type相同;否则,输出数组与输入数组只是通道数相同,而tpye=CV_MAT_DEPTH(dtype).
⑦mask-操作掩膜,用于指示函数是否仅仅对指定的元素进行操作。
3.4 伽马变换
图像归一化后得到图像I(r,c),伽马变换就是O(r,c)=I(r,c)^γ, 0<=r<H, 0<=c<W, 当γ=1,图像不变。如果图像整体或者感兴趣区域较暗,令0<γ<1可以增强对比度;如果较亮,则令γ>1,降低对比度。实质上是对图像矩阵中的每一个值进行幂运算。
# 图像归一化
f1 = image/255.0
# 伽马变换
gamma = 0.5
O= np.power(f1,gamma)
3.5 全局直方图均衡化
直方图均衡化是将原始的直方图拉伸,使之均匀分布在全部灰度范围内,从而增强图像的对比度。
直方图均衡化的中心思想是把原始图像的的灰度直方图从比较集中的某个区域变成在全部灰度范围内的均匀分布。旨在使得图像整体效果均匀,黑与白之间的各个像素级之间的点更均匀一点。
全局直方图均衡化(HE):可以更好的提高对比度,但是暗区域的噪声可能会放大,变得清晰,而亮区域可能会损失信息。为了提出该问题,采用CLAHE
直方图均衡化的步骤:
第一步:计算图像灰度直方图
第二步:计算灰度直方图的累加直方图
第三步:根据累加直方图的直方图均衡化原理得到输入灰度级和输出灰度级之间的映射关系
第四步:根据第三步得到的灰度级映射关系,循环得到输出图像的每个像素灰度级。
# 全局直方图均衡化
def equalHist(img, z_max = 255): # z_max = L-1 = 255
# 灰度图像矩阵的高、宽
H, W = img.shape
# S is the total of pixels
S = H * W
out = np.zeros(img.shape)
sum_h = 0
for i in range(256):
ind = np.where(img == i)
sum_h += len(img[ind])
z_prime = z_max / S * sum_h
out[ind] = z_prime
out = out.astype(np.uint8)
return out
image = cv2.imread('../Img/1686370964745.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('image',image)
image1 = equalHist(image)
image2 = cv2.equalizeHist(image,cv2.CV_8UC1)
3.6 CLAHE
CLAHE限制对比度的自适应直方图均衡化原理:
1.将图像划分为不重叠的区域块
2.对每个块分别进行直方图均衡化
3.在没有噪声的情况下,每个小区域的灰度直方图会被限制在一个小的灰度级范围内;在有噪声的情况下,每一个分割的区域执行直方图均衡化后,噪声会放大。为了避免出现噪声这种情况,提出限制对比度,如果直方图的bin超过了提前预设好的“限制对比度”,那么就将超出的部分剪裁并均匀分布到其他的bin,这样就重构了直方图。
gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=5.0,tileGridSize=(8,8))
dst = clahe.apply(gray)
clipLimit:对比度限制值,控制直方图均衡化的增益大小,范围在 0-1 之间。如果小于等于 0 则表示没有对比度限制,直方图均衡化的结果与原始图像相同;
tileGridSize:每个 tile 的大小,需要保证整个图像被 tile 完全覆盖,通常选择一个正方形的 tile。例如 (8, 8) 表示每个 tile 的大小为 8 像素。