Python の POC の一部として、GEGL ブレンド モード、Color DodgeおよびSubtractを実装しようとしています。私が従う流れは、減算によって成功した回避です。実装のために次のソースを参照しています。
- SVG 合成仕様: https://www.w3.org/TR/SVGCompositing/#comp-op-property
- Color DodgeおよびSubtractの 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()
そのため、減算モードでは、覆い焼き操作の出力をトップ レイヤーに、元のソース イメージをボトム レイヤーにしました。不透明度は 100% に設定されています。これは私の目的を果たし、実装を簡素化するためです。
コードの構造がきれいではありません。では、これで失礼します。まず、アルゴリズムを修正したいと思います。
以下は、検証に使用した 2 色のテスト イメージです: Source Image。左半分の RGB トリプレット: (71, 66, 50)、右半分: (22, 255, 182)。
GIMP とPOCからのColor Dodgeの出力。両方の画像の RGB トリプレットは同じです - 左: (98, 89, 62); 右: (24、255、255)。
Subtract を適用した後の出力は次のとおりです: GIMP、POC。最終的な合成画像に大きな違いが見られます: GIMP 画像の RGB トリプレット: (69, 60, 35) および (4, 255, 255) POC 画像の RGB トリプレット: (27, 23, 12) および (2, 0) 、73)
SOで同様の問題を見つけようとしたところ、これ、これ、およびこれが発見されました。しかし、これらは私が観察してきた行動を理解するのに役立ちませんでした. この点で誰かが私を助けてくれれば幸いです。
編集 (13/10/2021): 減算 (ドキュメントに従って): max(Background - Foreground, 0)。Subtract はブレンドにアルファ情報を使用していないようです。結果に差異が見られたので、BG 画像で個別に Subtract をテストしようとしました。そこで、2 つのプレーンな RGB イメージ (アルファを 1 に設定) で試してみました - BG: (205,36,50)、FG: (125,38,85)。結果として得られる色 Blended: (170, 234, 0) は、上記の計算には当てはまりません。