0

我一直在尝试实现 GEGL 混合模式、颜色减淡减法,作为 Python 中 POC 的一部分。我遵循的流程是减法成功的道奇。我一直在为我的实现参考以下来源:

  1. SVG 合成规范:https ://www.w3.org/TR/SVGCompositing/#comp-op-property
  2. Color DodgeSubtract的 GEGL 实现。

颜色减淡混合工作正常,并且“几乎”与 GIMP 结果相同(对于某些像素,我得到的强度差异最大为 1,但这足以满足我的需要)。但是,我从 Subtract 获得的结果与在 GIMP 中观察到的结果完全不同。我理解 Subtract 是每个通道单独的简单的每个元素差异。

我使用线性 RGB。以下是我的 Python 实现:

import cv2
import numpy as np

# Colour Dodge mode
# Alpha channel is assumed to be 1 (Opacity 100%) as this serves the purpose and 
# simplifies implementation.
def applyColourDodge(srcImage, destImage, alphaImage, iterations):
    aComp =  alphaCh + alphaCh - alphaCh * alphaCh
    
    sCdC = srcImage + destImage
    numComponents = srcImage.shape;
    numDims = len(numComponents);
    compImage = srcImage.copy()

    isAlphaPresent = False
    for channel in range(0, numComponents[numDims-1]):
        numRows = srcImage.shape[0]
        numCols = srcImage.shape[1]
        for row in range(0, numRows):
            for col in range (0, numCols):
                if (sCdC[row,col, channel] >= 1):
                    compImage[row, col, channel] = 1
                else:
                    if (srcImage[row, col, channel] == 1):
                        compImage[row, col, channel] = 1
                    else:
                        cD = destImage[row, col, channel]
                        cS = srcImage[row, col, channel]

                        if (cD == 1):
                            compImage[row, col, channel] = 1
                        else:
                            compImage[row, col, channel] = cS/(1 - cD)

    if (isAlphaPresent):
        compImage[:,:,numComponents[numDims-1]] = aComp

    return compImage

# Subtract mode
def applySubtract(srcImage, destImage, alphaImage):
    aComp =  alphaCh + alphaCh - alphaCh * alphaCh
    
    numComponents = srcImage.shape;
    numDims = len(numComponents);

    compImage = np.zeros(srcImage.shape, dtype = "float64")
    isAlphaPresent = False
    for ch in range(0, numComponents[numDims-1]):
        compImage[:,:,ch] = srcImage[:,:,ch] - destImage[:,:,ch]

    if (isAlphaPresent):
        compImage[:,:,numComponents[numDims-1]] = aComp

    return compImage

ipFolder = "D:/Work/TIS/IssueWorkedOn/VP-17871 - Dual Colour Capsules/Dual Color Caps Samples/"

ipString = 'Test Image.bmp'
refString = 'Brown Black Dodge Final.bmp'

ipBGR = cv2.imread(ipFolder + ipString, cv2.IMREAD_COLOR)

ipORG = ipBGR.copy() # Retain the original image
ipBGR = ipBGR.astype("float64") 
ipBGR = ipBGR/255 # Normalise in range [0, 1]

alphaCh = np.ones(ipBGR.shape[:2], dtype = "float64") # Alpha channel

srcImage = ipBGR.copy() # Bottom layer
destImage = srcImage.copy() # Top layer

# For debugging purpose
numComponents = ipBGR.shape;
numRows = srcImage.shape[0]
numCols = srcImage.shape[1]
print(ipORG[int(numRows/2),int(numCols/4),:])
print(ipORG[int(numRows/2),int(3*numCols/4),:])

# Actual composite generation. Desired flow: Dodge -> Dodge -> Subtract
compImage = applyColourDodge(srcImage, destImage, alphaCh, 2)
# compImage = applyColourDodge(compImage, srcImage, alphaCh, 2)
compImage = applySubtract(compImage, srcImage, alphaCh)

# Remap in the range [0, 255]
compImage = compImage * 255
compImage = compImage.astype("uint8")

print(compImage[int(numRows/2),int(numCols/4),:])
print(compImage[int(numRows/2),int(3*numCols/4),:])

# For visualisation
orgWin = "Original Image"
filWin = 'Composite Image'
toolWin = 'Tool Composite'

cv2.namedWindow(orgWin, cv2.WINDOW_FREERATIO)
cv2.namedWindow(filWin, cv2.WINDOW_FREERATIO)
cv2.imshow(orgWin, ipBGR)
cv2.imshow(filWin, compImage)
cv2.imshow(toolWin, ipRef)
cv2.waitKey(0)
cv2.destroyAllWindows()

因此,对于减法模式,我将 Dodge 操作的输出作为顶层,将原始源图像作为底层。不透明度设置为 100%,因为这符合我的目的并简化了实现。

代码的结构不干净。所以,请原谅我。首先,我想修复算法。

以下是我用于验证的双色测试图像: Source Image。左半部分的 RGB 三元组:(71, 66, 50),右半部分:(22, 255, 182)。

GIMP 和POC的颜色减淡输出。两幅图像的 RGB 三元组相同 - 左:(98、89、62);右:(24、255、255)。

以下是应用减法后的输出:GIMPPOC。我在最终的合成图像中看到了明显的不同: GIMP 图像的 RGB 三元组:(69, 60, 35) 和 (4, 255, 255) POC 图像的 RGB 三元组:(27, 23, 12) 和 (2, 0 , 73)

我试图在 SO 上找到类似的问题并发现了这个这个这个。但是,这些无法帮助我理解我一直在观察的行为。如果有人可以在这方面帮助我,我将不胜感激。

编辑(2021 年 13 月 10 日): 减去(根据文档):最大(背景 - 前景,0)。似乎 Subtract 不使用 alpha 信息进行混合。因为,我看到了结果的差异,所以尝试用 BG 图像独立测试减法。因此,尝试使用两个普通的 RGB 图像(alpha 设置为 1) - BG:(205,36,50),FG:(125,38,85)。结果颜色 Blended: (170, 234, 0) 不符合上面的数学。

4

0 回答 0