画像の畳み込みの間に事前に熟成した方法を使用して、アルファブリードの問題を解決する方法は?
-
27-10-2019 - |
質問
透明な画像にボックスブラーを適用しようとしていますが、エッジの周りに「暗いハロー」を取得しています。
ジェリー・ハクステーブル 問題について短い言及があります, 、そして問題が起こることを示す非常に良いデモンストレーション:
しかし、私は、私の人生のために、どのように理解できません」事前に行われたアルファ「問題を解決できます。非常に簡単な例では、1つの赤と1つの緑色のピクセルを含む3x3画像があります。
実際には、残りのピクセルは透明です:
次に、3x3ボックスのぼかしを画像に適用します。単純化のために、センターピクセルの新しい値のみを計算します。ボックスブラーの仕組みは、9位の正方形(3x3、カーネルと呼ばれる)があるため、カーネルの各ピクセルの1/9を取得し、それを追加することです。
そう
finalRed = 1/9 * red1 + 1/9 * red2 + 1/9 * red3+ ... + 1/9 * red9
finalGreen = 1/9*green1 + 1/9*green2 + 1/9*green3+ ... + 1/9*green9
finalBlue = 1/9* blue1 + 1/9* blue2 + 1/9* blue3+ ... + 1/9* blue9
finalAlpha = 1/9*alpha1 + 1/9*alpha2 + 1/9*alpha3+ ... + 1/9*alpha9
この非常に単純化された例では、計算は非常に単純になります。
finalRed = 1/9 * 255
finalGreen = 1/9 * 255
finalBlue = 0
finalAlpha = 1/9*255 + 1/9*255
これにより、次のような最終的な色の値が得られます。
finalRed = 28
finalGreen = 28
finalBlue = 0
finalAlpha = 56 (22.2%)
この色は暗すぎます。 Photoshopで同じ3x3ピクセル画像で3pxボックスブラーを実行すると、予想されることがわかります。
白に表示されると、これはより明確です:
実際には、透明なテキストを含むビットマップでボックスブラーを実行しています。
私はにあるGDI+ビットマップから始めています PixelFormat32bppARGB
フォーマット
3x3畳み込みカーネルを適用するときに、「事前に栽培されたアルファ」を使用するにはどうすればよいですか?
回答には、新しいForumlaを含める必要があります。
final = 1/9*(pixel1+pixel2+pixel3...+pixel9)
私に間違った答えを得ています。
編集: 簡単な例は、次のとおりです。
0..1の範囲で色とアルファ値でこの数学を実行します:
ボックスブラー畳み込みフィルターを中央のピクセルに適用します。
ARGB'
= 1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0) +
1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0) +
1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0);
= (0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0) +
(0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0) +
(0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0)
= (0, 0.33, 0, 0.33)
これはかなり透明な濃い緑を与えます。
それは私が見たいと思っているものではありません。そして比較すると、Photoshopのボックスブラーは次のとおりです。
私が仮定するなら (0, 0.33, 0, 0.33)
事前に行われたアルファであり、それは不変です、私は得ます:
(0, 1, 0, 0.33)
これは私のすべての透明の例に適しています。しかし、部分的に透明なピクセルを巻き始めたとき、私は何をすべきかわかりません。
参照してください
解決
Tkerwinは持っています すでに正解を提供しました, 、しかし、それはさらなる説明が必要なようです。
あなたがあなたの質問に示した数学は、最後まで絶対に正しいです。ステップが欠けているのはそこにあります - 結果はまだ事前に行われたアルファモードであり、pixelformat32bppargb形式に「翻訳されていない」必要があります。増加の反対は格差です。したがって、次のとおりです。
finalRed = finalRed * 255 / finalAlpha;
finalGreen = finalGreen * 255 / finalAlpha;
finalBlue = finalBlue * 255 / finalAlpha;
あなたは、格差が範囲外の結果を生み出すかもしれないという懸念を表明しましたが、それは起こりません。数学を追跡すると、事前拡大ステップのため、赤、緑、青の値はアルファ値よりも大きくないことがわかります。単純なボックスブラーよりも複雑なフィルターを使用している場合、それは可能性があるかもしれませんが、アルファを使用していなくてもそうです!正しい応答は、結果をクランプし、負の数を0に変え、255を超えるものを255に変えることです。
他のヒント
あなたのリンクのアドバイスに従って、あなたはぼやけた後、ぼやけた後にぼやけてun-premultiplyの前に事前に熟成します。あなたの例では、半透明のピクセルがないため、事前総合は実際には何もしません。あなたはぼかしをしました、そしてあなたはあなたが実行することによってあなたを非プレマルチプリーが必要とします(0から1の正規化された色の値を仮定します)::
RGB' = RGB/A (if A is > 0)
A' = A
これにより、非総命令のぼやけた最終イメージが得られます。
両方の答えがここで間違っているように見えます。
Porter Duffによると、適切なブレンドモードを使用してください。
FG.RGB + (1.0 - FG.Alpha)*BG.RGB
残りの答えがどこから来ているのかわからないが、すごい。
アルファエンコーディングは、オーバー操作を決定します。