使用Python和OpenCV实现超快速,简单的伽玛校正功能
这篇博客将介绍伽马校正(也称为幂律变换)是什么,并将演示如何使用Python和OpenCV实现超快速,简单的伽玛校正功能。
使用伽玛校正的原因是因为眼睛与数码相机中的传感器所感知的颜色和亮度不同。
当数码相机上的传感器接收到两倍数量的光子时,信号将加倍(线性关系)。但是当光子增加一倍时,眼睛感知到的光量只是原来的一小部分(非线性关系)。
伽玛校正可以看作是眼睛灵敏度和相机传感器之间的转换。
学习完可以尝试对自己的照片进行伽玛校正。查找过暗或过亮并被过量曝光的图像。然后对这些图像进行伽玛校正,看它们是否在视觉上更具吸引力。
1. 效果图
原图 VS 0.1伽玛值 如下:
原图 VS 0.5伽玛值 如下:
原图 VS 1.5伽玛值 如下:
- 可以看到伽玛值0.1使得图像足够暗没法看;
- 伽玛值为0.5会使结果图像显得比原始图像更暗;
- 伽玛值1.5使得结果图像比原始图像更亮,基本会报废掉;
上图效果不是很明显,下边的右侧伽玛图像更具有吸引力,对比度更强,比原始图更好看
2. 什么是伽玛校正?
- Gamma correction 伽玛校正
- the Power Law Transform 幂律变换
伽玛校正也称为幂律变换。首先,图像像素强度必须在[0,255]到[0,1.0]的范围内缩放。然后可以通过应用以下方程式获得输出的伽玛校正图像:
O = I ^(1 / G)
其中I是输入图像,G是伽玛值。然后将输出图像O缩放回范围[0,255]。
伽玛值<1将使图像移向光谱的较暗端,而伽玛值> 1将使图像显得较亮。 Gamma值G = 1对输入图像没有影响。
有两种(简单)的方法可以使用OpenCV和Python进行伽玛校正:
- 简单地利用Python + OpenCV将图像表示为NumPy数组。只需将像素强度缩放到[0,1.0]范围,应用变换,然后再缩放回[0,255]范围。总体而言,NumPy方法涉及除法,加到幂,再乘以乘法-由于所有这些运算都是矢量化的,因此非常快。
- 借助OpenCV,可以更快地执行伽玛校正。需要建立一张表格(即字典),将输入像素值映射到输出经过伽玛校正的值。然后,OpenCV可以获取该表并快速确定O(1)时间中给定像素的输出值。
3. 源码
# Gamma correction and the Power Law Transform,伽马校正也称幂律交换;使图像变得更亮或者更暗的方法;
# USAGE
# python adjust_gamma.py --image images/_L3A4387.jpg
# 导入必要的包
from __future__ import print_function
import numpy as np
import argparse
import cv2
import imutils
# 伽马校正
# --image 要对其应用伽玛校正的图像。
# --gamma (可选)伽玛值,默认1.0
def adjust_gamma(image, gamma=1.0):
# 建立查找表,将像素值[0,255]映射到调整后的伽玛值
# 遍历[0,255]范围内的所有像素值来构建查找表,然后再提高到反伽马的幂-然后将该值存储在表格中
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# 使用查找表应用伽玛校正
return cv2.LUT(image, table)
# 构建命令行参数及解析
# --image 图像路径
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True,
help="path to input image")
args = vars(ap.parse_args())
# 加载原始图像
original = cv2.imread(args["image"])
original = imutils.resize(original, width=300)
# 通过使用各种伽玛值并检查每个图像的输出图像来探索伽玛校正;
# 遍历各种不同的伽马值
for gamma in np.arange(0.0, 2, 0.5):
# 忽略伽马值为1的情况,因为跟原始图像没有任何差别
if gamma == 1:
continue
# 应用伽马校正并展示图像
gamma = gamma if gamma > 0 else 0.1
adjusted = adjust_gamma(original, gamma=gamma)
cv2.putText(adjusted, "g={}".format(gamma), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 3)
cv2.imshow("Images", np.hstack([original, adjusted]))
name = str(args['image']).replace(".jpg", "_" + str(gamma) + ".jpg")
cv2.imwrite(name, adjusted)
cv2.waitKey(0)