Metlivi Blog

So entfernen oder verfestigen Sie halbtransparente Pixel in gerenderten Charakter-Frames

Um halbtransparente Pixel aus gerenderten Charakter-Frames zu entfernen, ändern Sie ihre Alphawerte entweder in vollständig transparent oder vollständig deckend. Entscheiden Sie, ob Sie alle teilweise transparenten Pixel löschen, alle sichtbaren Pixel verfestigen oder einen Schwellenwert verwenden möchten, der die stärkeren Teile der Kontur erhält.

Dieser Workflow richtet sich an Kreative, die transparente Charakter-PNG-Frames mit klaren Kanten vorbereiten. Er umfasst eine visuelle Methode in GIMP und eine wiederholbare Python-Methode für einen ganzen Frame-Ordner, einschließlich Prüfungen, ob die exportierten Bilder keine Zwischenwerte des Alphakanals enthalten.

29. Oktober 20268 Min. LesezeitVon Metlivi Editorial Team
Abschnitt 1

Was genau muss im Frame geändert werden?

Bei einem 8-Bit-RGBA-Bild hat jedes Pixel die Komponenten Rot, Grün, Blau und Alpha. Alpha 0 bedeutet vollständig transparent, Alpha 255 vollständig deckend. Werte von 1 bis 254 sind teilweise transparent. Pillow beschreibt RGBA als vier 8-Bit-Kanäle mit einer Transparenzmaske. Pillow: Concepts

Ein Frame kann daher fast vollständig deckend aussehen und dennoch viele teilweise transparente Pixel enthalten. Prüfen Sie vor der Bearbeitung eine Kopie in der vorgesehenen Anzeigegröße und in einer vergrößerten Pixelansicht. Legen Sie vorübergehend helle und dunkle Hintergründe darunter. Achten Sie auf schwache äußere Pixel, fehlende schmale Details und Farbsäume.

Entscheiden Sie, ob Teiltransparenz im fertigen Bild erhalten bleiben soll. Ein durchscheinendes Accessoire oder ein weicher Schatten verändert sich deutlich, wenn es in eine deckende oder transparente Maske gezwungen wird. Wenn nur die Charakterkontur korrigiert werden muss, grenzen Sie diesen Bereich oder diese Ebene ein, bevor Sie eine globale Operation anwenden.

Bewahren Sie die original gerenderten Frames auf. Durch das Schwellenwertverfahren werden viele Alphawerte auf zwei Endpunkte reduziert, sodass sich der ursprüngliche Transparenzgrad dieser Pixel in der bearbeiteten Datei nicht mehr nachvollziehen lässt.

Abschnitt 2

Sollten Sie teilweise transparente Pixel entfernen oder deckend machen?

Verwenden Sie für die gesamte Frame-Sequenz dieselbe eindeutige Regel. In der folgenden Tabelle ist C der minimale Alphawert, der erhalten bleibt, und jedes erhaltene Pixel wird vollständig deckend. Diese Regeln gelten für 8-Bit-Eingaben.

Gewünschtes Ergebnis Regel Wichtigster visueller Kompromiss
Alle halbtransparenten Pixel entfernen Nur Alpha 255 beibehalten Schmale Details, die ausschließlich aus teilweise transparenten Pixeln bestehen, verschwinden
Alle sichtbaren Pixel deckend machen Alpha 1–255 beibehalten Schwache äußere Pixel werden Teil der deckenden Silhouette
Eine Zwischenstufe für die Kontur wählen Alpha ≥ C beibehalten; Alpha < C verwerfen Der Schwellenwert bestimmt, welche Kantenpixel erhalten bleiben

Betrachten Sie beispielsweise die veranschaulichenden Alphawerte 0, 1, 64, 127, 128, 254, 255. Bei C = 128 wird die Ausgabe zu 0, 0, 0, 0, 255, 255, 255. Bei C = 255 bleibt nur das letzte Pixel erhalten. Bei C = 1 wird jedes ursprünglich sichtbare Pixel deckend.

Beginnen Sie zum Vergleich mit C = 128 und prüfen Sie dann den tatsächlichen Charakter. Das ist ein praktischer Mittelwert, aber keine allgemein als optimal anerkannte Einstellung. Erhöhen Sie den Wert, wenn unerwünschte schwache Pixel verbleiben; senken Sie ihn, wenn nützliche Details verschwinden. Verwenden Sie für jeden Vergleich wieder den Original-Frame.

Wenn ein höherer Schwellenwert zwar einen Saum entfernt, aber zugleich ein wichtiges Detail unterbricht, kann ein einzelner globaler Schwellenwert nicht beide Ziele erfüllen. Korrigieren Sie das Detail lokal oder trennen Sie es vor der Verarbeitung der restlichen Kontur in eine eigene Maske.

Abschnitt 3

Wie lässt sich der Alphakanal in GIMP mit einem Schwellenwert bearbeiten?

GIMP 3 bietet Ebene → Transparenz → Alphawert-Schwelle…. Die Funktion wirkt auf eine einzelne Ebene, erfordert einen Alphakanal und hat keine Wirkung, wenn Alphakanal sperren aktiviert ist. Der Schwellenwert reicht von 0 bis 1: Werte über dem Schwellenwert werden deckend, während Werte gleich dem oder kleiner als der Schwellenwert transparent werden. GIMP: Threshold Alpha

  1. Öffnen Sie eine Kopie des Frames und wählen Sie die Charakterebene aus.
  2. Vergewissern Sie sich, dass sie einen Alphakanal hat, und deaktivieren Sie Alphakanal sperren.
  3. Öffnen Sie Ebene → Transparenz → Alphawert-Schwelle….
  4. Sehen Sie sich eine Vorschau mit einem Schwellenwert von 0,5 für einen mittleren Schnitt oder 0 an, um jedes Pixel mit einem Alphawert ungleich null deckend zu machen.
  5. Prüfen Sie kleine Details und die äußere Kontur, bevor Sie die Operation anwenden.
  6. Exportieren Sie das Ergebnis als separate PNG-Datei.

Bei 8-Bit-Eingaben behält ein Schwellenwert von 254/255, ungefähr 0,996078, nur Pixel bei, deren ursprünglicher Alphawert 255 war. Vermeiden Sie dafür den Schwellenwert 1: Bei dem dokumentierten strikten Vergleich liegt selbst Alpha 1 auf dem Schwellenwert und wird transparent. GIMP: Threshold Alpha

Achten Sie darauf, dass vorübergehende Prüfhintergründe nicht in die exportierte Charakterdatei gelangen. Öffnen Sie die PNG-Datei anschließend erneut, damit Sie sowohl das exportierte Ergebnis als auch das bearbeitbare Dokument beurteilen.

Abschnitt 4

Wie lässt sich dieselbe Regel auf jeden Frame anwenden?

Verwenden Sie für mehrere Frames eine feste Alphawert-Zuordnung, statt jedes Bild einzeln anzupassen. Das folgende vollständige Python-Programm verarbeitet die PNG-Dateien direkt in einem Ordner, behält ihre Namen und Abmessungen bei und schreibt sie in einen neuen Ordner.

Installieren Sie Pillow mit python -m pip install Pillow und speichern Sie das Programm dann als alpha_clean.py. Verwenden Sie separate, statische 8-Bit-RGBA-PNG-Frames. Exportieren Sie Palettenbilder, Renderings mit höherer Farbtiefe oder andere Bildtypen bewusst in dieses Format, bevor Sie diesen Workflow verwenden.

Das Programm extrahiert den Alphakanal mit getchannel, ordnet ihn mithilfe einer Nachschlagetabelle über point zu und ersetzt mit putalpha ausschließlich den Alphakanal. Diese Operationen sind in der Pillow Image module reference dokumentiert.

import argparse
from pathlib import Path
from PIL import Image


def threshold_alpha(image, cutoff):
    result = image.copy()
    table = [255 if value >= cutoff else 0 for value in range(256)]
    result.putalpha(image.getchannel("A").point(table))
    return result


def partial_count(image):
    return sum(image.getchannel("A").histogram()[1:255])


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("source", type=Path)
    parser.add_argument("destination", type=Path)
    parser.add_argument("--cutoff", type=int, default=128)
    parser.add_argument("--demo", action="store_true")
    args = parser.parse_args()

    if not 1 <= args.cutoff <= 255:
        parser.error("--cutoff must be between 1 and 255")

    if args.demo:
        values = [0, 1, 64, 127, 128, 254, 255]
        sample = Image.new("RGBA", (len(values), 1))
        sample.putdata([(80, 160, 220, a) for a in values])
        result = threshold_alpha(sample, args.cutoff)
        print([result.getpixel((x, 0))[3] for x in range(len(values))])
        return

    if not args.source.is_dir():
        parser.error("Source must be an existing folder")
    if args.destination.exists():
        parser.error("Destination must be a new folder")

    files = sorted(
        p for p in args.source.iterdir()
        if p.is_file() and p.suffix.lower() == ".png"
    )
    if not files:
        parser.error("No PNG frames found directly inside source")

    args.destination.mkdir(parents=True)
    for path in files:
        with Image.open(path) as image:
            if image.format != "PNG" or image.mode != "RGBA":
                raise ValueError(f"{path.name}: expected RGBA PNG")
            if getattr(image, "n_frames", 1) != 1:
                raise ValueError(f"{path.name}: expected a single frame")
            before = partial_count(image)
            result = threshold_alpha(image, args.cutoff)
            target = args.destination / path.name
            result.save(target, format="PNG")

        with Image.open(target) as saved:
            after = partial_count(saved)
            if saved.size != result.size or after != 0:
                raise RuntimeError(f"{target.name}: verification failed")
        print(f"{path.name}: partial pixels {before} -> {after}")


if __name__ == "__main__":
    main()

Führen Sie zuerst das eigenständige Beispiel aus. Im Demomodus werden die beiden Ordnerargumente angenommen, aber keiner der beiden Ordner wird gelesen oder erstellt:

python alpha_clean.py unused_input unused_output --demo --cutoff 128

Es gibt [0, 0, 0, 0, 255, 255, 255] aus. Die zugrunde liegenden Zuordnungen für die Schwellenwerte 1, 128 und 255, unveränderte RGB-Werte sowie das Speichern und erneute Öffnen von PNG-Dateien wurden mit einem In-Memory-Beispiel unter Verwendung von Pillow 13.0.0 überprüft.

Legen Sie Ihre tatsächlichen PNG-Frames in einem Ordner namens frames ab und führen Sie dann Folgendes aus:

python alpha_clean.py frames frames_clean --cutoff 128

Verwenden Sie --cutoff 255, um alle halbtransparenten Pixel zu löschen, oder --cutoff 1, um alle sichtbaren Pixel deckend zu machen. Wählen Sie für jeden Vergleich einen neuen Zielordner.

Das Programm wird bei nicht unterstützten Eingaben oder einer fehlgeschlagenen Prüfung angehalten. Vor einem Fehler bereits verarbeitete Dateien bleiben im Zielordner; dieser Ordner enthält dann einen unvollständigen Durchlauf. Korrigieren Sie die Eingabe und führen Sie das Programm erneut in einem anderen neuen Ordner aus. Das Programm durchläuft keine Unterordner, bewahrt keine Animationszeiten und ist kein allgemeines Werkzeug zur Erhaltung von Metadaten.

Abschnitt 5

Warum kann eine verfestigte Kante dennoch dunkel oder blass wirken?

Die Alphabereinigung ändert die Deckung. Die Kantenfarbe muss separat geprüft werden. Microsoft unterscheidet zwischen geradem Alpha, bei dem RGB und Alpha unabhängig sind, und vormultipliziertem Alpha, bei dem RGB bereits mit Alpha multipliziert wurde. Microsoft Learn: Premultiplied alpha

Als veranschaulichende Berechnung entspricht ein gerades Rot (200, 0, 0) mit Alpha 0,25 dem vormultiplizierten RGB-Wert (50, 0, 0). Werden diese vormultiplizierten Farbwerte fälschlich als gerades RGB behandelt und Alpha einfach auf 1 erhöht, entsteht ein dunkelrotes Pixel. Das ergibt sich direkt aus dem dokumentierten Umrechnungsverhältnis. Microsoft Learn: Premultiplied alpha

Der Python-Workflow setzt korrekt codierte RGBA-PNG-Eingaben mit geradem Alpha voraus. Er kann falsch codierte Farben weder erkennen noch die beabsichtigte Konturfarbe rekonstruieren. Wenn beim Verfestigen von Pixeln ein Saum sichtbar wird, prüfen Sie zuerst, wie Alpha beim ursprünglichen Rendern oder Export interpretiert wurde. Falls die Farbe selbst durch eine frühere Hintergrundkomposition verfälscht wurde, verwenden Sie wieder ein sauberes transparentes Rendering oder malen Sie die betroffene Kante neu.

Vergleichen Sie den bereinigten Frame vor hellem und dunklem Hintergrund. Eine Anzahl von null teilweise transparenten Pixeln belegt, dass der Alphakanal binär ist; sie belegt nicht, dass die Kantenfarben zum Charakter passen.

Abschnitt 6

Wie bleibt die Bereinigung beim Export und bei der Wiedergabe erhalten?

Nehmen Sie Größenänderungen vor der abschließenden Alphabereinigung vor. Bei interpolierendem Resampling können Zwischenwerte zwischen transparenten und deckenden Pixeln entstehen. Pillow beschreibt bilineares Resampling als Berechnung von Werten durch Interpolation, während die Nächster-Nachbar-Methode ein vorhandenes Eingabepixel auswählt. Daher bleiben beim Verkleinern oder Vergrößern eines binären Alphakanals mit der Nächster-Nachbar-Methode seine beiden Endwerte erhalten. Pillow: Concepts—Filters

Verwenden Sie Nächster-Nachbar, wenn der gewünschte Look ein diskretes Pixelraster vorsieht. Für einen anderen visuellen Stil skalieren Sie zuerst mit dem gewünschten Filter, wenden anschließend auf die resultierenden Frames den Schwellenwert an und prüfen deren Konturen erneut. Eine spätere Skalierung oder Komposition sollte eine erneute Prüfung der endgültigen Ausgabe nach sich ziehen.

Prüfen Sie die gesamte Sequenz mit demselben Schwellenwert. Ein schmales Element kann zwischen benachbarten Frames den Schwellenwert überschreiten und flackernd wirken, obwohl jeder Frame einzeln akzeptabel aussieht. Prüfen Sie in diesem Fall die Original-Frames rund um den Wechsel und korrigieren Sie das Element in diesen Frames einheitlich.

Prüfen Sie vor der Verwendung der Sequenz die folgenden konkreten Punkte:

  • Jeder erwartete Frame ist mit seinem ursprünglichen Dateinamen und seinen ursprünglichen Abmessungen der Arbeitsfläche vorhanden.
  • Jeder gespeicherte Frame enthält null Pixel mit Alphawerten von 1 bis 254.
  • Kleine Details bleiben in der vorgesehenen Anzeigegröße lesbar.
  • Vorschauen vor hellem und dunklem Hintergrund zeigen keine unerwünschten Säume.
  • Bei der Wiedergabe bleibt die Silhouette während der gesamten Bewegung stimmig.

Wählen Sie die Alpharegel, die die beabsichtigte Form des Charakters erhält, wenden Sie sie einheitlich an und prüfen Sie die exportierte Sequenz. Bewahren Sie die Original-Renderings zusammen mit den bereinigten Frames auf, damit spätere Anpassungen auf den vollständigen Transparenzinformationen aufbauen können.

Abschnitt 7

Quellen

Weitere Artikel

Dieses Thema weiter erkunden