一,简介:
在摄影中,逆光或强光条件往往会导致图像出现不均匀的曝光,使得主体过暗而背景过亮。本文旨在通过一系列图像处理方法,改善这种光照不均的问题,从而恢复图像的细节和色彩平衡。通过这种校正,即使是逆光或强光条件下的照片,也能展现出更自然和均匀的光照效果。
二,方案简述:
本方案通过读取图像,将其转换为灰度图并计算平方确定阴影区域,然后根据设定的校正亮度参数创建过渡矩阵以调整图像的亮度和对比度,最后通过指数函数和掩码实现阴影区域的平滑提亮,最终得到校正后的图像。
三,算法实现步骤:
3.1 获得图像的阴影区域:
首先,将输入图像转换为浮点类型并归一化,使其像素值范围在0到1之间,便于后续的数值计算。然后,将归一化的图像转换为灰度图,以便简化处理并专注于亮度信息。接着,计算灰度图的平方,这一步是为了放大亮度较低的区域,使其在后续处理中更容易被识别为阴影区域。之后,计算这些平方值的平均值,用作区分阴影区域和非阴影区域的阈值。最后,根据这个阈值创建一个掩码,将图像中亮度低于平均值的区域(即阴影区域)标记为白色(255),而其他区域标记为黑色(0)。
实现代码:
# 将输入图像转换为浮点类型并归一化,便于后续处理
f = input_image.astype(np.float32) / 255.0
# 使用OpenCV将归一化的图像转换为灰度图
gray = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)
# 计算灰度图的平方,用以确定阴影区域
thresh = (1.0 - gray) ** 2
# 计算阴影区域的平均值,用作后续的阈值
t = np.mean(thresh)
# 创建一个掩码,标记阴影区域(高于平均值的区域)
mask = np.where(thresh >= t, 255, 0).astype(np.uint8)
3.2 调整阴影区域的亮度和对比度
获得图像的阴影区域之后需要对图像的阴影区域进行调整,通过计算校正参数并创建两个过渡矩阵,分别用于调整图像的对比度和亮度,实现了对逆光条件下图像阴影区域的校正,通过指数函数和平滑过渡,使图像在阴影区域与非阴影区域之间达到自然的亮度与对比度变化,最终得到校正后的图像。
实现代码:
max_val = 4 # 最大校正范围
bright = light / 100.0 / max_val # 计算校正强度
mid = 1.0 + max_val * bright # 计算中间值
# 创建两个过渡矩阵,用于调整图像的亮度和对比度
midrate = np.where(mask == 255, mid, ((mid - 1.0) / t * thresh) + 1.0)
brightrate = np.where(mask == 255, bright, (1.0 / t * thresh) * bright)
# 使用指数函数调整图像亮度,并通过掩码实现平滑过渡
result = np.clip(pow(f, 1.0 / midrate[:, :, np.newaxis]), 0.0, 1.0)
# 根据计算出的亮度率调整图像,限制值在0到1之间
result = np.clip(result * (1.0 / (1 - brightrate[:, :, np.newaxis])), 0.0, 1.0) * 255
# 将结果转换为8位无符号整型,以便显示和保存
result = result.astype(np.uint8)
四:整体代码
import cv2
import numpy as np
def shadow(input_image, light):
# 将输入图像转换为浮点类型并归一化,便于后续处理
f = input_image.astype(np.float32) / 255.0
# 使用OpenCV将归一化的图像转换为灰度图
gray = cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)
# 计算灰度图的平方,用以确定阴影区域
thresh = (1.0 - gray) ** 2
# 计算阴影区域的平均值,用作后续的阈值
t = np.mean(thresh)
# 创建一个掩码,标记阴影区域(高于平均值的区域)
mask = np.where(thresh >= t, 255, 0).astype(np.uint8)
# 设置校正参数
max_val = 4 # 最大校正范围
bright = light / 100.0 / max_val # 计算校正强度
mid = 1.0 + max_val * bright # 计算中间值
# 创建两个过渡矩阵,用于调整图像的亮度和对比度
midrate = np.where(mask == 255, mid, ((mid - 1.0) / t * thresh) + 1.0)
brightrate = np.where(mask == 255, bright, (1.0 / t * thresh) * bright)
# 使用指数函数调整图像亮度,并通过掩码实现平滑过渡
result = np.clip(pow(f, 1.0 / midrate[:, :, np.newaxis]), 0.0, 1.0)
# 根据计算出的亮度率调整图像,限制值在0到1之间
result = np.clip(result * (1.0 / (1 - brightrate[:, :, np.newaxis])), 0.0, 1.0) * 255
# 将结果转换为8位无符号整型,以便显示和保存
result = result.astype(np.uint8)
return result
# 主程序
# 读取图像文件
src = cv2.imread(r"F:\traditional_vison\2.jpg")
# 设置校正亮度参数,负值表示减少亮度,正值表示增加亮度 取值为-100到100
light = -50
# 调用阴影校正函数
result = shadow(src, light)
# 显示原始图像和校正后的图像
cv2.imshow("original", src)
cv2.imshow("result", result)
# 等待按键后关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
五,效果:
原图:
光照增强百分之五十:
光照减弱百分之五十: