4 Punkte von GN⁺ 2025-05-28 | 1 Kommentare | Auf WhatsApp teilen
  • Rational Bloom Filter Video Compression implementiert einen verlustfreien Workflow, bei dem Rohvideo komprimiert wird und das wiederhergestellte Ergebnis bitgenau mit dem Original übereinstimmen muss
  • Der Kern besteht darin, bei Bloom-Filtern eine nicht-ganzzahlige Anzahl von Hash-Funktionen einzusetzen, um theoretisch eine bessere Kompressionsrate als herkömmliche Ansätze zu erzielen
  • Ziel sind Raw-Video-Inhalte wie Y4M, YUV und HDR; für typische Videos wird eine Speicherersparnis von 40–50 % angegeben
  • Die Implementierung basiert auf Python 3.7+ und benötigt Abhängigkeiten wie numpy, opencv-python, xxhash, Pillow, scikit-image sowie pyexr für HDR
  • Enthalten sind Benchmarks zum Vergleich mit FFV1, HuffYUV und dem verlustfreien Modus von H.264; vor einem praktischen Einsatz sollte man die Ergebnisse und Reproduktionsschritte in results.md prüfen

Überblick über Rational Bloom Filter Video Compression

  • Dieses Projekt implementiert ein Verfahren zur verlustfreien Videokompression auf Basis eines rational Bloom filter
  • Bloom-Filter werden als probabilistische Datenstruktur zur effizienten Darstellung binärer Daten verwendet
  • Der Unterschied besteht darin, dass im Bloom-Filter eine nicht-ganzzahlige rational hash function verwendet wird
  • Ziel ist, dass das nach der Kompression wiederhergestellte Ergebnis bit-exact mit dem Original übereinstimmt

Unterstützte Inhalte und Kompressionsfunktionen

  • Das Kompressionssystem richtet sich an Raw-Video-Inhalte wie Y4M, YUV und HDR
  • Es bietet folgende Funktionen
    • True lossless compression mit garantiert bitgenauer Wiederherstellung
    • 40–50 % Speicherersparnis bei typischen Videoinhalten
    • Encoding und Decoding mit Multithreading-Unterstützung
    • Unterstützung mehrerer Color Spaces wie RGB, BGR und YUV
    • Unterstützung für die Verarbeitung von HDR-Inhalten
  • Für die HDR-Verarbeitung gilt die Einschränkung, dass „noch mehr Arbeit nötig ist, um sie schnell und nutzbar zu machen“

Installationsanforderungen

  • Die Laufzeitumgebung ist Python 3.7+
  • Benötigt werden folgende Pakete
    • numpy
    • opencv-python
    • matplotlib
    • pandas
    • tqdm
    • requests
    • xxhash
    • Pillow
    • scikit-image
    • pyexr: für HDR-Unterstützung
  • Die Abhängigkeiten werden mit folgendem Befehl installiert
pip install -r requirements.txt

Grundlegende Verwendung

  • In Python-Code wird ImprovedVideoCompressor importiert und der Kompressor initialisiert
  • Die Beispielkonfiguration enthält noise_tolerance=10.0, keyframe_interval=30, use_direct_yuv=True und verbose=True
  • compress_video() komprimiert das Eingabevideo in eine .bfvc-Datei
  • decompress_video() stellt eine .bfvc-Datei wieder her
  • Mit verify_lossless() wird geprüft, ob Original-Frames und wiederhergestellte Frames verlustfrei übereinstimmen
from improved_video_compressor import ImprovedVideoCompressor

compressor = ImprovedVideoCompressor(
    noise_tolerance=10.0,
    keyframe_interval=30,
    use_direct_yuv=True,
    verbose=True
)

compressor.compress_video(
    input_file="input_video.y4m",
    output_file="compressed.bfvc"
)

compressor.decompress_video(
    input_file="compressed.bfvc",
    output_file="decompressed.mp4"
)

original_frames = compressor.extract_frames_from_video("input_video.y4m")
decompressed_frames = compressor.decompress_video("compressed.bfvc")
verification = compressor.verify_lossless(original_frames, decompressed_frames)
print(f"Lossless: {verification['lossless']}")

Nutzung über die Kommandozeile

  • Videokompression wird wie folgt ausgeführt
python -m improved_video_compressor compress input_video.y4m output.bfvc --max-frames 30
  • Raw-YUV-Dateien werden verarbeitet, indem Breite, Höhe und Format gemeinsam angegeben werden
python -m improved_video_compressor process-yuv input.yuv output.bfvc --width 1920 --height 1080 --format YUV444

Benchmarks und Vergleichsmethoden

  • Das Projekt enthält ein Benchmark-System, das die Rational-Bloom-Filter-Kompression mit anderen verlustfreien Kompressionsverfahren vergleicht
  • Verglichen wird mit FFV1, HuffYUV und dem verlustfreien Modus von H.264
  • Der vollständige Benchmark wird mit folgendem Befehl ausgeführt
python benchmark_compression.py
  • Es lassen sich auch nur bestimmte Datensätze und Methoden angeben
python benchmark_compression.py --datasets y4m --methods bloom ffv1 --max-frames 10
  • Detaillierte Benchmark-Ergebnisse und Reproduktionsanweisungen stehen in results.md

Ablauf des Kompressionsverfahrens

  • Das Kompressionsschema arbeitet in folgenden Schritten
    • Frame Extraction: Extrahiert Frames aus dem Eingabevideo
    • Keyframe Selection: Keyframes werden direkt als zlib-komprimierte Frames gespeichert
    • Bloom Filter Compression: Inter-Frames werden als Differenzkarten mit einem rational Bloom filter komprimiert
    • Lossless Verification: Prüft während des Decodings die bitgenaue Wiederherstellung
  • Der rational Bloom filter verwendet eine nicht-ganzzahlige Anzahl von Hash-Funktionen k*, um das Gleichgewicht zwischen Speicherbedarf und Genauigkeit zu optimieren
  • Die Implementierung verwendet deterministisch ⌊k*⌋ Hash-Funktionen; eine zusätzliche Hash-Funktion wird mit der Wahrscheinlichkeit k* - ⌊k*⌋ angewendet

Projektdateien

  • improved_video_compressor.py: main implementation des Kompressionsalgorithmus
  • verify_true_lossless.py: Skript zur Überprüfung der verlustfreien Wiederherstellung
  • benchmark_compression.py: Benchmark-System zum Vergleich mehrerer Kompressionsverfahren
  • download_*.py: Skripte zum Herunterladen von Testdatensätzen
  • results.md: Detaillierte Benchmark-Ergebnisse und Analyse

Lizenz und Zitierung

  • Die Lizenz ist die MIT License; Details stehen in der Datei LICENSE
  • Wer den Code in Forschungsarbeiten verwendet, wird darauf hingewiesen, die im README enthaltene Citation im BibTeX-Format zu nutzen

1 Kommentare

 
GN⁺ 2025-05-28
Meinungen auf Hacker News
  • Das Dokument scheint eine sehr einfache Idee nicht gut zu erklären. Wenn ich es richtig verstanden habe, erstellt man zuerst eine Bitmap, in der jedes Bit als Pixel eines Bildes betrachtet wird, und setzt beim Übergang von Frame 0 zu Frame 1 geänderte Pixel auf 1, sonst auf 0.
    Anschließend hasht man die Offsets der Positionen mit Wert 1 und legt sie in einen Bloom-Filter. Dann werden diese Indizes sowie ein gewisser Anteil falsch positiver Indizes als positiv ausgegeben.
    Danach fragt man den Bloom-Filter ab, findet alle positiven Indizes und speichert für diese Pixel die geänderten Roh-Pixeldaten; so lässt sich der nächste Frame leicht rekonstruieren.
    Man kann das als Verfahren sehen, bei dem das Delta zwischen zwei Frames als x,y,r,g,b aller geänderten Pixel gespeichert wird, wobei der x,y-Teil stark komprimiert wird und dafür etwas mehr r,g,b gespeichert wird als nötig.
    Da die Positionen der Pixel, die sich von Frame 0→1 ändern, häufig ähnlich zu den Positionen sind, die sich von Frame 1→2 ändern, scheint es noch weiteres Kompressionspotenzial zu geben, wenn man im nächsten Frame ein passendes Flag setzt und nur die gegenüber zuvor zusätzlich geänderten Offsets unverändert speichert.

    • Ich frage mich, wie gut die tatsächliche Kompressionsrate ist. Das erinnert mich daran, wie ich vor etwa 22 Jahren mit Wavelets für Bildkompression experimentiert habe.
      Die inverse Transformation beginnt mit einem kleinen Pixelbild und wandelt es mit derselben Anzahl an Koeffizienten in ein Bild mit doppelter Breite oder Höhe um, und das wird wiederholt.
      Der Kernpunkt ist, dass der Großteil der Daten aus Koeffizienten besteht und die meisten davon nahe bei 0 liegen, sodass man sie auf 0 drücken kann. Dann wird die Frage, wie man die Nicht-Null-Positionen codiert, und man landet bei Strukturen wie einer Bitmap plus einem Array der Nicht-Null-Werte.
      Die Algorithmen zum Codieren der Nicht-Null-Werte unterschieden sich darin, wie konservativ sie waren, nutzten aber meist aus, dass diese Werte ziemlich stark geclustert sind. Das ist das genaue Gegenteil der üblichen Hash-Funktionen, die man für Bloom-Filter verwendet.
      Diese Art von Bildkompression war sowohl bei der Transformation selbst als auch bei der Koeffizientenkompression wegen der sehr schlechten Lokalität langsam und fühlte sich deshalb wie eine Sackgasse an.
    • Wenn man die Delta-Änderungen von einem Frame zum nächsten speichert, sind unveränderte Pixel einfach 0. Folgen von Nullen zu komprimieren ist bei verlustfreier Kompression die trivialste Aufgabe, und anders als bei Bloom-Filtern gibt es keine False Positives.
      Ich kann mir vorstellen, dass Bloom-Filter als Teil einer komplexen hybriden Kompressionsstrategie nützlich sein können. Bei solchen Kompressoren gilt: je mehr Werkzeuge, desto besser; im Durchschnitt erwarte ich aber keine große Verbesserung.
    • Ich frage mich, welchen Vorteil ein Bloom-Filter gegenüber so etwas wie einer Hash-Tabelle bringt.
    • Ein großer Teil der Videokompression besteht darin, Bewegung zu behandeln. Ich frage mich, wie der Fall verarbeitet wird, dass durch Panning dieselben Pixel zwei Pixel nach links rutschen.
  • Das Eingabevideo ist bereits ein von YouTube nach Kompression wiederhergestelltes Video, deshalb scheint es besser zu funktionieren.
    Bei Eingabe des Originalvideos dürfte die Annahme brechen, dass „sich zwischen aufeinanderfolgenden Frames die meisten Pixel nur wenig oder gar nicht ändern, sodass eine dünn besetzte Differenzmatrix entsteht“.
    Bei einem sehr sauberen Signal, etwa einem rauscharmen Sensor und einer hellen Szene, könnte das möglich sein, aber bei den meisten realen Signalen ist das Rauschen größer als 1 LSB, sodass ich erwarten würde, dass sich mindestens etwa die Hälfte der unteren Bits ändert.
    Wenn ein Video einmal durch Kompression und Wiederherstellung gegangen ist, wird solches Rauschen tendenziell entfernt, wodurch ein künstlich statisches Video entsteht, bei dem diese Annahme gilt.

    • So wie es aussieht, ist auch das nicht verlustfrei: https://github.com/ross39/new_bloom_filter_repo/blob/main/vi...
      Es scheint, dass für Pixel, deren durchschnittliche Änderung der r,g,b-Werte unter 10 liegt, keine Differenz gespeichert wird. Dann könnte ein Pixel, das sich in aufeinanderfolgenden Frames von reinem Blau (#00ff00) zu reinem Rot (#ff0000) ändert, in beiden Frames als reines Blau wiederhergestellt werden.
    • So wie man für Fotos kein PNG verwendet, wird man für tatsächlich gefilmtes Material wohl keinen verlustfreien Videocodec nutzen.
      Verlustfreies Video passt viel besser zu digitalen Inhalten wie Bildschirmaufnahmen. Auch die Annahme, dass sich zwischen aufeinanderfolgenden Frames nur wenige Pixel ändern, ist dort plausibler.
    • Vielleicht ist das kein großes Problem, weil normale Leute kein Raw verwenden. Smartphones und Kameras speichern ohnehin in Dateien wie MP4 oder AV1.
      Solange man es nicht ausdrücklich aktiviert und Dateigröße sowie Verarbeitungsaufwand in Kauf nimmt, weiß man vielleicht nicht einmal, dass es so etwas wie Original- oder Rohdaten noch gibt.
      So hatte ich vorher noch nie darüber nachgedacht.
    • In der aktuellen Form dürfte das Verfahren sehr gut für Animationen geeignet sein.
    • Die faule Methode wäre, ein 8K-Video herunterzuladen und auf etwa 720p herunterzusampeln.
      Oder man kauft eine Kamera und nimmt selbst originales 8K-Material von Alltagsszenen auf.
  • Laut Grafik [1] ist dieses neue Kompressionsverfahren nicht einfach immer strikt schlechter als die Verwendung von GZIP?
    [1] https://github.com/ross39/new_bloom_filter_repo/blob/main/co...

    • In der Grafik steht es nicht, aber das Bloom-Filter-Verfahren könnte zumindest schneller sein als gzip. Allerdings kann ich auch anderswo keine Performance-Metriken finden.
  • „Zentrale Erkenntnis: Wenn die Dichte der 1en in einem Binärstring gering ist, insbesondere unter p* ≈ 0,32453, ist es effizienter, nur die Positionen der 1en zu codieren, als den Rohstring zu speichern.“
    Ein großer Teil dessen, was JPEG/MPEG tun, besteht darin, das Problem so umzuordnen, dass lange Folgen von 0en entstehen können. Die Art, wie DCT-Blöcke passend zu den Positionen der AC/DC-Komponenten gescannt werden, könnte einer der innovativsten Teile vieler Video- und Bildkompressionsverfahren sein.

    • Dieses Verfahren ist für Videokompression in der Praxis ziemlich schlecht. Denn es verwirft aktiv die Lokalität von Pixeländerungen, die in normalen Videos vorhanden ist.
      Anders gesagt: An dieser Technik ist nichts speziell auf Videoframes zugeschnitten. Dieselbe Idee könnte man auch verwenden, um die Differenz zwischen zwei Bitfolgen gleicher Länge zu komprimieren.
      Trotzdem ist es unwahrscheinlich, dass dieses Problem besser abschneidet als bestehende Kompressionsverfahren, etwa zwei Blöcke aneinanderzuhängen und mit gzip zu komprimieren. Damit Kompression funktioniert, muss die Eingabeverteilung – hier die Menge unterschiedlicher Bitpositionen – sehr vorhersehbar und nicht zufällig sein; wenn man die Daten durch eine Hashfunktion schickt, geht diese Eigenschaft verloren. Insbesondere ist es das Ziel kryptografisch starker Hashes, ihre Ausgabe von Zufall ununterscheidbar zu machen.
    • Ich glaube, diese Erklärung stimmt nicht.
      Was DCT und die Umwandlung der Farbdarstellung tun, ist, feine Details in hohe Frequenzen und wesentliche Details in niedrige Frequenzen zu überführen. Danach lassen sich Bildqualität und Kompressionsrate darauf reduzieren, wie viel von der Hochfrequenzdarstellung man verwirft.
      Darüber hinaus verwendet JPEG Huffman-Tabellen, um die Bildgröße weiter zu reduzieren.
      Soweit ich weiß, macht es nichts Spezielles, um lange Folgen von 0en zu reduzieren. Deshalb hilft es auch nicht besonders, 0en in eine Reihe zu bringen.
  • Diese Zeile verwirrt mich: https://github.com/ross39/new_bloom_filter_repo/blob/4798d90...
    Dadurch wird die Kompression verlustbehaftet, und zum Beispiel dürfte ein Übergang von #ffffff zu #fffffa verworfen werden. Auch die Zeile direkt darüber, in der der Mittelwert der Pixeldaten genommen wird, dürfte unabhängig vom Schwellwert einen Übergang von #ff0000 zu #00ff00 verwerfen.
    Vielleicht verstehe ich die Rolle dieser Codezeile falsch. Was in der Ergebnismaske zu 0 wird, scheint nicht im Bloom Filter codiert zu werden.

  • Die Berechnung der Kompressionsrate ist beschrieben, aber ich frage mich, ob es auch Beispiele für Worst-Case-, Durchschnitts- und Best-Case-Kompressionsraten gibt.
    Edit: Ich habe gesehen, dass im Repository ein Bild liegt. Es in das README aufzunehmen, wäre hilfreich.

    • Ich bin der Autor. Das Repository ist zwar ein komplettes Chaos, aber wenn du bereit bist, dich durch den Code zu wühlen, gibt es darin Code zum Erzeugen von Diagrammen usw.
      Ich plane, mit vielen sauberen Tests deutlich konkreter zu werden. Im Moment ist es noch eher ein sehr unordentliches Work in Progress.
  • Ich bin der Autor. Ich habe viel gutes Feedback bekommen und mich entschieden, mich vorerst auf strengere Tests mit Originalvideos und verrauschten Videos zu konzentrieren. Das Repository werde ich weiterhin häufig aktualisieren.
    Es ist noch sehr früh, aber bei Tests mit Originalvideos gab es mit einigen Hinweisen ziemlich gute Ergebnisse: Kompressionsrate 4,8 %, also 95,2 % Größenreduktion, Kompressionsgeschwindigkeit 8,29 fps, Dekompressionsgeschwindigkeit 9,16 fps, Keyframes werden nur für 4 % der Frames benötigt, und die Ausgabe ist perzeptuell verlustfrei (PSNR 31,10 dB).
    Im Vergleich zu Standard-Codecs: Rational Bloom Filter 4,8 %, JPEG2000 verlustfrei 3,7 %, FFV1 verlustfrei 36,5 %, H.265/HEVC verlustbehaftet 9,2 %, H.264 verlustbehaftet 0,3 %.
    Es gibt auch aktuelle Grenzen und künftige Arbeiten. Die Kompressionsergebnisse sind vielversprechend, aber bei der Verarbeitung der Farbkanäle ist es noch nicht wirklich verlustfrei. Die aktuelle Implementierung hat Schwierigkeiten bei der Farbraumkonvertierung von YUV nach BGR, und durch die Präzision der Farbraumkonvertierung entstehen kleine Rundungsfehler, sodass bei den Pixelwerten im Mittel eine Abweichung von etwa 4,7 bleibt.
    Außerdem verarbeitet die aktuelle Implementierung die Farbkanäle nach der Konvertierung im BGR-Format, was zusätzlichen Präzisionsverlust verursacht.
    Als Nächstes plane ich, YUV direkt ohne BGR-Konvertierung zu verarbeiten, Farbdaten bitgenau zu behandeln, die Bloom-Filter-Parameter an die Chroma-Subsampling-Muster anzupassen und ein eigenes System zu bauen, das jeden Farbkanal unabhängig validiert.
    Ich möchte mathematisch beweisen, dass es verlustfrei ist, aber bis dahin ist es noch ein weiter Weg. Ich werde diese Idee der verlustfreien Kompression weiter verfolgen, und ich habe auch einige Ideen, Rational Bloom Filter in anderen Bereichen einzusetzen.

  • Codecs wie H.264 können ebenfalls in einem wirklich verlustfreien Modus laufen. Es benutzt nur fast niemand so.

    • Ich habe das einmal sogar mit Hardwarebeschleunigung über NVENC hinbekommen. Die Wiedergabe war allerdings schwierig; ffplay funktionierte, anderes nicht.
  • Ein nettes Konzept, aber wenn man einen spärlich besetzten Binärstring hat, stehen die Chancen gut, dass traditionelle Methoden besser sind.

  • Dem Repository ist schwer zu folgen, aber die Kompressionsrate scheint danach berechnet zu werden, wie viele Pixeldifferenzen verworfen werden konnten.
    Interessant ist es, aber der wichtigere Vergleich wäre die durchschnittliche Bytegröße jedes Frames in einem komprimierten YouTube-Video. Ohne diesen Vergleich lässt sich schwer beurteilen, ob es gegenüber heutigen Verfahren eine Verbesserung ist.
    Wenn der Algorithmus verlustbehaftet ist, also kleine Differenzen auf 0 drückt, dann ist er nicht verlustfrei und sollte wohl mit anderen verlustbehafteten Algorithmen verglichen werden.