图像的Gamma 变换
什么是Gamma 变换
Gamma变换是对输⼊图像灰度值进⾏的⾮线性操作,使输出图像灰度值与输⼊图像灰度值呈指数关系:
王者荣耀战斗力
这个指数即为Gamma。
注意这个的取值范围为0~1,因此需要先进⾏归⼀化,然后取指数。
void GetGammaTransLUT(uchar *pLUT, float Gamma, int iLUTLen)
{
for(int i=0;i<iLUTLen;i++)
{
pLUT[i]=(uchar)(pow((float)i/255,Gamma)*255);
}
}
或者:
if (GAMMA_CORRECTION~=1)
%%% gamma correct actual image
obs_im = (double(obs_im).^(GAMMA_CORRECTION))/(256^(GAMMA_CORRECTION-1));
el
obs_im = double(obs_im);
end
Gamma变换就是⽤来图像增强,其提升了暗部细节,简单来说就是通过⾮线性变换,让图像从暴光强度的线性响应变得更接近⼈眼感受的响应,即将漂⽩(相机曝光)或过暗(曝光不⾜)的图⽚,进⾏矫正。
经过Gamma变换后的输⼊和输出图像灰度值关系如图1所⽰:横坐标是输⼊灰度值,纵坐标是输出灰
度值,蓝⾊曲线是gamma值⼩于1时的输⼊输出关系,红⾊曲线是gamma值⼤于1时的输⼊输出关系。可以观察到,当gamma值⼩于1时(蓝⾊曲线),图像的整体亮度值得到工劳
提升,同时低灰度处的对⽐度得到增加,更利于分辩低灰度值时的图像细节。
即可以总结如下:
gamma>1, 较亮的区域灰度被拉伸,较暗的区域灰度被压缩的更暗,图像整体变暗;
gamma<1, 较亮的区域灰度被压缩,较暗的区域灰度被拉伸的较亮,图像整体变亮;
灰度值为0时为⿊⾊,255为⽩⾊。
为什么进⾏Gamma 变换
1. ⼈眼对外界光源的感光值与输⼊光强不是呈线性关系的,⽽是呈指数型关系的。在低照度下,⼈眼
更容易分辨出亮度的变化,随着照度的增加,⼈眼不易分辨出亮度的变化。⽽摄像机感光与输⼊光强呈线性关系。如图2所⽰:
V =out AV in
γV in
2. 为能更有效的保存图像亮度信息,需进⾏Gamma变换。未经Gamma变换和经过Gamma变换保存图像信息如图3所⽰:可以观察
到,未经Gamma变换的情况下,低灰度时,有较⼤范围的灰度值被保存成同⼀个值,造成信息丢失;同时⾼灰度值时,很多⽐较接近的灰度值却被保存成不同的值,造成空间浪费。经过Gamma变
换后,改善了存储的有效性和效率。
3. Gamma矫正⽤在8位RGB图中,⽤来解决在有限的存储空间中保存尽可能多的⼈类感受敏感的⾊彩内容。显⽰器显⽰8位图⽚时,我
们已知现在主流显⽰器的⾊彩要⼤于8位,多数都是32位真彩⾊。显⽰器显⽰的时候也经过了⼀次Gamma校正,它把0.5⼜变成了
大九连环0.2。如果不经过这⼀步,直接输出0.5,因为显⽰器是32位的,那么你在屏幕上得到的将是位于图2中间位置的那个颜⾊,你会说这
个显⽰器有问题,颜⾊不准确,亮瞎了。
8位图与32位图对⽐如下,可以看出,在8位图,⿊⽩分解线在0.2附近,⽽由于32位可以表现的颜⾊多,⽽⼈的眼睛对暗⾊⽐较敏感,因此感觉分界线在0.2附近:
Gamma变换的基本形式
⼤于1时,对图像的灰度分布直⽅图具有拉伸作⽤(使灰度向⾼灰度值延展),⽽⼩于1时,对图像的灰度分布直⽅图具有收缩作⽤(是使灰度向低灰度值⽅向靠拢)。
图2中左图为原图,中图为gamma = 1/2.2在校正结果,原图中左半侧的灰度值较⾼,右半侧的灰度值较低,经过gamma = 1/2.2校正后(中图),左侧的对⽐度降低(见胡须),右侧在对⽐度提⾼(明显可以看清⾯容),同时图像在的整体灰度值提⾼。
右图为gamma = 2.2在校正结果,校正后,左侧的对⽐度提⾼(见胡须),右侧在对⽐度降低(⾯容更不清楚了),同时图像在的整体灰度值降低。
opencv下的gamma矫正
import cv2
#分道计算每个通道的直⽅图外伶仃岛旅游攻略
img0 = cv2.imread('12.jpg')
hist_b = cv2.calcHist([img0],[0],None,[256],[0,256])
hist_g = cv2.calcHist([img0],[1],None,[256],[0,256])
hist_r = cv2.calcHist([img0],[2],None,[256],[0,256])
def gamma_trans(img,gamma):
#具体做法先归⼀化到1,然后gamma作为指数值求出新的像素值再还原
gamma_table =[np.power(x/255.0,gamma)*255.0for x in range(256)]
gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)
#实现映射⽤的是Opencv的查表函数
拳击教程return cv2.LUT(img0,gamma_table)
img0_corrted = gamma_trans(img0,0.5)
cv2.imshow('img0',img0)
cv2.imshow('gamma_image',img0_corrted)
cv2.imwrite('gamma_image.png',img0_corrted)
#分通道计算Gamma校正后的直⽅图
hist_b_c =cv2.calcHist([img0_corrted],[0],None,[256],[0,256])
hist_g_c =cv2.calcHist([img0_corrted],[1],None,[256],[0,256])
发达hist_r_c =cv2.calcHist([img0_corrted],[2],None,[256],[0,256])
fig = plt.figure('gamma')
pix_hists =[[hist_b, hist_g, hist_r],六字成语有哪些
[hist_b_c, hist_g_c, hist_r_c]]
pix_vals =range(256)
for sub_plt, pix_hist in zip([121,122], pix_hists):
ax = fig.add_subplot(sub_plt, projection='3d')
for c, z, channel_hist in zip(['b','g','r'],[20,10,0], pix_hist):
cs =[c]*256
ax.bar(pix_vals, channel_hist, zs=z, zdir='y', color=cs, alpha=0.618, edgecolor='none', lw=0) ax.t_xlabel('Pixel Values')
ax.t_xlim([0,256])
ax.t_ylabel('Count')
ax.t_zlabel('Channels')
plt.show()
cv2.waitKey()
分析用英语怎么说参考资料
One more thing
更多关于⼈⼯智能、Python、C++、计算机等知识,欢迎访问我的个⼈博客进⾏交流,