Alpha合成

在計算機圖形學領域，**Alpha 合成**（英語：alpha compositing）是一種將圖像與背景結合的過程，結合後可以產生部分透明或全透明的視覺效果。Alpha 合成也叫**阿爾法合成**或**透明合成**。渲染圖像時，通常會將目標圖像中的多個子元素單獨渲染，最後再把多張子元素的圖片合成為單獨的圖像。例如，電視直播時就會將大量計算機生成的圖像元素合成到現場鏡頭上。

要正確結合圖像元素，每個元素的必須有對應的遮片。遮片包含覆蓋範圍信息 —— 圖中幾何對象的形狀 —— 可以藉此分辨圖像中的任意位置到底是被繪製的幾何對象本身，還是邏輯上的「空白」區域。

## 描述

為了保存遮片信息，匠白光提出了 Alpha 通道的概念，後由托馬斯・波特和湯姆・達夫完善。二維圖像里記錄著每個像素的顏色信息，額外的信息以 0 和 1 之間的值表示，記錄在 Alpha 通道里。0 表示該像素沒有覆蓋信息，是透明的，即圖中的幾何體沒有覆蓋到本像素；而 1 則表示像素不透明，幾何體完全覆蓋了此像素。

圖像中使用的 Alpha 通道通常有兩種表示形式：**平直 Alpha**（英語：straight alpha）和**預乘 Alpha**（英語：premultiplied alpha）。

* 如果使用平直 Alpha，圖像中的 RGB 分量僅表示像素的顏色，與是否透明無關。
* 如果使用預乘 Alpha，圖像中的 RGB 分量也表示像素的顏色，但事先已經和不透明度做了乘法。某些使用場景下，這樣的做法可以在後續合成時節省一次乘法。不過預乘 Alpha 的最顯著優勢在於使用簡單、準確而非性能。

如果用平直的（非預乘）RGBA 元組表達像素顏色，那麼像素值 (0, 0.7, 0, 0.5) 表示像素有 70% 的最大綠色亮度，同時不透明度是 50%。同樣條件下的純綠色是 (0, 1, 0, 0.5)。而如果用預乘 Alpha，此處的 RGB 值 (0, 0.7, 0) 需要都乘以 0.5，表達為 (0, 0.35, 0, 0.5)。雖然此處 G 通道的值是 0.35 ，但它表示的還是最大亮度的 70%（其中包含了 50% 的不透明度）。此時的純綠色則需要表達為 (0, 0.5, 0, 0.5)。因此，了解圖像（文件）到底使用的是平直 Alpha 還是預乘 Alpha 非常重要，只有這樣才能對圖像做正確的處理和合成。

有了 Alpha 通道，圖片的合成操作就可以用合成代數的形式表達。假設有圖像元素 A 和 B，最常見的合成操作就是把 A 作為前景、B 作為背景，我們稱這種操作（運算）為 **over**，記作 $A\operatorname {over} B$ 。除此之外，波特和達夫還定義了其它幾個運算符：**in**、**out**、**atop**、**xor**：

運算符 **over** 的效果與普通繪畫效果一致（見畫家算法），運算符 **in** 則等價於裁剪。

以運算符 **over** 為例，運算結果相當於對圖像中的所有像素做以下公式：

　
: $\alpha _{o}=\alpha _{a}+\alpha _{b}\left(1-\alpha _{a}\right)$

　
: $C_{o}={\frac {C_{a}\alpha _{a}+C_{b}\alpha _{b}\left(1-\alpha _{a}\right)}{\alpha _{o}}}$

其中 $C_{o}$ 是運算結果， $C_{a}$ 是圖像 A 中的像素， $C_{b}$ 是圖像 B 中的像素，而 $\alpha _{a}$ 和 $\alpha _{b}$ 則分別是圖像 A、B 中對應像素的 Alpha 值。

如果假設顏色值都是預乘了 Alpha 值的（ $c_{i}=\alpha _{i}C_{i}$ ），那麼我們就可以將等式進行改寫，結果圖像中的顏色即：

　
: $c_{o}=c_{a}+c_{b}\left(1-\alpha _{a}\right)$

結果中的 Alpha 值即：

　
: $\alpha _{o}={\frac {c_{o}}{C_{o}}}=\alpha _{a}+\alpha _{b}\left(1-\alpha _{a}\right)$

## over 運算符的解析推導

通過研究正交覆蓋，Porter 和 Buff 給出了 alpha 合成的幾何解釋。在 1981 年 Bruce A. Wallace 的論文裡則給出了另一種基於的反射率 / 透過率的物理模型的另一種推導。

第三種推導方法通過使用兩條簡單的假設得到。為了簡單起見，我們將 **over** 運算符簡記成 $a\odot b$ 。

第一條假設是當背景是不透明（即 $\alpha _{b}=1$ ）時，**over** 運算符表示前景顏色與背景顏色的凸組合：

　
: $C_{o}=\alpha _{a}C_{a}+(1-\alpha _{a})C_{b}$

第二條假設是這種運算應該滿足結合律：

　
: $(a\odot b)\odot c=a\odot (b\odot c)$

現在，可以假設 $a$ 和 $b$ 包含不透明度分量，而 $c$ 不包含。考慮中間變量

　
: $o=a\odot b$ .

由於結合律成立，有

　
: $o\odot c=a\odot (b\odot c)$

由於 $c$ 是不透明的，因此 $b\odot c$ 也是不透明的。由第二條假設，在上面的式子中，上式地每個 $\odot $ 運算都可以用凸組合表達：

　
: ${\begin{aligned}\alpha _{o}C_{o}+(1-\alpha _{o})C_{c}&=\alpha _{a}C_{a}+(1-\alpha _{a})(\alpha _{b}C_{b}+(1-\alpha _{b})C_{c})\\&=[\alpha _{a}C_{a}+(1-\alpha _{a})\alpha _{b}C_{b}]+(1-\alpha _{a})(1-\alpha _{b})C_{c}\end{aligned}}$

這個式子的兩邊都滿足 $X_{0}+Y_{0}C_{c}=X_{1}+Y_{1}C_{c}$ 的形式，令 $X_{0}=X_{1}$ 且 $Y_{0}=Y_{1}$ ，可以得到：

　
: ${\begin{aligned}\alpha _{o}&=1-(1-\alpha _{a})(1-\alpha _{b}),\\C_{o}&={\frac {\alpha _{a}C_{a}+(1-\alpha _{a})\alpha _{b}C_{b}}{\alpha _{o}}},\end{aligned}}$

至此，我們推導出了 $o=a\odot b$ 的顏色和其 alpha 分量的解析式。

注意到 $(1-\alpha _{a})\alpha _{b}=\alpha _{o}-\alpha _{a}$ ，這樣，上式可以緊湊地表示成

　
: $C_{o}={\frac {\alpha _{a}}{\alpha _{o}}}C_{a}+\left(1-{\frac {\alpha _{a}}{\alpha _{o}}}\right)C_{b}$

 $\odot $ 運算符滿足非交換么半群的定義。這個群的單位元 $e$ 是所有滿足 $\alpha =0$ 的二元組 $\langle C,\alpha \rangle $ ，這可以通過式子 $e\odot a=a\odot e=a$ 得到。

## Alpha 混合

**Alpha 混合**（英語：alpha blending）是將半透明的前景色與背景色結合的過程，可以得到混合後的新顏色。前景色的透明度不限，從完全透明到完全不透明都可以。如果前景色完全透明，混合後的顏色就是背景色；如果前景色完全不透明，混合後的顏色就是前景色；如果在這兩種極端情況之間，混合後的顏色可以通過前景色和背景色的加權平均計算。

Alpha 合成後的顏色可以這樣計算：

　
: ${\begin{cases}\mathrm {out} _{A}=\mathrm {src} _{A}+\mathrm {dst} _{A}(1-\mathrm {src} _{A})\\\mathrm {out} _{RGB}={\bigl (}\mathrm {src} _{RGB}\mathrm {src} _{A}+\mathrm {dst} _{RGB}\mathrm {dst} _{A}\left(1-\mathrm {src} _{A}\right){\bigr )}\div \mathrm {out} _{A}\\\mathrm {out} _{A}=0\Rightarrow \mathrm {out} _{RGB}=0\end{cases}}$

如果背景色不透明，即 $dst_{A}=1$ ，代入上述方程後可以得到：

　
: ${\begin{cases}\mathrm {out} _{A}=1\\\mathrm {out} _{RGB}=\mathrm {src} _{RGB}\mathrm {src} _{A}+\mathrm {dst} _{RGB}(1-\mathrm {src} _{A})\end{cases}}$

如果使用了預乘 Alpha，最初的方程組可以簡化為：

　
: ${\begin{cases}\mathrm {out} _{A}=\mathrm {src} _{A}+\mathrm {dst} _{A}(1-\mathrm {src} _{A})\\\mathrm {out} _{RGB}=\mathrm {src} _{RGB}+\mathrm {dst} _{RGB}\left(1-\mathrm {src} _{A}\right)\end{cases}}$

## 伽瑪校正

計算機圖像一般不直接存儲光照亮度對應的 RGB 值，而是需要先對這些值做伽瑪校正。

伽瑪校正的大致過程如下：

* 設 $displayed_{RGB}$ 為屏幕上顯示的 RGB 亮度（標準化後的亮度值，在 0 和 1 之間）
* 設 $stored_{RGB}$ 為計算機內存中所存儲的 RGB 亮度（也是標準化後的亮度值）
* 設 $\gamma $ 為用於「解碼」 $stored_{RGB}$ 圖像的伽瑪值 2.2（2.2 為 $\gamma $ 的典型取值）

則它們三者之間的關係為

　
: $displayed_{RGB}={stored_{RGB}}^{\gamma }$

因此，在處理計算機圖像的 RGB 值時（尤其是做 Alpha 混合時），可以在處理前先將伽瑪校正消除，完成處理後再重新做伽瑪校正，這樣做的效果比直接處理伽瑪校正後的 RGB 值要好。

例如有一張圖片 $overlay_{rgb}$ ，它對應的 Alpha 通道為 $overlay_{\alpha }$ ，現在要把它疊加到背景圖 $background_{rgb}$ 上，那麼最終的圖像 $out_{rgb}$ 可以這樣計算：

　
: $out_{rgb}=({overlay_{rgb}}^{\gamma }\times overlay_{\alpha }+{background_{rgb}}^{\gamma }\times (1-overlay_{\alpha }))^{1/\gamma }$

此處的 $out_{rgb}$ 是計算機內存中所存儲的數據；在計算機顯示器上會以 $out_{rgb}^{\gamma }$ 的數據顯示。

## 參考資料