5.12. Seuillage binaire

De nombreux pipelines de traitement d’image se résument à une question posée sur chaque pixel : cette luminosité se situe-t-elle dans la plage qui signifie « avant-plan » ? Cette couleur est-elle suffisamment proche du rouge pour être le marqueur que l’application suit ? Ce pixel fait-il partie de l’ensemble candidat que l’étape suivante du pipeline doit examiner ? Le seuillage est l’opération qui transforme ces questions en une réponse binaire à chaque position – activée si le pixel correspond, désactivée sinon – et réduit l’image entière à un masque sur lequel le reste du pipeline peut travailler.

5.12.1. La méthode binary

La méthode binary() exécute cette classification sur chaque pixel en un seul appel. Elle prend une liste de plages de seuil – les conditions qu’un pixel peut satisfaire pour compter comme « activé » – et réécrit l’image de sorte que chaque pixel correspondant à au moins une des plages soit réglé à la valeur maximale du format, et chaque pixel ne correspondant à aucune soit mis à zéro. Le résultat est le masque binaire que le reste du pipeline peut utiliser directement.

Dans sa forme la plus simple, la liste de seuils contient une seule plage et l’appel renvoie un masque des pixels situés dans cette plage :

img.binary([(120, 255)])

C’est la forme en liste qui rend binary puissant. Un pipeline qui souhaite suivre deux marqueurs colorés, ou une plage de luminosité plus un pic de saturation isolé, passe les deux plages dans la même liste et obtient un masque de sortie unique couvrant toutes les correspondances.

Un gradient horizontal en niveaux de gris en haut, intitulé « entrée -- valeurs de pixels de 0 à 255 ». En dessous, une plage de seuil inclusive de lo à hi est marquée par des crochets le long du gradient, englobant la plage des valeurs de luminosité comptées comme correspondances. Une barre de sortie binaire en bas affiche du blanc à l'intérieur de la plage lo-à-hi et du noir à l'extérieur.

Le seuillage transforme une image à valeurs continues en un masque binaire : chaque pixel à l’intérieur de la plage de seuil devient le maximum du format, chaque pixel à l’extérieur devient zéro.

5.12.2. Le tuple en niveaux de gris

Pour une image en niveaux de gris, chaque entrée de la liste de seuils est un tuple à deux éléments (lo, hi) décrivant une plage de luminosité inclusive. Les pixels dont les valeurs sont comprises entre lo et hi (inclus) correspondent ; tout ce qui est en dehors de cette plage ne correspond pas. Les motifs naturels sont simples :

  • (0, 60) correspond aux pixels sombres – de tout ce qui va du noir jusqu’au gris profond.

  • (180, 255) correspond aux pixels clairs – de tout ce qui va du gris clair jusqu’au blanc.

  • (100, 160) correspond aux pixels gris moyens – une bande au milieu de la plage de luminosité.

L’ordre des deux valeurs à l’intérieur d’un tuple n’a pas d’importance ; la méthode les échange en interne si lo est supérieur à hi, de sorte que (60, 0) fonctionne de la même façon que (0, 60).

5.12.3. Le tuple LAB pour la couleur

Pour une image RGB565, chaque entrée est un tuple à six éléments (l_lo, l_hi, a_lo, a_hi, b_lo, b_hi) décrivant une plage inclusive dans l’espace colorimétrique LAB plutôt que directement en rouge, vert et bleu. Les seuils sont L (luminosité), A (axe chromatique vert-rouge) et B (axe chromatique bleu-jaune), chacun comparé à la valeur du pixel dans ce canal.

La raison de passer par LAB plutôt que de seuiller directement le RGB tient à la propriété autour de laquelle l’espace colorimétrique LAB a été conçu : LAB sépare la luminosité de la chromaticité. Deux pixels qui présentent la même couleur mais à des luminosités différentes aboutissent à des valeurs L différentes mais à des valeurs A et B à peu près identiques. Cette séparation permet aux plages de seuil de décrire une couleur par sa position sur les axes A et B et de laisser la plage L grande ouverte pour accepter cette couleur à chaque luminosité, de l’ombre jusqu’aux hautes lumières. Un seuil basé sur le RGB ne peut pas faire cela – tout changement d’éclairage déplace les trois valeurs R, V, B à la fois, et un suiveur construit sur des seuils RGB s’effondre dès qu’un nuage passe devant le soleil.

Le motif pratique : choisir les plages A et B qui décrivent la couleur que l’application suit, et laisser la plage L large – souvent (0, 100) pour accepter toute luminosité – à moins que l’application ne veuille spécifiquement seuiller sur la luminosité en plus de la couleur.

Pour les tuples comportant moins de six valeurs, les composantes manquantes prennent par défaut la plage maximale (aucune contrainte sur cet axe). Un tuple à deux éléments (l_lo, l_hi) dans une liste de seuils RGB565 ne seuille donc que sur la luminosité et correspond à toutes les couleurs.

Note

Une plage L vraiment grande ouverte comporte un piège à son extrémité basse. À mesure que la luminosité tombe vers zéro, toutes les couleurs convergent vers le noir, les valeurs A et B s’effondrant vers zéro et devenant dominées par le bruit – de sorte que les pixels sombres peuvent dériver dans les plages A et B et être suivis comme la couleur cible. Si des régions noires de la scène s’allument comme des correspondances, augmentez l_lo jusqu’à ce qu’elles disparaissent.

5.12.4. Indicateurs

Trois arguments nommés contrôlent la sortie :

  • invert=True inverse le résultat. Chaque pixel qui aurait correspondu devient zéro, et chaque pixel qui aurait été zéro devient la valeur maximale. Utile lorsque la façon naturelle de décrire l’avant-plan est par ce qu’il n’est pas.

  • zero=True change le mode de fonctionnement : les pixels correspondants sont mis à zéro et les pixels non correspondants conservent leurs valeurs d’origine. À utiliser lorsque l’objectif est d”effacer les pixels correspondants de l’image plutôt que de réduire l’image à un masque binaire de ceux-ci.

  • to_bitmap=True renvoie le résultat sous forme d’image BINARY au lieu d’écraser le format existant de la source. Le résultat à un bit par pixel est ce que les arguments de masque ultérieurs acceptent directement, et la conversion économise souvent la pression mémoire qu’imposerait le transport d’un masque au format complet.

Le masque et la ROI suivent la même convention que le reste de la surface : un rectangle roi restreint l’opération à une sous-zone, une image mask la restreint à un motif arbitraire de positions.

5.12.5. Sur place par défaut

Comme les opérations arithmétiques, binary s’exécute sur place par défaut : les pixels de l’image source sont écrasés par la sortie binaire, et les valeurs d’origine ont disparu après l’appel. La forme to_bitmap=True est l’alternative lorsque la source doit être préservée et que la sortie doit être une image BINARY nouvellement allouée. La forme copy=True est également acceptée pour un résultat de même format sur un nouveau tampon.