4 points par GN⁺ 2025-05-28 | 1 commentaires | Partager sur WhatsApp
  • Rational Bloom Filter Video Compression met en œuvre un workflow de compression de vidéo brute où le résultat restauré doit être bit à bit identique à l’original
  • L’idée centrale consiste à appliquer aux filtres de Bloom un nombre non entier de fonctions de hachage, dans le but théorique d’obtenir un meilleur taux de compression que les approches existantes
  • Le projet cible des raw video content comme Y4M, YUV et HDR, et indique fournir une réduction d’espace de 40 à 50 % sur des vidéos classiques
  • L’implémentation repose sur Python 3.7+ et nécessite des dépendances comme numpy, opencv-python, xxhash, Pillow, scikit-image et pyexr pour le HDR
  • Des benchmarks comparant FFV1, HuffYUV et le mode sans perte de H.264 sont inclus ; avant un usage réel, il faut consulter les résultats et la procédure de reproduction dans results.md

Présentation de Rational Bloom Filter Video Compression

  • Ce projet implémente une méthode de compression vidéo sans perte basée sur un rational Bloom filter
  • Le filtre de Bloom est utilisé comme structure de données probabiliste pour représenter efficacement des données binaires
  • Sa particularité est d’utiliser dans le filtre de Bloom des fonctions de hachage rationnelles, et non entières
  • L’objectif est que le résultat restauré après compression corresponde à l’original de manière bit-exact

Cibles prises en charge et fonctions de compression

  • Le système de compression cible des raw video content comme Y4M, YUV et HDR
  • Les fonctions proposées sont les suivantes
    • une true lossless compression garantissant une restauration strictement identique bit à bit
    • une réduction d’espace de 40 à 50 % sur des contenus vidéo classiques
    • l’encodage et le décodage avec prise en charge du multithreading
    • la prise en charge de plusieurs espaces colorimétriques comme RGB, BGR et YUV
    • la prise en charge des contenus HDR
  • Le traitement HDR comporte une limite : « il reste du travail pour le rendre rapide et réellement exploitable »

Exigences d’installation

  • L’environnement d’exécution est Python 3.7+
  • Les paquets nécessaires sont les suivants
    • numpy
    • opencv-python
    • matplotlib
    • pandas
    • tqdm
    • requests
    • xxhash
    • Pillow
    • scikit-image
    • pyexr : pour la prise en charge du HDR
  • Les dépendances s’installent avec la commande suivante
pip install -r requirements.txt

Utilisation de base

  • Dans le code Python, on importe ImprovedVideoCompressor puis on initialise le compresseur
  • L’exemple de configuration inclut noise_tolerance=10.0, keyframe_interval=30, use_direct_yuv=True, verbose=True
  • compress_video() compresse la vidéo d’entrée en fichier .bfvc
  • decompress_video() restaure un fichier .bfvc
  • verify_lossless() vérifie le caractère sans perte entre les images d’origine et les images restaurées
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']}")

Utilisation en ligne de commande

  • La compression vidéo s’exécute ainsi
python -m improved_video_compressor compress input_video.y4m output.bfvc --max-frames 30
  • Les fichiers YUV bruts se traitent en précisant aussi la largeur, la hauteur et le format
python -m improved_video_compressor process-yuv input.yuv output.bfvc --width 1920 --height 1080 --format YUV444

Benchmarks et éléments de comparaison

  • Le projet inclut un système de benchmark qui compare la compression Rational Bloom Filter à d’autres méthodes de compression sans perte
  • Les éléments de comparaison sont FFV1, HuffYUV et le mode sans perte de H.264
  • La commande pour lancer l’ensemble des benchmarks est la suivante
python benchmark_compression.py
  • Il est aussi possible d’exécuter uniquement certains jeux de données et certaines méthodes
python benchmark_compression.py --datasets y4m --methods bloom ffv1 --max-frames 10
  • Les résultats détaillés des benchmarks et la méthode de reproduction se trouvent dans results.md

Fonctionnement du schéma de compression

  • Le schéma de compression fonctionne selon les étapes suivantes
    • Frame Extraction : extraction des images depuis la vidéo d’entrée
    • Keyframe Selection : les images clés sont stockées sous forme d’images compressées directement avec zlib
    • Bloom Filter Compression : les images intermédiaires sont compressées via une carte des différences avec un rational Bloom filter
    • Lossless Verification : la restauration bit-exact est vérifiée pendant le décodage
  • Le rational Bloom filter utilise un nombre non entier de fonctions de hachage k* afin d’optimiser l’équilibre entre espace et précision
  • L’implémentation utilise de façon déterministe ⌊k*⌋ fonctions de hachage, puis applique une fonction de hachage supplémentaire avec une probabilité de k* - ⌊k*⌋

Organisation des fichiers du projet

  • improved_video_compressor.py : main implementation de l’algorithme de compression
  • verify_true_lossless.py : script de vérification de la restauration sans perte
  • benchmark_compression.py : système de benchmark comparant plusieurs méthodes de compression
  • download_*.py : scripts de téléchargement des jeux de données de test
  • results.md : résultats détaillés des benchmarks et analyse

Licence et citation

  • La licence est la MIT License ; plus de détails sont disponibles dans le fichier LICENSE
  • En cas d’utilisation du code dans un travail de recherche, le README indique d’utiliser la citation au format BibTeX qui y figure

1 commentaires

 
GN⁺ 2025-05-28
Avis de Hacker News
  • J’ai l’impression que le document explique mal une idée pourtant très simple. Si j’ai bien compris, on commence par créer un bitmap où chaque bit est vu comme un pixel de l’image, puis, en passant de la frame 0 à la frame 1, on met à 1 les pixels qui ont changé, et à 0 les autres.
    Ensuite, on hache les offsets des positions à 1 et on les met dans un Bloom filter. Les index correspondants, ainsi qu’une certaine proportion de faux positifs, ressortent alors positifs.
    Puis on interroge le Bloom filter pour trouver tous les index positifs, et on stocke les données brutes des pixels modifiés pour ces pixels, ce qui permet de reconstruire facilement la frame suivante.
    On peut voir ça comme le stockage du delta entre deux frames sous forme de x,y,r,g,b pour tous les pixels modifiés, mais avec une forte compression de la partie x,y, au prix de stocker un peu plus de r,g,b que nécessaire.
    Comme les positions des pixels modifiés entre les frames 0→1 ressemblent souvent à celles qui changeront entre les frames 1→2, il semble aussi possible de compresser davantage en définissant un flag approprié sur la frame suivante et en ne stockant tels quels que les offsets qui diffèrent en plus des précédents.

    • Je me demande quel est le taux de compression réel. Ça me rappelle mes expérimentations avec des ondelettes pour la compression d’images il y a environ 22 ans.
      La transformation inverse partait d’une petite image de pixels, puis la transformait en une image deux fois plus large ou deux fois plus haute en utilisant le même nombre de coefficients, et répétait l’opération.
      Le point clé était que la majeure partie des données était constituée de coefficients, et que la plupart d’entre eux étaient proches de 0, donc pouvaient être ramenés à 0. Le problème devenait alors d’encoder les positions non nulles, avec une structure du type bitmap plus tableau des valeurs non nulles.
      Les algorithmes d’encodage des valeurs non nulles variaient dans leur degré de prudence, mais exploitaient généralement le fait que ces valeurs étaient assez regroupées. C’est exactement l’inverse des fonctions de hachage généralement utilisées dans un Bloom filter.
      Ce type de compression d’image était lent, car la localité était très mauvaise à la fois dans la transformation elle-même et dans la compression des coefficients, et ça donnait l’impression d’une impasse.
    • Si l’on stocke les variations de delta d’une frame à la suivante, les pixels inchangés valent simplement 0. Compresser des suites de 0 est l’une des tâches les plus triviales en compression sans perte, et contrairement à un Bloom filter, il n’y a pas de faux positifs.
      Je peux imaginer qu’un Bloom filter fasse partie d’une stratégie de compression hybride complexe. Dans ce genre de compresseur, plus on a d’outils, mieux c’est, mais je ne pense pas que ça améliore beaucoup les choses en moyenne.
    • Je me demande en quoi un Bloom filter aide par rapport à quelque chose comme une table de hachage.
    • Une grande partie de la compression vidéo consiste à gérer le mouvement. Je me demande comment le cas où, à cause d’un panoramique, le même pixel glisse de deux pixels vers la gauche est traité.
  • Ça semble mieux fonctionner parce que la vidéo d’entrée est déjà une vidéo compressée puis restaurée par YouTube.
    Avec une vidéo source originale, l’hypothèse selon laquelle « la plupart des pixels changent peu, voire pas du tout, entre deux frames successives, ce qui produit une matrice de différences creuse » risque de ne plus tenir.
    Avec un signal très propre, par exemple un capteur peu bruité et une scène lumineuse, ce serait possible, mais dans la plupart des signaux réels, je m’attends à ce que le bruit dépasse 1 LSB, donc qu’au moins environ la moitié des bits de poids faible changent.
    Faire passer une vidéo une fois par un cycle compression/restauration tend à supprimer ce bruit, ce qui produit une vidéo artificiellement statique où cette hypothèse devient valable.

    • À première vue, ça aussi semble ne pas être sans perte : https://github.com/ross39/new_bloom_filter_repo/blob/main/vi...
      Les pixels dont la variation moyenne des valeurs r,g,b est inférieure à 10 ne semblent pas avoir leur différence stockée. Dans ce cas, même si un pixel passe du bleu pur (#00ff00) au rouge pur (#ff0000) entre deux frames successives, les deux frames pourraient être restaurées en bleu pur.
    • De la même façon qu’on n’utilise pas PNG pour les photos, je ne pense pas qu’on utiliserait un codec vidéo sans perte pour des séquences réellement filmées.
      La vidéo sans perte convient beaucoup mieux aux contenus numériques comme l’enregistrement d’écran. L’hypothèse selon laquelle peu de pixels changent entre deux frames successives est aussi plus pertinente dans ce cas.
    • Ce n’est peut-être pas un gros problème, car les gens ordinaires n’utilisent généralement pas le raw. Les téléphones et les appareils photo enregistrent de toute façon dans des fichiers comme MP4 ou AV1.
      À moins de l’activer explicitement et d’assumer la taille des fichiers ainsi que la charge de traitement, ils peuvent même ignorer que la notion d’original ou de données brutes existe encore.
      Je n’y avais jamais pensé de cette manière auparavant.
    • En l’état, cette méthode semble très bien adaptée à l’animation.
    • La méthode paresseuse consiste à télécharger une vidéo 8K et à la downsampler vers quelque chose comme du 720p.
      Sinon, on peut aussi acheter une caméra et filmer soi-même des scènes du quotidien en 8K brut.
  • D’après le graphique [1], ce nouveau mode de compression n’est-il pas tout simplement toujours strictement moins bon que GZIP ?
    [1] https://github.com/ross39/new_bloom_filter_repo/blob/main/co...

    • Ce n’est pas sur le graphique, mais la méthode avec Bloom filter pourrait au moins être plus rapide que gzip. Cela dit, je ne trouve pas non plus de métriques de performance ailleurs.
  • « Point clé : dans une chaîne binaire, si la densité de 1 est faible, en particulier en dessous de p* ≈ 0,32453, il est plus efficace d’encoder uniquement les positions des 1 que de stocker la chaîne brute. »
    Une grande partie de ce que font JPEG/MPEG consiste à réorganiser le problème pour pouvoir créer de longues suites de 0. La manière dont les blocs DCT sont parcourus selon la position des composantes AC/DC est peut-être l’un des aspects les plus innovants de nombreuses techniques de compression vidéo et image.

    • Cette approche est en fait assez mauvaise pour la compression vidéo, car elle jette activement la localité des changements de pixels présente dans les vidéos ordinaires.
      Pour le dire plus favorablement, cette technique n’a rien de spécifique aux images vidéo. On pourrait utiliser la même idée pour compresser la différence entre deux chaînes de bits de même longueur.
      Cela dit, il est peu probable que ce problème fasse mieux que les méthodes de compression existantes, par exemple concaténer deux blocs puis les passer à gzip. Pour que la compression fonctionne, la distribution d’entrée — ici l’ensemble des positions de bits différentes — doit être très prévisible et non aléatoire ; or passer les données dans une fonction de hachage détruit cette propriété. En particulier, le but d’un hachage cryptographiquement fort est de produire une sortie indiscernable de l’aléatoire.
    • Je ne pense pas que cette explication soit correcte.
      Ce que font la DCT et la conversion de représentation des couleurs, c’est transformer les détails fins en hautes fréquences et les détails essentiels en basses fréquences. Ensuite, la qualité d’image et le taux de compression se résument à la quantité de représentation haute fréquence que l’on décide de jeter.
      À part cela, JPEG utilise des tables de Huffman pour réduire encore la taille de l’image.
      À ma connaissance, il ne fait rien de particulier pour réduire de longues suites de 0. Aligner les 0 en rangée n’aide donc pas énormément.
  • Cette ligne me perturbe : https://github.com/ross39/new_bloom_filter_repo/blob/4798d90...
    Avec ça, la compression devient avec pertes, et il me semble par exemple qu’une transition de #ffffff à #fffffa serait supprimée. La ligne juste au-dessus, qui prend la moyenne des données de pixels, semble aussi supprimer une transition de #ff0000 à #00ff00 indépendamment du seuil.
    Je ne sais pas si je comprends mal le rôle de cette ligne de code. Ce qui devient 0 dans le masque résultant ne semble pas être encodé dans le Bloom filter.

  • La méthode de calcul du taux de compression est indiquée, mais je me demande s’il existe aussi des exemples de taux de compression dans le pire cas, en moyenne et dans le meilleur cas.
    Édition : j’ai vu qu’il y avait une image dans le dépôt. Ce serait utile de l’ajouter au README.

    • Je suis l’auteur. Le dépôt est totalement en bazar, mais si vous avez envie de fouiller dans le code, il contient ce qui génère les graphiques, entre autres.
      Je compte faire beaucoup plus de tests sérieux pour rendre tout cela bien plus concret. Pour l’instant, c’est encore un travail en cours très brouillon.
  • Je suis l’auteur. J’ai reçu beaucoup de bons retours et, pour le moment, j’ai décidé de me concentrer sur des tests plus rigoureux avec des vidéos originales et des vidéos bruitées. Je continuerai à mettre le dépôt à jour fréquemment.
    C’est encore très préliminaire, mais les tests sur vidéo originale ont donné des résultats plutôt bons, avec quelques réserves : taux de compression de 4,8 %, soit une réduction de taille de 95,2 %, vitesse de compression de 8,29 fps, vitesse de décompression de 9,16 fps, seulement 4 % des frames nécessaires comme keyframes, et une sortie perceptuellement sans perte (PSNR 31,10 dB).
    Par comparaison avec des codecs standards : Rational Bloom Filter 4,8 %, JPEG2000 sans perte 3,7 %, FFV1 sans perte 36,5 %, H.265/HEVC avec pertes 9,2 %, H.264 avec pertes 0,3 %.
    Il y a aussi des limites actuelles et des travaux à venir. Les résultats de compression sont prometteurs, mais le traitement des canaux de couleur n’est pas encore réellement sans perte. L’implémentation actuelle rencontre des difficultés lors de la conversion d’espace colorimétrique de YUV vers BGR, et la précision de cette conversion introduit de petites erreurs d’arrondi, laissant une différence moyenne d’environ 4,7 sur les valeurs de pixels.
    De plus, l’implémentation actuelle traite les canaux de couleur au format BGR après conversion, ce qui provoque une perte de précision supplémentaire.
    À l’avenir, je prévois de traiter directement le YUV sans conversion BGR, de manipuler les données de couleur avec une exactitude au bit près, d’affiner les paramètres du Bloom filter en fonction des schémas de sous-échantillonnage de la chrominance, et de créer un système dédié pour valider chaque canal de couleur indépendamment.
    J’aimerais prouver mathématiquement le caractère sans perte, mais il reste beaucoup de chemin à parcourir. Je compte continuer à creuser cette idée de compression sans perte, et j’ai aussi quelques idées pour appliquer le Rational Bloom Filter à d’autres domaines.

  • Les codecs comme H.264 peuvent aussi fonctionner en vrai mode sans perte. C’est juste que presque personne ne les utilise ainsi.

    • J’ai déjà réussi à le faire avec accélération matérielle via NVENC. En revanche, la lecture était difficile : ffplay fonctionnait, mais pas le reste.
  • Le concept est mignon, mais si l’on a une chaîne binaire creuse, il y a de fortes chances que les méthodes traditionnelles fassent mieux.

  • Le dépôt est difficile à suivre, mais il semble que le taux de compression soit calculé en regardant combien de différences de pixels ont pu être supprimées.
    C’est intéressant, mais la comparaison la plus importante serait plutôt la taille moyenne en octets de chaque frame dans une vidéo YouTube compressée. Sans cette comparaison, il est difficile de savoir s’il s’agit d’une amélioration par rapport aux méthodes actuelles.
    Si l’algorithme est avec pertes, c’est-à-dire s’il écrase les petites différences à 0, alors ce n’est pas du sans perte et il faudrait plutôt le comparer à d’autres algorithmes avec pertes.