Wie kann ich während der Bildverarbeitung vormultiplimiert werden, um das Problem mit Alpha-Blutungen zu lösen?

StackOverflow https://stackoverflow.com/questions/4854839

Frage

Ich versuche, eine Box -Unschärfe auf ein transparentes Bild anzuwenden, und ich bekomme einen "dunklen Halo" an den Rändern.

Jerry Huxtable hat eine kurze Erwähnung des Problems, und eine sehr gute Demonstration, die das Problem zeigt:

enter image description here

Aber ich kann für mein Leben nicht verstehen, wie "vor-multiplimiertes Alpha"Kann das Problem beheben. Jetzt für ein sehr einfaches Beispiel. Ich habe ein 3x3 -Bild, das ein rotes und ein grünes Pixel enthält:

enter image description here

In Wirklichkeit sind die verbleibenden Pixel transparent:

enter image description here

Jetzt werden wir eine 3x3 -Box -Unschärfe auf das Bild anwenden. Für die Einfachheiten werden wir nur den neuen Wert des Mittelpixels berechnen. Die Art und Weise, wie eine Box -Unschärfe funktioniert, ist, dass wir, da wir ein 9 -Positions -Quadrat (3x3, als Kernel genannt) haben, 1/9 von jedem Pixel im Kernel einnehmen und sie hinzufügen:

enter image description here

So

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

In diesem sehr vereinfachten Beispiel werden die Berechnungen sehr einfach:

finalRed =   1/9 * 255
finalGreen = 1/9 * 255
finalBlue =  0
finalAlpha = 1/9*255 + 1/9*255

Dies gibt mir einen endgültigen Farbwert von:

finalRed =   28
finalGreen = 28
finalBlue =  0
finalAlpha = 56 (22.2%)

enter image description here

Diese Farbe ist zu dunkel. Wenn ich in Photoshop eine 3px -Box -Unschärfe auf demselben 3x3 -Pixel -Bild ausführe, bekomme ich das, was ich erwarte:

enter image description here

Das ist klarer, wenn es über Weiß angezeigt wird:

enter image description here


In Wirklichkeit führe ich eine Box-Unschärfe auf einer Bitmap mit transparentem Text durch und der Text erhält die verräterische Dunkelheit um die Ränder:

enter image description here

Ich fange mit einer GDI+ Bitmap an, in der sich befindet PixelFormat32bppARGB Format


Wie verwende ich "Pre-Multiplied Alpha", wenn ich den 3x3-Faltungskernel anwende?

Jede Antwort muss neue Forumla enthalten, da:

final = 1/9*(pixel1+pixel2+pixel3...+pixel9)

Bekommt mir die falsche Antwort.


Bearbeiten: Ein einfacheres Beispiel ist:

Ich werde diese Mathematik mit Farb- und Alpha -Werten im Bereich von 0..1 ausführen:

enter image description here

Ich werde den Faltungsfilter des Box Blur -Faltungsfilters auf das mittlere Pixel anwenden:

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)

Das gibt ein ziemlich transparentes dunkelgrünes.

enter image description here

Das ist nicht das, was ich erwarte zu sehen. Und im Vergleich ist Photoshops Box Blur::

enter image description here

Wenn ich annehme (0, 0.33, 0, 0.33) ist vormultiplimiert Alpha, und ich bekomme es nicht, ich bekomme:

(0, 1, 0, 0.33)

enter image description here

Was für mein All-Opaque-Beispiel richtig aussieht; Aber ich weiß nicht, was ich tun soll, wenn ich anfange, teilweise transparente Pixel einzubeziehen.

Siehe auch

War es hilfreich?

Lösung

Tkerwin hat Bereits die richtige Antwort bereitgestellt, aber es scheint eine weitere Erklärung zu brauchen.

Die Mathematik, die Sie in Ihrer Frage gezeigt haben, ist absolut korrekt, bis zum Ende. Dort fehlt Ihnen ein Schritt - die Ergebnisse befinden sich immer noch in einem vormultiplimierten Alpha -Modus und müssen in das PixelFormat32BPPARGB -Format "unmultiplipliert" werden. Das Gegenteil eines Multiplikums ist eine Kluft, also:

finalRed = finalRed * 255 / finalAlpha;
finalGreen = finalGreen * 255 / finalAlpha;
finalBlue = finalBlue * 255 / finalAlpha;

Sie haben besorgt darüber geäußert, dass die Kluft ein Ergebnis erzielt, das wild außerhalb der Reichweite ist, aber das wird nicht passieren. Wenn Sie die Mathematik nachverfolgen, werden Sie feststellen, dass die rot, grün und blauen Werte aufgrund des Schritts vor der Multiplikation nicht größer sein als der Alpha-Wert. Wenn Sie einen komplizierteren Filter als eine einfache Box -Unschärfe verwenden, könnte dies eine Möglichkeit sein, aber das wäre der Fall, selbst wenn Sie nicht Alpha verwenden! Die korrekte Reaktion besteht darin, das Ergebnis zu klemmen und negative Zahlen in 0 und alles mehr als 255 in 255 zu verwandeln.

Andere Tipps

Befolgen Sie den Rat in Ihrem Link, bevor Sie sich vor dem Unschärfen und unbemultieren nach dem Unschärfen befinden. In Ihrem Beispiel tut das Vorbinden tatsächlich nichts, da es keine halbtransparenten Pixel gibt. Sie haben die Unschärfe gemacht, dann brauchen Sie Sie unpre-multiply (unter der Annahme normalisierter Farbwerte von 0 bis 1):

RGB' = RGB/A  (if A is > 0)
A' = A

Dadurch erhalten Sie ein nicht-multiplimiertes, verschwommenes Endbild.

Beide Antworten erscheinen hier falsch.

Verwenden Sie den richtigen Mischmodus, der nach Porter Duff lautet:

FG.RGB + (1.0 - FG.Alpha)*BG.RGB

Ich bin mir nicht sicher, woher der Rest der Antworten kommt, aber wow.

Die Alpha -Codierung bestimmt den Over Operation.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top