Aller au contenu principal

Comparer des Images avec la Vision API

Mis à jour le 29 juillet 2026

L’analyse comparative visuelle

La comparaison d’images est un cas d’usage puissant qui exploite la capacité multi-images vue en leçon 6. La question n’est plus « que montre cette image ? » mais « qu’est-ce qui a changé ? » — et c’est une opération qu’un modèle sémantique traite tout autrement qu’un comparateur de pixels. Là où une différence de pixels signale une divergence sans la qualifier, le modèle sait dire qu’une étiquette a été déplacée de deux millimètres et qu’un logo a disparu, puis juger lequel des deux compte.

Contrôle qualité, suivi d’évolution, détection de régressions visuelles : cette leçon montre comment structurer des prompts de comparaison et exploiter les résultats.

Comparaison avant/après

Le cas le plus courant consiste à vérifier ce qui a changé entre deux états. Le message système fixe la méthode de comparaison, le message utilisateur nomme les images :

from mistralai import Mistral
import os

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {
            "role": "system",
            "content": """Vous êtes un expert en analyse comparative d'images. Quand on vous présente deux images :
1. Décrivez brièvement chaque image
2. Listez les différences identifiées (avec emplacement)
3. Évaluez la significativité de chaque différence (mineure/majeure)
4. Donnez un score de similarité global (0-100%)"""
        },
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Image AVANT (référence) :"},
                {"type": "image_url", "image_url": "https://exemple.com/avant.jpg"},
                {"type": "text", "text": "Image APRÈS (état actuel) :"},
                {"type": "image_url", "image_url": "https://exemple.com/apres.jpg"},
                {"type": "text", "text": "Identifiez toutes les différences entre ces deux images."}
            ]
        }
    ]
)

print(response.choices[0].message.content)

L’intercalation de texte (« Image AVANT », « Image APRÈS ») aide le modèle à identifier le rôle de chaque image. La troisième étape du prompt système est celle qui rend le rapport exploitable : sans hiérarchisation, vous recevez une liste où un changement d’ombre pèse autant qu’une pièce manquante.

Contrôle qualité produit

En sortie de chaîne, ce rapport doit être lu par un programme, pas par un humain. On combine donc la comparaison avec le mode JSON de la leçon 9 : le modèle rend un verdict, un score et une liste de défauts qualifiés, que le code exploite immédiatement.

import base64
import json

def encoder_image(chemin):
    with open(chemin, "rb") as f:
        b64 = base64.standard_b64encode(f.read()).decode("utf-8")
    return f"data:image/jpeg;base64,{b64}"

def controle_qualite(image_reference, image_echantillon):
    """Compare un échantillon à sa référence et détecte les défauts."""
    response = client.chat.complete(
        model="mistral-large-latest",
        response_format={"type": "json_object"},
        messages=[
            {
                "role": "system",
                "content": "Vous êtes un inspecteur qualité. Comparez l'échantillon à la référence et retournez un rapport JSON."
            },
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": "Référence (produit conforme) :"},
                    {"type": "image_url", "image_url": encoder_image(image_reference)},
                    {"type": "text", "text": "Échantillon à inspecter :"},
                    {"type": "image_url", "image_url": encoder_image(image_echantillon)},
                    {
                        "type": "text",
                        "text": """Comparez et retournez :
{
  "conforme": true/false,
  "score_conformite": 0-100,
  "defauts": [
    {"description": "...", "severite": "mineure/majeure/critique", "localisation": "..."}
  ],
  "recommandation": "accepter/revoir/rejeter"
}"""
                    }
                ]
            }
        ]
    )

    return json.loads(response.choices[0].message.content)

# Utilisation
resultat = controle_qualite("reference/produit-ok.jpg", "lot-42/echantillon-7.jpg")

if resultat["conforme"]:
    print(f"CONFORME - Score : {resultat['score_conformite']}%")
else:
    print(f"NON CONFORME - {len(resultat['defauts'])} défaut(s) détecté(s)")
    for defaut in resultat["defauts"]:
        print(f"  - [{defaut['severite']}] {defaut['description']}")

Le champ recommandation est plus intéressant qu’il n’y paraît : en distinguant « revoir » de « rejeter », il réserve l’intervention humaine aux cas ambigus au lieu de l’imposer partout ou nulle part.

Suivi d’évolution dans le temps

Une série chronologique — chantier, croissance de culture, dégradation d’ouvrage — se traite comme une comparaison étendue, à condition d’étiqueter chaque image avec sa date. Le modèle dispose alors de l’axe temporel et peut qualifier un rythme, pas seulement un écart.

def analyser_evolution(images_chronologiques, contexte=""):
    """Analyse l'évolution visible sur une série d'images ordonnées."""
    content = [
        {
            "type": "text",
            "text": f"Voici {len(images_chronologiques)} images prises à des moments différents, dans l'ordre chronologique. {contexte}"
        }
    ]

    for i, (date, chemin) in enumerate(images_chronologiques):
        content.append({"type": "text", "text": f"Image {i+1} ({date}) :"})
        content.append({"type": "image_url", "image_url": encoder_image(chemin)})

    content.append({
        "type": "text",
        "text": "Décrivez l'évolution observée entre chaque étape. Identifiez les changements majeurs et la tendance générale."
    })

    response = client.chat.complete(
        model="mistral-large-latest",
        messages=[{"role": "user", "content": content}]
    )

    return response.choices[0].message.content

# Suivi d'un chantier
images = [
    ("2025-01", "chantier/jan-2025.jpg"),
    ("2025-06", "chantier/jun-2025.jpg"),
    ("2026-01", "chantier/jan-2026.jpg"),
]

evolution = analyser_evolution(images, contexte="Suivi d'un chantier de construction.")
print(evolution)

La question finale n’est ajoutée qu’après toutes les images, une fois le dossier complet posé.

Comparer des interfaces utilisateur

Le développement web offre un terrain immédiat : confronter la maquette validée au rendu réellement produit. Là où un test de régression pixel échoue sur un décalage d’un pixel sans importance, le modèle qualifie l’impact de chaque écart.

def comparer_interfaces(screenshot_attendu, screenshot_reel):
    """Compare deux screenshots d'interface pour détecter les régressions visuelles."""
    response = client.chat.complete(
        model="mistral-large-latest",
        response_format={"type": "json_object"},
        messages=[
            {
                "role": "system",
                "content": "Vous êtes un testeur QA spécialisé en tests visuels d'interfaces web."
            },
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": "Design attendu (maquette) :"},
                    {"type": "image_url", "image_url": encoder_image(screenshot_attendu)},
                    {"type": "text", "text": "Rendu actuel (screenshot) :"},
                    {"type": "image_url", "image_url": encoder_image(screenshot_reel)},
                    {
                        "type": "text",
                        "text": """Comparez et retournez :
{
  "pixel_perfect": true/false,
  "differences": [
    {"element": "...", "attendu": "...", "reel": "...", "impact": "mineur/moyen/majeur"}
  ],
  "score_fidelite": 0-100,
  "verdict": "conforme/ajustements_mineurs/regression"
}"""
                    }
                ]
            }
        ]
    )

    return json.loads(response.choices[0].message.content)

Branché sur votre chaîne d’intégration continue, ce contrôle ne bloque la livraison que sur un verdict regression.

Bonnes pratiques de comparaison

Ces exemples partagent quelques principes qu’il vaut la peine d’expliciter. Nommez toujours vos images par un label intercalé — « Référence », « Échantillon », « Avant », « Après » — car sans cela le modèle attribue les rôles au hasard de l’ordre. Veillez à la comparabilité des prises de vue : à angle et éclairage différents, le modèle signalera des écarts qui ne tiennent qu’aux conditions de photo. Utilisez Mistral Large 3, car la comparaison mobilise un raisonnement fin que les modèles plus petits ne maîtrisent pas toujours. Limitez-vous à deux ou trois images par appel, au-delà la précision comparative se dilue. Et demandez systématiquement un format structuré, avec score, différences listées et verdict, si le résultat doit être traité automatiquement.

Points clés à retenir

  • La comparaison d’images exploite la capacité multi-images de l’API
  • Intercalez du texte explicatif entre les images pour clarifier leur rôle
  • Le mode JSON (response_format) est idéal pour les rapports de comparaison automatisés
  • Les cas d’usage principaux : contrôle qualité, suivi de chantier, QA visuel, avant/après
  • Utilisez toujours Mistral Large 3 pour les tâches de comparaison exigeantes