You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中实现CIE L*a*b*图像的多方向色彩曲线调整?

实现Photoshop风格的Lab*通道多方向曲线调整

伽马校正确实只能处理单调的幂函数型调整,没法实现Photoshop曲线工具那种灵活的多区间、多方向调整——毕竟伽马只是曲线工具里的一个特例而已。要复刻PS里的曲线调整效果,核心思路是自定义像素值的映射表(LUT),因为PS的曲线本质就是把输入像素值映射到你指定的输出值,我们可以用插值的方法生成平滑的映射表,然后应用到Lab*的各个通道上。

下面是具体实现方案和代码:

核心原理

Photoshop的曲线工具允许你在0-255的像素范围内设置任意控制点,软件会自动插值生成平滑的映射曲线。我们可以用同样的逻辑:

  1. 为每个通道(L、a、b)定义你想要的控制点(比如暗部、中间调、高光的输入输出值)
  2. 用插值算法(比如三次样条插值)生成完整的0-255像素值映射表(LUT)
  3. 将这个LUT应用到对应的Lab*通道上,最后合并通道转回RGB/BGR格式

代码实现

首先写一个生成自定义曲线LUT的工具函数,以及通道调整函数:

import numpy as np
import cv2
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d

def create_curve_lut(points):
    # 控制点格式:[(输入像素值, 输出像素值), ...],比如[(0,10), (127,160), (255,255)]
    # 先按输入值排序,避免插值出错
    sorted_points = sorted(points, key=lambda x: x[0])
    inputs = np.array([p[0] for p in sorted_points])
    outputs = np.array([p[1] for p in sorted_points])
    
    # 用三次样条插值生成平滑曲线,和PS的曲线平滑度一致
    interp_func = interp1d(inputs, outputs, kind='cubic', fill_value="extrapolate")
    
    # 生成0到255的完整映射表
    lut = np.round(interp_func(np.arange(0, 256))).astype(np.uint8)
    # 确保所有值都在0-255的合法范围内
    lut = np.clip(lut, 0, 255)
    return lut

def apply_curve_to_channel(channel, lut):
    # 用OpenCV的LUT函数快速应用映射
    return cv2.LUT(channel, lut)

然后结合Lab*通道的完整工作流:

# 读取你的图像(OpenCV默认是BGR格式)
image_BGR = cv2.imread("your_image_path.jpg")

# 转换到L*a*b*色彩空间
lab_image = cv2.cvtColor(image_BGR, cv2.COLOR_BGR2LAB)
L, a, b = cv2.split(lab_image)

# 为每个通道定义自定义曲线控制点,你可以根据需求修改
# L通道示例:暗部稍微压暗,中间调提亮,高光保持不变
L_curve_points = [(0, 10), (60, 50), (127, 160), (200, 220), (255, 255)]
# a通道示例:增加红色(a通道正值方向),弱化绿色(负值方向)
a_curve_points = [(0, 0), (127, 140), (255, 255)]
# b通道示例:增加黄色(b通道负值方向),弱化蓝色(正值方向)
b_curve_points = [(0, 30), (127, 110), (255, 220)]

# 生成各通道的映射表
L_lut = create_curve_lut(L_curve_points)
a_lut = create_curve_lut(a_curve_points)
b_lut = create_curve_lut(b_curve_points)

# 应用曲线到每个通道
adjusted_L = apply_curve_to_channel(L, L_lut)
adjusted_a = apply_curve_to_channel(a, a_lut)
adjusted_b = apply_curve_to_channel(b, b_lut)

# 合并通道并转换回BGR格式
adjusted_lab = cv2.merge([adjusted_L, adjusted_a, adjusted_b])
final_image = cv2.cvtColor(adjusted_lab, cv2.COLOR_LAB2BGR)

# 对比原图和调整后的效果
cv2.imshow("Original vs Adjusted", np.hstack([image_BGR, final_image]))
cv2.waitKey(0)
cv2.destroyAllWindows()

额外技巧:可视化调整曲线

如果你想直观看到自己定义的曲线形状,可以加一个绘图函数:

def plot_curve(lut):
    plt.figure(figsize=(8, 4))
    plt.plot(np.arange(0, 256), lut, linewidth=2)
    plt.xlabel("Input Pixel Value")
    plt.ylabel("Output Pixel Value")
    plt.title("Custom Adjustment Curve")
    plt.grid(True, linestyle="--", alpha=0.7)
    plt.show()

# 示例:查看L通道的曲线形状
plot_curve(L_lut)

为什么这个方法比伽马校正更好?

  • 伽马校正只是单调的幂函数调整,只能整体提亮或压暗;而自定义曲线可以在不同像素区间做差异化调整(比如暗部压暗同时中间调提亮),实现多方向的精细控制。
  • 每个通道独立调整,不会出现伽马校正那种容易导致的色彩偏移问题,因为你可以精准控制a、b通道的色彩偏向。
  • 三次样条插值生成的曲线平滑自然,和Photoshop的曲线工具效果几乎一致。

内容的提问来源于stack exchange,提问作者Deepti Hegde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:22:05