Pokemon TCG Karten-Extraktor mit OCR
#Einleitung
Als Pokemon TCG Pocket-Spieler fand ich mich jedes Mal dabei, meine Sammlung manuell zu durchsuchen, wenn ich wissen wollte, ob ich eine bestimmte Karte hatte. Das Spiel erlaubt dir, Karten zu erfassen, aber es gibt keinen einfachen Weg, deine Sammlung zu exportieren oder zu durchsuchen. Also habe ich einen gebaut.
Dieser Artikel dokumentiert, wie ich ein vollständiges Karten-Extraktionssystem mit OCR, Web-Scraping und SQLite gebaut habe. Ich führe dich durch die Architektur, die Herausforderungen, die ich gemeistert habe, und wie ich sie gelöst habe.
#Das Problem
Karten manuell zu katalogisieren ist mühselig:
- Screenshot einer Karte in der App
- Kartenname in einer Datenbank nachschlagen
- In einer Tabelle erfassen
Das wollte ich automatisieren: Screenshot → OCR → Datenbank in Sekunden, nicht Minuten.
#Systemarchitektur
Das System hat fünf Hauptkomponenten:
#Komponenten-Übersicht
| Komponente | Zweck |
|-----------|---------|
| vorverarbeitung/ | Bildzuschnitt, Kontrastverbesserung |
| extraktion/ | Pokemon/Trainer/Energy-Karten erkennen |
| ocr_engine/ | EasyOCR + Tesseract für Textextraktion |
| api/local_lookup.py | Multi-Signal-Kartenabgleich |
| database.py | SQLite-Sammlungsspeicher |
#Datensammlung: Scraping von Pokewiki.de
Bevor ich Karten abgleichen konnte, brauchte ich eine Datenbank. Ich habe pokewiki.de (deutsches Pokemon-Wiki) nach Kartendaten gescraped.
#Was ich gescraped habe
- 2540 einzigartige Karten in 17 Sets (A1-B2a, PROMO-A, PROMO-B)
- 124 einzigartige Fähigkeiten mit Effektbeschreibungen
- 4509 Bild-URLs (inklusive Nachdrucke)
- ~200 Angriffseffekte mit detailliertem Text
#Scraping-Datenfluss
#Karten-Erkennung: Pokemon vs Trainer vs Energy
Nicht alle Karten sind gleich. Pokemon-Karten haben KP, Angriffe und Fähigkeiten. Trainer-Karten haben völlig andere Felder. Ich musste zuerst den Kartentyp erkennen.
Die Erkennung nutzt deutsche Keywords, da das Spiel auf Deutsch angezeigt wird:
#OCR-Extraktion: EasyOCR zur Rettung
Mit dem bekannten Kartentyp extrahierte ich Text mit EasyOCR mit deutschen und englischen Modellen.
#Extraktions-Pipeline
#Vollständiger End-to-End-Datenfluss
#Bildvorverarbeitungs-Pipeline
#OCR-Signal-Korrektur-Pipeline
#Beispiel-Extraktion
Eingabe: Screenshot der Karte Igastarnish (Grass/Bug Pokemon)
Roh-OCR-Ausgabe:
Extrahierte Signale:
#Herausforderungen & Lösungen
#Herausforderung 1: OCR liest KP-Werte falsch
Problem: EasyOCR liest oft KP-Werte falsch. "502" bedeutet "50", "802" bedeutet "80". Die zusätzliche Ziffer ist Rauschen vom KP-Icon.
Lösung: Nachbearbeitung mit Regex, die nachfolgende Ziffern entfernt:
#Herausforderung 2: Doppelte Karten in der Datenbank
Problem: Einige Karten erscheinen in mehreren Sets (Nachdrucke). Der Scraper erstellte doppelte Einträge mit verschiedenen Set-IDs, aber demselben Kartennamen.
Lösung: Deduplikationslogik hinzugefügt, die Einträge zusammenführt basierend auf:
- Exaktem deutschen Namen
- Gleicher KP-Wert
- Gleicher Pokédex-Nummer
#Herausforderung 3: Fehlende Kartenbilder
Problem: Erster Scrapevorgang erhielt nur 1483 Bilder. 1969 Karten hatten keine Bild-URLs.
Lösung: scrape_images.py ein zweites Mal mit aggressiverem Timeout-Handling und Retry-Logik ausgeführt:
#Herausforderung 4: Besondere Illustration-Karten
Problem: Special Illustration (SAI)-Karten haben verschiedene Bild-URLs auf pokewiki - sie werden auf einem separaten CDN mit verschiedenen URL-Mustern gehostet.
Lösung: SAI-Karten anhand der Seltenheit ("4 Star" oder "Special Illustration") erkennen und ein anderes URL-Muster verwenden:
#Herausforderung 5: Schwäche/Rückzug nicht extrahiert
Problem: Das Regex für Schwäche und Rückzug funktionierte nicht mit dem OCR-Output. Das Schwäche-Symbol (Fire+20) erschien in einer separaten Zeile.
Lösung: Regex-Muster verbessert und gesamten OCR-Output-Kontext betrachtet:
#Karten-Abgleich: Die Multi-Signal-Engine
Mit extrahierten Signalen und einer Datenbank brauchte ich einen Abgleichalgorithmus. Ich implementierte einen prioritätsbasierten Ansatz:
#Konfidenz-Bewertung
| Strategie | Konfidenz | Wann verwendet | |-----------|----------|----------------| | Name + Set | 95% | Exakter deutscher Name + Set-ID | | Name + KP | 85% | Fuzzy-Name + KP-Übereinstimmung | | KP + Angriff + Set | 85% | KP + Angriffsname + Set-Kombination | | KP + Schwäche + Set | 80% | KP + Schwäche + Set-Kombination | | Nur KP | 60% | Notlösung - nur KP-Übereinstimmung |
Karten unter 60% Konfidenz gehen in failed_to_capture/ zur manuellen Überprüfung.
#Datenbank-Design
Die Sammlung verwendet SQLite mit einem einfachen, aber effektiven Schema:
Wichtige Features:
- Mengenverfolgung: Increment beim Hinzufügen von Duplikaten
- Vollständige Kartendaten: Alle Felder für Filterung gespeichert
- Schnelle Lookups: Indiziert auf name, set_id, KP
#Python Core: Das Extraktions-Skript
Der Haupteinstiegspunkt ist extract_batch_v2.py. So funktioniert es:
#Bildvorverarbeitung
#Kartentyp-Erkennung
#Python Core: Die Karten-Abgleich-Engine
Die Abgleichlogik in api/local_lookup.py implementiert Multi-Signal-Abgleich:
#Python Core: Der Web-Scraper
Den Aufbau der Datenbank erforderte mehrere Scraper:
#Ergebnisse
Nach Implementierung aller Komponenten:
- Extraktionszeit: ~3-5 Sekunden pro Karte
- Erfolgsrate: ~85% der Karten matchen mit 60%+ Konfidenz
- Sammlungsgröße: Begonnen mit 1 Karte (Ledyba, natürlich)
- Datenabdeckung: Alle 2540 deutschen Karten mit Bildern
#Datensammlung: Datenfluss
Dieses Dokument zeigt den Datenfluss durch das Pokemon TCG Pocket Karten-Extraktionssystem.
#Datenbank-Quellen
#Karten-Abgleich-Priorität
#Datenschema
Eingabe: Screenshot
Nach OCR: Signale
Datenbank-Abgleich: Kartendaten
Sammlungs-Speicher
#Datei-Transformationen
#Sammlungs-Statistiken Flow
#Scraping-Workflow
#Gelernte Lektionen
-
Nachbearbeitung ist essentiell: OCR ist nie perfekt. Baue robuste Korrekturlogik für häufige Fehlermodi.
-
Scraping ist iterativ: Erster Durchgang holt selten alles. Plane mehrere Durchgänge, um Lücken zu füllen.
-
Konfidenz-Bewertung ist subjektiv: 60% Schwellenwert funktioniert, aber einige Fehlpositive rutschen durch. Erwäge Feedback-Schleife.
-
Deutscher Text ist knifflig: Sonderzeichen (ü, ö, ä) und zusammengesetzte Wörter verursachen Abgleichprobleme. Normalisieren vor dem Vergleichen.
#Zukünftige Arbeit
- Bildbasiertes Matching mit Karten-Art hinzufügen
- Mobile App für Kamera-Erfassung implementieren
- Duplikaterkennung aus verschiedenen Sets hinzufügen
- Web-Interface für Sammlungs-Durchsuchung bauen
#Fazit
Den Bau dieses Karten-Extraktors hat mir viel über OCR-Pipelines, Web-Scraping im großen Maßstab und Multi-Signal-Abgleichalgorithmen beigebracht. Die wichtigste Erkenntnis: Beginne einfach, iteriere bei Fehlern.
Der vollständige Quellcode ist im Projekt-Repository verfügbar. Viel Spaß beim Sammeln!
Erstellt mit Python, EasyOCR, SQLite und jeder Menge deutscher Kartendaten.