5.30. Mise en correspondance de modèles

Les détecteurs abordés jusqu’ici répondent à des questions portant sur le contenu d’une seule trame : où se trouvent les blobs, où vont les lignes, ce que dit un code imprimé. Une autre catégorie de question compare une image à une autre. Cette région de la trame capturée ressemble-t-elle au motif de référence que j’ai stocké lors de la calibration ? Les méthodes de mise en correspondance répondent à cette question.

L’analyse tonale et statistique a présenté get_similarity() pour la question connexe – à quel point ces deux images de même taille se ressemblent-elles globalement ? – avec le SSIM comme métrique sous-jacente. La question de mise en correspondance restante est celle de la localisation : non pas « à quel point ces deux images se ressemblent » mais « à quel endroit, dans cette image plus grande, ce plus petit motif apparaît-il ? » Le bon outil pour la question de localisation est la mise en correspondance de modèles.

5.30.1. L’appel de base

find_template() recherche le premier endroit où une petite image modèle apparaît à l’intérieur de la trame capturée. L’implémentation utilise la corrélation croisée normalisée (NCC) : le modèle se déplace le long de la trame, le score de correspondance par position est calculé à partir de la corrélation entre les pixels du modèle et les pixels sous-jacents de la trame (normalisée par rapport aux moyennes et variances locales afin que les variations de gain ne trompent pas la correspondance), et la première position dont le score dépasse threshold est renvoyée sous forme de boîte englobante :

template = image.Image("/sdcard/template.bmp", copy_to_fb=False)
template.to_grayscale()

match = img.find_template(template, threshold=0.7,
                           search=image.SEARCH_DS)

if match is not None:
    img.draw_rectangle(match, color=(255, 0, 0))

La méthode ne fonctionne que sur les images en niveaux de gris. Capturez en niveaux de gris (le choix naturel pour toute caméra dépourvue de capteur couleur), ou convertissez sur place via to_grayscale() avant l’appel. Il en va de même pour le modèle chargé depuis le disque : un modèle en couleur est converti avec la même méthode, et le résultat est ce que le module de mise en correspondance attend.

threshold est un nombre flottant compris entre 0.0 et 1.0. Une valeur de 1.0 exige une correspondance parfaite, pixel par pixel (ce qui n’arrive jamais avec de vraies images capturées), 0.0 accepte n’importe quoi, et les valeurs comprises entre 0.6 et 0.8 couvrent le cas courant où le modèle a été capturé sous un éclairage similaire et où la scène n’a pas changé de façon spectaculaire. Augmentez le seuil pour supprimer les faux positifs ; abaissez-le pour accepter des correspondances plus bruitées au prix d’un plus grand nombre de détections parasites.

5.30.2. Stratégie de recherche

search choisit entre deux stratégies. image.SEARCH_EX est la recherche exhaustive : le modèle parcourt chaque position espacée de step pixels dans la trame et renvoie la première correspondance au-dessus du seuil. image.SEARCH_DS est la recherche en losange : le module de mise en correspondance échantillonne d’abord grossièrement, puis affine autour du meilleur score, ce qui est considérablement plus rapide mais peut manquer une vraie correspondance si la passe grossière se trouve atterrir près d’un maximum local qui bat le maximum global. Pour un pipeline en temps réel où le modèle est bien défini et peu susceptible d’être confondu, SEARCH_DS est la valeur par défaut appropriée ; pour une calibration ponctuelle où le coût d’une correspondance manquée est supérieur au coût d’un balayage plus lent, SEARCH_EX est plus sûr.

step contrôle le saut de pixels pendant la passe exhaustive (la recherche en losange gère son propre pas). Des valeurs de step plus grandes accélèrent le balayage au prix de la précision sous-pixellique. roi restreint la recherche à une région de la trame, ce qui réduit à la fois ce que le module de mise en correspondance considère et la charge de travail.

La valeur renvoyée est un tuple de boîte englobante (x, y, w, h) identifiant la meilleure correspondance, ou None si aucune position n’a dépassé le seuil. La boîte englobante s’insère directement dans draw_rectangle() ou crop() pour l’étape de traitement suivante.

5.30.3. Le piège de l’échelle et de la rotation

L’écueil classique de la mise en correspondance de modèles est la sensibilité à l’échelle et à la rotation. Le module de mise en correspondance compare le modèle à la trame pixel par pixel ; un modèle capturé à une certaine distance ne correspond pas au même objet capturé à une distance différente, et un modèle capturé de face ne correspond pas au même objet vu de biais. Le seuil descend discrètement en dessous du niveau de correspondance même lorsque l’objet est clairement visible à l’œil humain, et la méthode renvoie None.

Quelques solutions de contournement existent pour les cas simples. L’application peut capturer plusieurs modèles à différentes échelles et exécuter find_template() pour chacun à tour de rôle, en acceptant le premier qui dépasse le seuil ; le coût augmente avec le nombre de modèles. L’application peut prétraiter la trame avec rotation_corr() ou la transformation polaire (Transformations géométriques) afin de supprimer la rotation problématique avant l’exécution de la correspondance ; le modèle mis en correspondance doit toujours correspondre à la géométrie corrigée.

Un idiome utile pour les pipelines d’inspection qualité associe le module de mise en correspondance de modèles au calcul de similarité présenté par l’analyse tonale et statistique : find_template() localise la pièce dans la trame capturée et la boîte englobante renvoyée est extraite par recadrage puis transmise à get_similarity() pour comparaison avec le motif de référence. L’étape de mise en correspondance de modèle décide où se trouve la pièce ; l’étape de calcul de similarité décide si la pièce est acceptable. Les deux étapes s’exécutent à chaque trame, le seuil sur mean constitue la barrière de réussite/échec, et la boîte englobante correspondante redessinée dans la trame est l’aperçu IDE que l’opérateur surveille.