Strukturierte Daten aus Bildern extrahieren
Auf dieser Seite
Bilder in verwertbare Daten umwandeln
Die vorherige Lektion konzentrierte sich auf die Transkription von Text; diese Lektion geht einen Schritt weiter und erzeugt strukturierte Daten. Das Extrahieren strukturierter Daten bedeutet, den visuellen Inhalt eines Bildes – eine Tabelle, ein Formular, eine Visitenkarte oder ein Etikett – in JSON, CSV oder ein anderes Format zu transformieren, das Ihr Code direkt manipulieren kann, ohne manuelle Prüfung.
Die Anforderungen sind höher. Eine ungenaue Transkription kann einem menschlichen Leser noch helfen, aber das Fehlen eines einzelnen Schlüssels in einer JSON-Antwort kann das Programm, das diese verarbeitet, zum Absturz bringen. In dieser Lektion werden die beiden Garantien behandelt, die Sie für die Implementierung benötigen: den JSON-Modus der API für die syntaktische Gültigkeit und die Schema-Validierung für die geschäftliche Konformität.
Der JSON-Modus der API
Mistral bietet einen response_format-Parameter an, der das Modell zwingt, gültiges JSON zurückzugeben. Ohne diesen Parameter verschwenden Sie Zeit damit, Antworten zu bereinigen, die in Markdown-Blöcke eingewickelt oder mit höflichen Einleitungssätzen versehen sind.
from mistralai.client import Mistral
import os
import json
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
response = client.chat.complete(
model="mistral-large-latest",
response_format={"type": "json_object"},
messages=[
{
"role": "system",
"content": "Geben Sie immer ein gültiges JSON-Objekt mit den aus dem Bild extrahierten Daten zurück."
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "Extrahieren Sie die folgenden Daten aus dieser Visitenkarte als JSON: name, title, company, email, phone, address."
},
{"type": "image_url", "image_url": data_uri_carte}
]
}
]
)
# Das Ergebnis ist direkt parsbar
donnees = json.loads(response.choices[0].message.content)
print(json.dumps(donnees, indent=2, ensure_ascii=False))
Der Aufruf von json.loads läuft ohne besondere Vorsichtsmaßnahmen: response_format={"type": "json_object"} garantiert eine syntaktisch gültige JSON-Ausgabe. Dies garantiert jedoch nicht, welche Schlüssel vorhanden sind. Deshalb müssen Sie das erwartete Format direkt im Prompt beschreiben, wie in den nachfolgenden Beispielen gezeigt.
Eine Tabelle aus einem Bild extrahieren
Aufgenommene Tabellen oder Screenshots sind ein häufiger Anwendungsfall, und hier zahlt sich ein explizites Schema am meisten aus. Ohne klare Anweisungen wird das Modell eine eigene Struktur erfinden, die bei jedem Aufruf variieren kann.
prompt_tableau = """Extrahieren Sie den Inhalt dieser Tabelle als JSON.
Erwartetes Format:
{
"columns": ["Column1", "Column2", ...],
"rows": [
{"Column1": "value", "Column2": "value"},
...
]
}
Lesen Sie alle sichtbaren Zeilen. Wenn eine Zelle leer ist, verwenden Sie null."""
response = client.chat.complete(
model="mistral-large-latest",
response_format={"type": "json_object"},
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt_tableau},
{"type": "image_url", "image_url": encoder_image("captures/tableau-excel.png")}
]
}
]
)
donnees = json.loads(response.choices[0].message.content)
print(f"Spalten: {donnees['columns']}")
print(f"Anzahl der Zeilen: {len(donnees['rows'])}")
Die Anweisung bezüglich leerer Zellen ist kritisch. Ohne sie könnte das Modell Werte verschieben, um Lücken zu füllen, was die Tabelle verzerrt. Die Anzeige der Zeilenanzahl bietet eine sofortige Plausibilitätsprüfung: Wenn das Bild zwölf Zeilen zeigt, aber das Skript acht meldet, ist die Extraktion unvollständig.
Formulare und administrative Dokumente
Ausgefüllte Formulare bringen zwei Herausforderungen mit sich: Handschrift und Kontrollkästchen, die keinen Textwert haben. Ihr Schema muss daher dedizierte Felder für diese enthalten.
prompt_formulaire = """Analysieren Sie dieses ausgefüllte Formular und extrahieren Sie alle Felder und deren Werte.
Erwartetes JSON-Format:
{
"form_type": "...",
"fields": {
"field_name": "entered_value",
...
},
"checked_boxes": ["field1", "field2"],
"signature_present": true/false
}
Wenn ein Feld leer oder unlesbar ist, verwenden Sie null."""
response = client.chat.complete(
model="mistral-large-latest",
response_format={"type": "json_object"},
messages=[
{
"role": "system",
"content": "Sie sind ein präzises Formular-Extraktionswerkzeug. Geben Sie strukturiertes JSON zurück."
},
{
"role": "user",
"content": [
{"type": "text", "text": prompt_formulaire},
{"type": "image_url", "image_url": encoder_image("formulaires/cerfa-12345.jpg")}
]
}
]
)
Extraktion von Produktetikett-Daten
Nahrungsmittel-Etiketten folgen einer Standardstruktur: eine Nährwerttabelle pro 100 g, eine Zutatenliste und Allergene. Sie können das Schema bis auf den Einheitenname definieren, um später keine Vermutungen darüber anstellen zu müssen, ob sich „12” auf Gramm oder Kilokalorien bezog.
prompt_etiquette = """Extrahieren Sie die Nährwertinformationen aus diesem Etikett.
JSON-Format:
{
"product_name": "...",
"net_weight": "...",
"nutrition_per_100g": {
"energy_kcal": ...,
"fat_g": ...,
"saturated_fat_g": ...,
"carbohydrates_g": ...,
"sugars_g": ...,
"protein_g": ...,
"salt_g": ...
},
"ingredients": "...",
"allergens": ["..."]
}"""
response = client.chat.complete(
model="mistral-large-latest",
response_format={"type": "json_object"},
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": prompt_etiquette},
{"type": "image_url", "image_url": encoder_image("produits/etiquette.jpg")}
]
}
]
)
produit = json.loads(response.choices[0].message.content)
Extraktions-Pipeline mit Validierung
In der Produktion reichen syntaktische Garantien nicht aus. Das Modell könnte perfekt gültiges JSON zurückgeben, bei dem email fehlt oder bei dem phone eine ganze Zahl statt eines Strings enthält. Pydantic verwandelt diese Fälle in explizite Ausnahmen bereits im Extraktionsstadium, nicht erst drei Schritte weiter in Ihrer Pipeline.
from pydantic import BaseModel, Field
from typing import Optional
import json
class BusinessCard(BaseModel):
last_name: str
first_name: str
title: Optional[str] = None
company: Optional[str] = None
email: Optional[str] = None
phone: Optional[str] = None
address: Optional[str] = None
website: Optional[str] = None
def extract_business_card(image_path):
"""Extrahieren und validieren Sie Visitenkartendaten."""
response = client.chat.complete(
model="mistral-large-latest",
response_format={"type": "json_object"},
messages=[
{
"role": "system",
"content": "Extrahieren Sie Daten aus dieser Visitenkarte. Felder: last_name, first_name, title, company, email, phone, address, website. Geben Sie JSON zurück."
},
{
"role": "user",
"content": [
{"type": "text", "text": "Extrahieren Sie Informationen aus dieser Visitenkarte."},
{"type": "image_url", "image_url": encoder_image(image_path)}
]
}
]
)
# Parsen und Validieren mit Pydantic
raw_data = json.loads(response.choices[0].message.content)
card = BusinessCard(**raw_data)
return card
# Nutzung
card = extract_business_card("cartes/contact-dupont.jpg")
print(f"Kontakt: {card.first_name} {card.last_name} - {card.email}")
Achten Sie auf den Unterschied zwischen last_name: str und title: Optional[str] = None. Eine Visitenkarte ohne Namen ist ein fehlgeschlagener Extraktionsversuch; eine Visitenkarte ohne Berufsbezeichnung ist ein normaler Fall. Sie ziehen diese Grenze, und Pydantic setzt sie durch.
Umwandlung in CSV oder DataFrame
Der letzte Schritt ist die Zufuhr Ihrer Datenverarbeitungs-Pipeline. Das oben erzeugte JSON wandelt sich direkt um:
import pandas as pd
# Von einer extrahierten Tabelle
donnees = json.loads(response.choices[0].message.content)
# Erstellen eines pandas DataFrames
df = pd.DataFrame(donnees["rows"])
print(df.to_string())
# Export nach CSV
df.to_csv("export/tableau_extrait.csv", index=False, encoding="utf-8")
Das Argument encoding="utf-8" beim Export ist zwingend erforderlich, whenever Ihre Daten Akzentzeichen oder Währungssymbole enthalten.
Kernaussagen
- Der Parameter
response_format={"type": "json_object"}garantiert eine gültige JSON-Ausgabe - Geben Sie immer ein erwartetes JSON-Schema in Ihrem Prompt an, um die Extraktion zu lenken
- Verwenden Sie Pydantic, um extrahierte Daten in der Produktion zu validieren
- Tabellen, Formulare, Etiketten und Visitenkarten sind ideale Ziele
- Kombinieren Sie Extraktion mit pandas für eine direkte Integration in Ihre Datenworkflows