Notes concernant ACES

Introduction

Terminologie

Des courbes avant de commencer

Srgb_eotf

La courbe ci-dessus représente la relation entre l’intensité du signal électrique (l’intensité des diodes du moniteur) et l’intensité optique (la lumière) généré. Encore une fois, on observe qu’une alimentation de moitié ne renvoie pas la moitié de son intensité, mais beaucoup moins (0.18).

Quand on travaille dans un logiciel qui ne gère pas les espaces colorimétriques (ou qu’on choisit sciemment de ne pas s’en préoccuper) on a donc cette réponse : Les pixels sombres de notre image (ou texture) sont donc affiché pratiquement deux fois plus sombre que leur valeur réelle. Pour compenser ça, on a tendance à instinctivement monter les valeurs sombres. En fait on fait une image sRGB, sRGB étant la réponse de notre moniteur.

C’est la raison pour laquelle cette courbe est également appliquée aux images en entrée des logiciels, afin de rabaisser les valeurs sombres qui ont été augmentées par vous (du fait de la réponse non-linéaire de votre moniteur).

Rrt_srgb_odt

Ceci est la courbe de réponse de ACES sur un moniteur sRGB. Notez comment la valeur de 1.0 est affiché à 0.812… sur l’écran. Ceci permet de laisser un écart entre 0.812… et 1.0 pour afficher les valeurs entre 1.0 et 16.0 (qui ne sont pas affichés sur cette courbe).

Plus d’informations ici.

Rrt_srbg_odt_(srgb_eotf)

Cette courbe est une juxtaposition des deux précédentes. C’est la fameuse courbe filmic (ou S-shaped) supposé diminuer la valeur des hautes lumières pour en rendre le contenu distinguable.

Historiquement, c’est le fonctionnement des pellicules Kodak qui, par la magie de la chimie, atténuait l’impression de la lumière au prorata de sa luminosité. Plus la lumière était intense, moins son impression sur la pellicule était forte, permettant d’afficher une large gamme d’intensité lumineuse en une image.

Display-referred VS Scene-referred

ACES intègre une distinction que les habitués de la prise photo connaissent sûrement :

L’œil a un comportement complexe, mais ce qu’il faut comprendre c’est qu’il est capable de distinguer un écart de contraste (les nuances entre du noir et du blanc) bien plus élevé que ce que les écrans peuvent afficher. Il en est de même, à moindre échelle, pour les caméras capables de représenter des écarts important d’intensités lumineuses.

Sans cette distinction, on appliquerait bêtement la sortie d’une caméra ou d’un rendu sur l’écran, et toute valeur au-dessus de 1 se mettrait immédiatement à brûler. Notez que c’est souvent ce qu’on fait en rendu :

Spec_sRGB

Ce type de brûlure est classique quand on fait du rendu sans prendre en compte cette distinction.

Pourtant, dans la vraie vie, même un spéculaire un peu fort, vous ne le voyez pas blanc brillant. Ceci est dû au fait que vos yeux peuvent en supporter un écart plus important que votre écran. Il faut donc afficher l’image sur votre écran de sorte que les hautes lumières ne soient, en fait, pas si hautes.

En ayant cette distinction en tête, on peut appliquer, sur les valeurs des pixels de notre image (qui est en scene-reffered donc), une courbe (ayant une allure logarithmique) venant compenser les hautes lumières avant l’affichage :

Spec_sRGB_aces

On parle parfois d’appliquer une réponse, car on vient interpréter les valeurs brutes (d’une caméra ou d’un rendu, bref, d’une scène) en valeurs affichables.

La lumière générale en prend un coup : Une valeur de 1, devient 0.812…, mais entre 0.812… et 1.0, vous avez, dans le cas de ACES, des valeurs d’intensité de 1.0 à 16.0. Un peu comme ce que ferait votre œil en fait.

Convertir une séquence d’image EXR ACEScg en MP4

Il y a plusieurs façons de sortir un MP4 depuis une séquence d’image EXR ACEScg.

Passer par une séquence d’image 8 bits

Cette approche consiste à estimer que ffmpeg n’est pas très flexible et lui donner toujours le même type d’entrée avec le format adéquat ; un format simple. On a donc :

EXR ACEScg -> PNG/Tiff sRGB -> ffmpeg

Cette approche simplifie la gestion de la commande ffmpeg qui peut se concentrer sur des problématiques d’exports en s’évitant une manipulation des video filter.

Cela peut se faire par l’outil ocioconvert :

ocioconvert --ch 0, 1, 2 input.exr 'ACES - ACEScg' output.png 'Output - sRGB'

Ou par Nuke.

Passer par la gestion des LUTs de ffmpeg

ffmpeg peut gérer certains formats de LUTs dans les video filter.

Cette approche a le mérite d’éviter une étape intermédiaire, mais complexifie la commande ffmpeg.

Peu de formats de LUTs gèrent correctement les valeurs flottantes et au-dessus de 1 (pour rappel, ACES va de 0 à 16).

D’après mes recherches, seul les LUTs cineSpace (.csp) rassemblent les propriétés suivantes :

Au même titre que ocioconvert, ociobakelut est un utilitaire de la suite OpenColorIO. Il permet, entre autres, de générer des LUTs de transformation :

ociobakelut --inputspace 'ACES - ACEScg' --outputspace 'Output - sRGB' --format cinespace acescg_to_srgb_cinespace.csp

Plus d’informations d’information avec ociobakelut --help.

Une fois en possession de cette LUT, il faut l’appliquer à l’entrée de la vidéo :

ffmpeg -r 24 -i input.exr -vf lut3d='acescg_to_srgb_cinespace.csp' output.mp4

Note, comme toute commande simple ffmpeg, il est rare que celle-ci soit suffisante.

Le MP4 généré précédemment est fait pour être utilisé avec une fonction de conversion YUV Rec 601.

Dans Nuke, la valeur par défaut du paramètre YCrCb matrix n’est pas claire (Rec 601 ou Rec 709). Si vous devez générer un MP4 lisible avec une conversion Rec 709, il vous faut passer par une conversion de couleur, via colormatrix, comme suit :

ffmpeg -r 24 -i input.exr -vf lut3d=acescg_to_srgb_cinespace.csp,colormatrix=bt470bg:bt709 output.mp4

Le MP4 ainsi généré correspondra aux valeurs des EXR ACEScg quand il est importé dans Nuke avec le paramètre YCrCb matrix à Rec 709.

Exporter une image sRGB (PNG ou JPEG) depuis Houdini

La gestion d’OpenColorIO dans Houdini n’est pas très fine et concerne surtout les viewers (Render et Composite). L’export d’images sRGB reste problématique.

Ainsi, la case « Convert to Image's File Format Colorspace » d’une ROP File Output ne semble pas fonctionner correctement.

Comme proposé ici, l’astuce consiste à appliquer la transformation manuellement. Pour cela, dans votre Image Network, il faut créer un nœud VOP (VEX/VOP COP2 Generator) :

Houdini Image Network VEX/VOP COP2 Generator création

À l’intérieur, il faut créer un ocio_transform (dans Convert/OCIO Transform) :

Houdini Image Network VOP network

Ce dernier doit convertir l’espace vos données ACEScg en sRGB d’affichage :

Houdini Image Network OCIO Transform

En sortie, les valeurs sont donc déjà converties et prêtes à être écrite dans un fichier. Il est donc inutile d’appliquer une quelconque correction ou LUT supplémentaire.

Créez un ROP File Output :

Houdini Image Network ROP File Output création

Houdini Image Network ROP Output

Bien entendu, utilisez l’extension d’un format de fichier utilisant du sRGB (PNG, JPEG).

Le graph final ressemble à ça :

Houdini Image Network ACEScg to sRGB graph

Vous pouvez maintenant exécuter votre nœud de ROP et utiliser vos images.

Dernière mise à jour : mer. 09 février 2022