“阴影/高光”命令是一种用于校正由强逆光而形成剪影的照片,或者校正由于太接近相机闪光灯而有些发白的焦点的方法。在用其他方式采光的图像中,这种调整也可用于使阴影区域变亮。“阴影/高光”命令不是简单地使图像变亮或变暗,它基于阴影或高光中的周围像素(局部相邻像素)增亮或变暗。正因为如此,阴影和高光都有各自的控制选项。默认值设置为修复具有逆光问题的图像,来自 Adobe 官网。
阴影:
主要用于提亮阴影区域,对非阴影区几乎不产生效果
数量:用于控制阴影区要校正的程度,值越大,阴影区域被提的越亮
色调:控制被提亮的阴影区域的范围,较小的值会限制只对较暗的区域进行提亮,值越大,影响的阴影范围越宽
半径:控制每个像素周围的局部相邻像素的大小
高光:
主要用于压暗高光区域,对非高光区几乎不产生效果
数量:用于控制高光区要校正的程度,值越大,高光区域被压的越暗
色调:控制被压暗的高光区域的范围,较小的值会限制只对较亮的区域进行压暗,值越大,影响的高光范围越宽
半径:控制每个像素周围的局部相邻像素的大小
调整:
颜色:正值增加阴影区被提亮像素和高光区被压暗像素的饱和度,负值为减小饱和度
中间调:用来调整中间调的对比度,负值降低对比度,正值增加对比度
修剪黑色:设定将图像中多少比例的阴影变成纯黑
修剪白色:设定将图像中多少比例的高光变成纯白
Python 实现阴影区抠取及阴影区提亮
自动提前阴影区域,具体方式见我的另一一篇博客《Python 用 OpenCV 实现 PS 高光/阴影选区》
阴影区域提取:
先将原图转成灰度图,然后对灰度图做反相后做为两个输入源做正交叠底,对结果做阈值限制后输出
luminance = (1 - luminance) * (1 - luminance)
luminance = np.where(luminance > shadowThreshold, luminance, 0)
然后对阴影区提亮,并对非阴影去做过渡,否则会有明显边界。
提亮使用的非线性亮度调整,公式为伽马矫正公式,见《PS 色阶调整之算法公式原理详解及 Python 实现》中的中间调调整。
依赖的环境:Python3 numpy OpenCV
# -*- coding: utf-8 -*-
# @Time : 2021-04-26 19:45
# @Author : AlanWang4523
# @FileName: ps_shadow_highlight.py
import os
import sys
import cv2
import numpy as np
class PSShadowHighlight:
"""
色阶调整
"""
def __init__(self, image):
self.shadows_light = 50
img = image.astype(np.float)/255.0
srcR = img[:, :, 2]
srcG = img[:, :, 1]
srcB = img[:, :, 0]
srcGray = 0.299 * srcR + 0.587 * srcG + 0.114 * srcB
# 高光选区
# luminance = luminance * luminance
# luminance = np.where(luminance > 0.64, luminance, 0)
# 阴影选区
luminance = (1 - srcGray) * (1 - srcGray)
self.maskThreshold = np.mean(luminance)
mask = luminance > self.maskThreshold
imgRow=np.size(img, 0)
imgCol=np.size(img, 1)
print("imgRow:%d, imgCol:%d, maskThreshold:%f" % (imgRow, imgCol, self.maskThreshold))
print("shape:", img.shape)
self.rgbMask = np.zeros([imgRow, imgCol, 3], dtype = bool)
self.rgbMask[:, :, 0] = self.rgbMask[:, :, 1] = self.rgbMask[:, :, 2] = mask
self.rgbLuminance = np.zeros([imgRow, imgCol, 3], dtype = float)
self.rgbLuminance[:, :, 0] = self.rgbLuminance[:, :, 1] = self.rgbLuminance[:, :, 2] = luminance
self.midtonesRate = np.zeros([imgRow, imgCol, 3], dtype = float)
self.brightnessRate = np.zeros([imgRow, imgCol, 3], dtype = float)
def adjust_image(self, img):
maxRate = 4
brightness = (self.shadows_light / 100.0 - 0.0001) / maxRate
midtones = 1 + maxRate * brightness
self.midtonesRate[self.rgbMask] = midtones
self.midtonesRate[~self.rgbMask] = (midtones - 1.0) / self.maskThreshold * self.rgbLuminance[~self.rgbMask] + 1.0
self.brightnessRate[self.rgbMask] = brightness
self.brightnessRate[~self.rgbMask] = (1 / self.maskThreshold * self.rgbLuminance[~self.rgbMask]) * brightness
outImg = 255 * np.power(img / 255.0, 1.0 / self.midtonesRate) * (1.0 / (1 - self.brightnessRate))
img = outImg
img[img < 0] = 0
img[img > 255] = 255
img = img.astype(np.uint8)
return img
def ps_shadow_highlight_adjust_and_save_img(psSH, origin_image):
psSH.shadows_light = 50
image = psSH.adjust_image(origin_image)
cv2.imwrite('py_sh_out_01.png', image)
def ps_shadow_highlight_adjust(path):
"""
阴影提亮调整
"""
origin_image = cv2.imread(path)
psSH = PSShadowHighlight(origin_image)
# ps_shadow_highlight_adjust_and_save_img(psSH, origin_image)
def update_shadows_light(x):
psSH.shadows_light = x
# 创建图片显示窗口
title = "ShadowHighlight"
cv2.namedWindow(title, cv2.WINDOW_NORMAL)
cv2.resizeWindow(title, 800, 600)
cv2.moveWindow(title, 0, 0)
# 创建阴影提亮操作窗口
option_title = "Option"
cv2.namedWindow(option_title, cv2.WINDOW_NORMAL)
cv2.resizeWindow(option_title, 400, 20)
cv2.moveWindow(option_title, 0, 630)
cv2.createTrackbar('shadows_light', option_title, psSH.shadows_light, 100, update_shadows_light)
while True:
image = psSH.adjust_image(origin_image)
cv2.imshow(title, image)
if cv2.waitKey(1) == ord('q'):
break
cv2.destroyAllWindows()
if __name__ == '__main__':
'''
运行环境:Python 3
执行:python3 ps_shadow_hightlight.py <图片路径>
如:python3 ps_shadow_hightlight.py test.jpg
'''
if len(sys.argv) == 1:
print("参数错误:未传入图片路径!")
sys.exit(-1)
img_path = sys.argv[1]
print("img_path Params:", img_path)
ps_shadow_highlight_adjust(img_path)
默认效果(程度 50%)与 PS 中阴影的默认效果对比:
下图为与 PS 默认效果对比,左边为 PS 默认效果(数量 30,色调 50%,半径 30,饱和度 +20),右边为上面的 python 实现的默认 50% 程度的效果,基本差不多。
其他逆光图片的效果图:
以下是 Python 实现的在其他图片效果,左边是原图,右边是处理后的图,默认参数都是 50%,阴影阈值使用的正交叠底后的均值(每张图自动计算,不需人为修改):