5.19. Corrections tonales¶
Les corrections tonales modifient la répartition de la luminosité et de la couleur dans une image capturée – les ajustements qu’une application applique lorsqu’une trame est trop sombre, trop claire, trop plate ou orientée vers la mauvaise couleur.
Ces corrections appartiennent à deux familles : les ajustements de luminosité et de contraste qui redistribuent la luminosité, et les ajustements de couleur qui modifient la couleur perçue par chaque pixel. Toutes deux ont leurs équivalents dans l”ISP du capteur, qui corrige chaque trame à son entrée ; les méthodes présentées ici s’appliquent à une Image déjà capturée, après coup, pour les cas où la trame nécessite davantage de correction que ce que l’ISP a fourni.
5.19.1. Égalisation d’histogramme¶
L’opération d’étirement de contraste la plus simple est l”égalisation d’histogramme. L’idée consiste à remapper les valeurs des pixels afin que l’histogramme de sortie soit aussi plat que possible – chaque valeur apparaissant à peu près aussi souvent. L’effet visuel est qu’une image à faible contraste (dont l’histogramme est concentré dans une bande étroite) devient une image à fort contraste dont les pixels couvrent toute la plage 0 – 255.
histeq() effectue l’égalisation :
img.histeq()
Le mécanisme est direct. La fonction de répartition cumulative (CDF) de l’histogramme de la source est calculée ; chaque valeur de pixel en entrée est mappée à sa position dans la CDF, mise à l’échelle de la plage de sortie. Là où les pixels étaient déjà répartis uniformément, le mappage est proche de l’identité ; là où les pixels étaient accumulés à une même luminosité, le mappage les étale en répartissant cette luminosité sur une plage plus large de valeurs de sortie.
Le résultat est spectaculaire sur les scènes à faible contraste – la différence entre une photographie d’intérieur sombre et la même photographie après histeq est souvent celle entre « illisible » et « parfaitement lisible ». Le compromis est que l’opération amplifie tout, y compris le bruit du capteur. Sur une scène présentant de réels détails à faible contraste à récupérer, histeq est la bonne réponse ; sur une scène propre et bien exposée qui n’en a tout simplement pas besoin, histeq introduit du bruit visible.
5.19.2. CLAHE : égalisation adaptative¶
L’égalisation d’histogramme est globale : elle utilise une seule CDF calculée à partir de l’image entière et l’applique partout. Cela fonctionne sur les images dont la plage de luminosité est à peu près uniforme, mais échoue sur les scènes comportant des régions sombres et claires localisées – la CDF est tirée vers le côté qui possède le plus de pixels, et le côté opposé est surcorrigé.
La variante adaptative est l”égalisation adaptative d’histogramme à contraste limité (Contrast Limited Adaptive Histogram Equalisation), couramment appelée CLAHE. Au lieu d’une seule CDF globale, CLAHE calcule une CDF distincte pour chaque petite tuile de l’image, égalise chaque tuile par rapport à sa propre CDF, et fond ensemble les bords des tuiles. Le résultat est que les ajustements de luminosité se produisent localement – le coin ombragé obtient sa propre égalisation sans que le coin clair ne le tire dans la mauvaise direction.
L’option adaptive=True fait passer histeq() en mode CLAHE :
img.histeq(adaptive=True, clip_limit=10)
Le paramètre clip_limit est la partie de CLAHE à laquelle le terme « contraste limité » du nom fait référence. L’égalisation locale peut suramplifier le bruit dans les régions plates où la CDF possède très peu de valeurs distinctes ; la limite d’écrêtage plafonne l’agressivité avec laquelle un même intervalle peut être redistribué, ce qui empêche l’amplification du bruit tout en permettant l’étirement de contraste là où il importe. Une valeur autour de 10 constitue un point de départ raisonnable ; des valeurs plus élevées permettent à CLAHE de travailler davantage au prix d’un bruit plus visible, des valeurs plus faibles le rendent plus doux.
CLAHE est plus coûteux que l’histeq global, mais produit des résultats plus propres sur les scènes où la luminosité est répartie de manière inégale – c’est-à-dire la plupart des scènes du monde réel.
5.19.3. Gamma, contraste et luminosité¶
L’égalisation d’histogramme est la manière pilotée par les données de remapper la luminosité. La manière indépendante des données consiste à appliquer une courbe choisie, paramétrée par quelques réglages faciles à ajuster. gamma() en propose trois :
img.gamma(gamma=1.0, contrast=1.0, brightness=0.0)
Chaque paramètre applique une transformation spécifique à chaque pixel :
gamma fait passer la valeur de chaque pixel par la fonction puissance output = input ** (1 / gamma). La signification standard : les valeurs supérieures à 1.0 éclaircissent l’image et relèvent les tons moyens (la correction classique du « gamma du moniteur ») ; les valeurs inférieures à 1.0 l”assombrissent. Le paramètre est non linéaire – il préserve les points noir et blanc et ne remodèle que la distribution intermédiaire, ce qui est le bon comportement lorsque l’objectif est de récupérer des détails dans les zones d’ombre ou de hautes lumières sans écraser les extrêmes existants.
contrast fait passer chaque pixel par une multiplication directe autour du point gris moyen. Les valeurs supérieures à 1.0 augmentent le contraste (le sombre devient plus sombre, le clair devient plus clair, le gris moyen reste identique) ; les valeurs inférieures à 1.0 réduisent le contraste.
brightness ajoute une constante à chaque valeur de pixel. Les valeurs positives éclaircissent, les valeurs négatives assombrissent. Le décalage est uniforme – rien n’est préservé – ce qui correspond rarement à ce qu’une application souhaite à lui seul, mais se combine bien avec un passage de contraste pour recentrer le résultat.
Les trois paramètres se composent : un seul appel à gamma() peut appliquer une courbe gamma, puis une multiplication de contraste, puis un décalage de luminosité, le tout en un seul passage. L’ordre est gamma d’abord, puis contraste, puis luminosité, ce qui correspond à l’ordre donnant les résultats les plus intuitifs lorsque les trois sont différents de leur valeur par défaut.
5.19.4. Balance des blancs automatique¶
La famille couleur des corrections tonales commence par la balance des blancs automatique. Le même mécanisme que l’ISP du capteur exécute dans le cadre du pipeline d’imagerie – l’ajustement des gains relatifs sur les canaux rouge, vert et bleu afin qu’une plage de couleur grise moyenne soit perçue comme un gris réel – est également disponible en tant qu’opération post-capture sur une Image terminée :
img.awb()
Le comportement par défaut utilise l’algorithme gray-world : la couleur moyenne de l’image entière est supposée être un gris neutre, et les gains par canal sont ajustés en conséquence. La forme alternative max=True utilise l’algorithme white-patch : les pixels les plus brillants sont supposés être un blanc neutre, et les gains sont ajustés en conséquence. Les deux fonctionnent sur RGB565 et sur du Bayer brut ; aucun ne fonctionne sur les niveaux de gris (où il n’y a pas de couleur à équilibrer) ni sur YUV (où la représentation de la couleur n’est pas celle sur laquelle ces algorithmes opèrent).
Quand recourir à la forme post-capture plutôt qu’à la balance des blancs automatique de l’ISP : lorsque le choix de l’ISP était mal adapté à la scène particulière, lorsque l’application charge depuis le disque des trames de référence capturées dans des conditions différentes, ou lorsque le jugement de la couleur importe suffisamment pour que l’application veuille le réexécuter avec son propre choix d’algorithme.
5.19.5. La matrice de correction des couleurs¶
Lorsque la correction de couleur dont l’image a besoin n’est pas la mise à l’échelle par canal qu’offre la balance des blancs, mais un mélange de canaux plus général, l’opération à laquelle recourir est la matrice de correction des couleurs. La méthode ccm() applique une matrice 3 par 3 (ou 3 par 4 avec décalage) qui multiplie le vecteur (r, g, b) de chaque pixel pour produire un nouveau vecteur (r, g, b) :
img.ccm([[1.1, -0.05, -0.05],
[-0.05, 1.1, -0.05],
[-0.05, -0.05, 1.1]])
La matrice permet à l’application de corriger la diaphonie entre les canaux de couleur – là où la réponse du capteur rouge inclut une partie de la lumière verte, par exemple, la matrice peut soustraire une fraction du canal vert de la sortie rouge pour compenser. Combinée à un décalage par canal, la forme 3 par 4 permet également à l’application de remettre à zéro chaque canal.
Le document sur le pipeline ISP couvre le pourquoi des matrices de correction des couleurs. La forme post-capture sur l”Image est simplement la même opération, appliquée après coup.