所以我看着GIMP source code ......新!我使它具有通用性和可讀性。 雖然還是挺快的。 數學解釋見Sampo's answer。 這裏的C#實現(容易轉化爲C/C++):
static class PixelShaders {
/// <summary>
/// Generic color space color to alpha.
/// </summary>
/// <param name="pA">Pixel alpha.</param>
/// <param name="p1">Pixel 1st channel.</param>
/// <param name="p2">Pixel 2nd channel.</param>
/// <param name="p3">Pixel 3rd channel.</param>
/// <param name="r1">Reference 1st channel.</param>
/// <param name="r2">Reference 2nd channel.</param>
/// <param name="r3">Reference 3rd channel.</param>
/// <param name="mA">Maximum alpha value.</param>
/// <param name="mX">Maximum channel value.</param>
static void GColorToAlpha(ref double pA, ref double p1, ref double p2, ref double p3, double r1, double r2, double r3, double mA = 1.0, double mX = 1.0) {
double aA, a1, a2, a3;
// a1 calculation: minimal alpha giving r1 from p1
if (p1 > r1) a1 = mA * (p1 - r1)/(mX - r1);
else if (p1 < r1) a1 = mA * (r1 - p1)/r1;
else a1 = 0.0;
// a2 calculation: minimal alpha giving r2 from p2
if (p2 > r2) a2 = mA * (p2 - r2)/(mX - r2);
else if (p2 < r2) a2 = mA * (r2 - p2)/r2;
else a2 = 0.0;
// a3 calculation: minimal alpha giving r3 from p3
if (p3 > r3) a3 = mA * (p3 - r3)/(mX - r3);
else if (p3 < r3) a3 = mA * (r3 - p3)/r3;
else a3 = 0.0;
// aA calculation: max(a1, a2, a3)
aA = a1;
if (a2 > aA) aA = a2;
if (a3 > aA) aA = a3;
// apply aA to pixel:
if (aA >= mA/mX) {
pA = aA * pA/mA;
p1 = mA * (p1 - r1)/aA + r1;
p2 = mA * (p2 - r2)/aA + r2;
p3 = mA * (p3 - r3)/aA + r3;
} else {
pA = 0;
p1 = 0;
p2 = 0;
p3 = 0;
}
}
}
GIMP的實現(here)使用RGB顏色空間,使用α值作爲float
用0至1米範圍內,並且R,G,B作爲float
從0到255之間。
當圖像具有JPEG僞像時,RGB實現失敗,因爲它們意味着無法察覺的顏色偏差,但是相當顯着的絕對R,G,B偏差。使用LAB色彩空間應該可以解決這個問題。
如果您只是想從圖像中移除純色背景,則顏色轉換爲alpha算法不是最佳選擇。當使用LAB色彩空間計算每個像素的色彩空間距離時,我得到了很好的結果。計算出的距離然後應用於原始圖像的alpha通道。這和alpha顏色的主要區別是像素的色調不會改變。背景刪除只是設置阿爾法(不透明度)以色彩空間差異。如果在前景圖像中不出現背景顏色,則效果很好。如果它確實無法去除背景,或者必須使用BFS算法來僅行走外像素(就像在GIMP中使用魔術棒選擇,然後移除選區一樣)。
如果前景圖像同時具有類似於背景顏色的孔和像素顏色,則不能移除背景。這些圖像需要一些手動處理。
相關問題:http://stackoverflow.com/questions/9282714/how-to-change-the-alpha-of-a-pixel-without-changing-the-resulting-color – 2012-02-16 21:00:43
@MarkRansom我知道,你發佈了一個鏈接的問題是相關的,因爲問那個問題的人就是我! :)儘管你的公式可以達到這個Gimp特性的效果,但這個謎仍然存在,因爲我在Gimp的來源中看到的複雜程度高於你的公式。 – 2012-02-17 15:41:09
@MarkRansom繼續:但是你的方法似乎比Gimp更靈活,因爲通過重寫方程組的解決方案,可以將圖像從一種顏色的背景中「剪切」出來,並將其放置在另一種顏色的背景上,圖像仍然看起來一樣。所以我想這個問題已經沒有太大的意義了,所以如果沒有人不介意的話,我會註冊這個問題進行刪除。 – 2012-02-17 15:42:34