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

Python复现GIMP Addition图层混合模式与原生效果不一致如何解决

核心问题原因

你目前的代码是直接在伽马编码的sRGB空间对像素值做加法,而GIMP 2.10及以上版本默认启用线性空间混合,Addition模式的运算会先把两个图层的像素从伽马校正的sRGB空间转换到线性RGB空间,执行加法截断后再转换回sRGB空间输出,这是两者结果存在亮度差异的核心原因。

复现GIMP Addition模式的代码
import cv2
import numpy as np
from PIL import Image

def srgb_to_linear(img):
    # 输入为0-255的uint8 sRGB图像,输出0-1范围的线性RGB数组
    img = img.astype(np.float32) / 255.0
    mask = img <= 0.04045
    img[mask] = img[mask] / 12.92
    img[~mask] = np.power((img[~mask] + 0.055) / 1.055, 2.4)
    return img

def linear_to_srgb(img):
    # 输入为0-1范围的线性RGB数组,输出0-255的uint8 sRGB图像
    mask = img <= 0.0031308
    img[mask] = img[mask] * 12.92
    img[~mask] = 1.055 * np.power(img[~mask], 1/2.4) - 0.055
    return (img * 255).astype(np.uint8)

# 读取图像
diffuse = cv2.imread('diffuse.png')
reflection = cv2.imread('reflection.png')
# 转RGB
diffuse = cv2.cvtColor(diffuse, cv2.COLOR_BGR2RGB)
reflection = cv2.cvtColor(reflection, cv2.COLOR_BGR2RGB)

# 转线性空间
linear_diffuse = srgb_to_linear(diffuse)
linear_reflection = srgb_to_linear(reflection)

# 线性空间执行饱和加法
linear_add = np.clip(linear_diffuse + linear_reflection, 0.0, 1.0)

# 转回sRGB空间
result = linear_to_srgb(linear_add)

# 保存
im = Image.fromarray(result)
im.save('blended_python.png')
额外注意事项
  • 如果你的GIMP关闭了线性空间混合选项(路径:编辑→首选项→图像默认值→默认混合空间),不需要做伽马转换,直接调用cv2.add(diffuse, reflection)就能得到完全一致的结果,该函数原生支持饱和运算,不需要手动转类型做截断。
  • 如果图像带有alpha透明通道,读取时需要添加cv2.IMREAD_UNCHANGED参数,混合前需要先做预乘alpha处理,避免透明区域出现色偏。

内容的提问来源于stack exchange,提问作者Mitchell van Zuylen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 16:36:00