Les PNG transparents cassent les agrandisseurs IA : le bug du halo sombre
Donne un PNG avec transparence (une photo détourée, un export de sticker) à presque n'importe quel agrandisseur IA et un défaut précis apparaît : un halo sombre qui s'insinue de quelques pixels dans le sujet depuis chaque bord transparent, avec derrière lui un léger anneau clair de dépassement. Il se cache sur les aperçus sombres et saute aux yeux sur les pages blanches. Nous l'avons reproduit sur notre propre pipeline, mesuré sa forme exacte (une tranchée de −94 de luma, large de trois pixels du modèle), remonté jusqu'à l'aller-retour alpha prémultiplié de la plateforme web, et mesuré la correction que nous livrons : un remplissage par diffusion en O(n) qui retire 98 % de l'erreur avant même que le modèle ne tourne.
Chaque chiffre de cette note a été mesuré sur le code du pipeline de production : mêmes modèles, mêmes calculs. Données brutes par image : e3_alpha.json.
1 · D'où vient le noir
Le canvas 2D du web stocke les pixels prémultipliés : non pas (r, g, b, α) mais (rα, gα, bα, α). La composition adore ce format (les opérateurs de Porter-Duff[1] deviennent de simples multiplications-additions), mais il est destructif à exactement un endroit. Relire les pixels revient à diviser la couleur par α :
À α = 0, c'est 0/0, et la réponse de la plateforme[2] est qu'il ne reste rien à récupérer : la couleur a été multipliée par zéro à l'instant où elle a touché le canvas. getImageData renvoie un RVB de (0, 0, 0) sous chaque pixel entièrement transparent. Le champ transparent de ton détourage est silencieusement devenu un lac de noir pur.
Un humain ne voit jamais le lac : l'alpha le cache. Un réseau de super-résolution n'est pas un humain : il consomme trois canaux de RVB et pas d'alpha, si bien qu'il voit une photographie plongée dans du vantablack, et chaque pixel de sortie près de la frontière est calculé à partir d'un champ récepteur qui trempe dans le lac. Le noir ne reste pas en place ; il diffuse vers l'intérieur à travers la pile de convolutions[3].
2 · Mesurer le halo

Une mesure réellement contre-intuitive : nous nous attendions à ce que le modèle hallucine des déchets à l'intérieur de la zone transparente, qu'il « améliore le vide ». Il ne le fait pas. Noir uni en entrée, noir uni en sortie (énergie de gradient 0,1). Le mal n'est pas ce que le modèle invente dans le vide ; c'est ce que le vide fait au sujet à travers la frontière. C'est important, parce que cela signifie que masquer la sortie ne peut pas te sauver : les pixels abîmés sont à l'intérieur de la zone visible, sous α > 0.
3 · La correction : inonder le vide d'une couleur plausible
Si le modèle doit voir du RVB sous α = 0, que ce soit un RVB qui prolonge le sujet. Avant l'inférence, nous exécutons une diffusion alpha : une inondation en largeur d'abord à sources multiples depuis chaque pixel non transparent, où chaque pixel transparent prend la couleur moyenne de ses 4-voisins déjà colorés :
Amorcer la file avec l'anneau de frontière et traiter en FIFO garantit que chaque pixel défilé a au moins un voisin coloré (celui qui l'a enfilé a terminé avant), si bien qu'une seule passe en O(n) colore tout le vide : distance illimitée, trous enclavés compris. Les octets d'alpha ne sont jamais touchés ; les pixels semi-transparents gardent leur propre couleur. Le modèle voit alors un prolongement lisse au lieu d'une falaise, et l'alpha (agrandi séparément) est réappliqué à la sortie. Effet mesuré : l'erreur de la bande de 0–3 px tombe de -62,9 à 1,1 niveau de luma, une réduction de 63×, sans coût d'exécution mesurable.

4 · Ce que cela signifie pour tes images
Si tu utilises ce site : rien ; les PNG transparents empruntent le chemin mesuré ci-dessus dans le pipeline cloud comme dans le moteur de repli du navigateur, puisque les deux partagent la même bibliothèque pure. Si tu construis des outils d'image : considère tout modèle RVB seul comme allergique aux zéros prémultipliés : diffuse avant l'inférence (l'inondation ci-dessus tient en ~30 lignes sans dépendance), ou aplatis sur une couleur unie et accepte le biais de l'aplat. Et si tu diagnostiques un mystérieux bord sombre dans la sortie de l'agrandisseur de quelqu'un, tu connais désormais l'empreinte : une tranchée de quelques pixels de large, un anneau de dépassement derrière elle, et une corrélation parfaite avec la frontière alpha. Les trois chiffres à retenir : −94, 3 px, 63×.
Références
- Porter, T., & Duff, T. (1984). Compositing Digital Images. SIGGRAPH '84, Computer Graphics 18(3), 253–259. (The premultiplied-alpha compositing algebra.) dl.acm.org
- WHATWG HTML Living Standard, the 2D canvas element: premultiplied backing stores and the lossy getImageData round-trip for non-opaque pixels. html.spec.whatwg.org
- Wang, X., Xie, L., Dong, C., & Shan, Y. (2021). Real-ESRGAN: Training Real-World Blind Super-Resolution with Pure Synthetic Data. ICCV Workshops. arXiv:2107.10833. arxiv.org
- Lange, D. (1936). “Migrant Mother” (Destitute pea pickers in California), Farm Security Administration. Public domain, via Wikimedia Commons. commons.wikimedia.org
- ONNX Runtime: the inference engine both our server (CPU) and in-browser (WebGPU/WASM) engines run on. onnxruntime.ai