伽马变换
伽马变换主要用于图像的校正,将灰度过高 或者 灰度过低的图片进行修正,增强对比度。变换公式就是对原图像上每一个像素值做乘积运算:
伽马变换对图像的修正作用其实就是通过增强低灰度或高灰度的细节实现的,从伽马曲线可以直观理解:
一句话解释:其实就是说,在人眼看来,亮度并不是线性变化的(对深色更敏感),所以需要做一个映射,来让人眼感觉色彩是均匀变化的。这个映射就是所谓的gamma校正。
我们看下面这张图,左边在亮度上其实是均匀变化的,但是在我们人眼看来,深色数量远多于亮色。通过一个非线性校正后(右图),我们人眼看来就是均匀变化的了。这也就是gamma校正的目的
实际测出来人眼需要的gamma值是2.2
如上图所示,为函数 f ( I ) = I γ的曲线表示:
当γ < 1 时,为图中上方的虚线曲线,图中γ = 1 / 2.2
当γ = 1 时,为图中间的直线,也就是f ( I ) = I
当γ > 1 时, 为图中下方的曲线实线,图中γ = 2.2
当γ ! = 1时,会将对I进行非线性的变换,对0,1两端的变换最小,对中间的变换最大。如果把图像0-255像素值,归一化到0-1, 带入进来,通过该变换,则可达到一定的效果:
1)当γ < 1 时,图像中最亮(1)或者最暗(0)的像素保持不变,整体亮度会发生提升,像素值中间的部分效果最明显,用来处理比较暗的图片非常好
2)当γ > 1 时,图像中最亮(1)或者最暗(0)的像素保持不变,整体亮度会发生降低,像素值中间的部分效果最明显,用来处理比较亮的图片非常好
最后x255即可
demo1
import numpy as np
def imadjust(img, in_range=[0, 1], out_range=[0, 1], gamma=1):
# 默认参数和matlab中的默认参数相同
low_in, high_in = in_range[0], in_range[1]
low_out, high_out = out_range[0], out_range[1]
# 百分比截断
p1, p99 = np.percentile(img, (1, 99))
img_out = np.clip(img, p1, p99)
# 映射 参考https://stackoverflow.com/questions/39767612/what-is-the-equivalent-of-matlabs-imadjust-in-python
img_out = (((img_out - low_in) / (high_in - low_in)) ** gamma) * (high_out - low_out) + low_out
return img_out
demo2
import cv2
import numpy as np
import math
import os
def gamma_trans(img, gamma): # gamma函数处理
gamma_table = [np.power(x / 255.0, gamma) * 255.0 for x in range(256)] # 建立映射表
gamma_table = np.round(np.array(gamma_table)).astype(np.uint8) # 颜色值为整数
return cv2.LUT(img, gamma_table) # 图片颜色查表。另外可以根据光强(颜色)均匀化原则设计自适应算法。
def nothing(x):
pass
data_base_dir = r'./1' # 输入文件夹的路径
outfile_dir = r'./2' # 输出文件夹的路径
list = os.listdir(data_base_dir)
list.sort()
list2 = os.listdir(outfile_dir)
list2.sort()
for file in list: # 遍历目标文件夹图片
read_img_name = data_base_dir + '/' + file.strip() # 取图片完整路径
image = cv2.imread(read_img_name) # 读入图片
img_gray = cv2.imread(read_img_name, 0) # 灰度图读取,用于计算gamma值
mean = np.mean(img_gray)
gamma_val = math.log10(0.5) / math.log10(mean / 255) # 公式计算gamma
image_gamma_correct = gamma_trans(image, gamma_val) # gamma变换
out_img_name = outfile_dir + '/' + file.strip()
cv2.imwrite(out_img_name, image_gamma_correct)
print("The photo which is processed is {}".format(file))
r = 1/2.2 效果如下图