Technische Spezifikation der Stil-Analyse-Pipeline aus Vision §6 (Eigene
Schrift analysieren, inkl. Hände-vergleichen-Pfad). Ergänzt
architektur.md §6 (Qualitätspipeline) und
§12 (Stil-Analyse-Pipeline).
Jede gefittete Glyph-Instanz hat statistische Größen direkt im
DB-Schema (heute templates.measurements beim Canonical-Speichern;
per Text-Vorkommen später instances.measurements, beides JSONB):
| Feld | Bedeutung | Quelle |
|---|---|---|
slant_deg |
Schräglagen-Winkel der Hauptachse (zur Grundlinie, 90° = senkrecht) | core/pipeline.py:_measurements |
mean_half_width_px |
mittlere halbe Strichbreite | core/pipeline.py |
path_length_px |
Gesamtlänge des Strichs | core/pipeline.py |
aspect_ratio |
Breite/Höhe-Verhältnis des Crops | core/pipeline.py |
Erweiterungen (folgen demselben JSONB-Pattern, keine Schema-Migration):
curvature_mean,curvature_max— Krümmungs-Statistik entlang des Skeletts.entry_tangent_dev,exit_tangent_dev— Abweichung der Anschluss- Tangenten von der Norm (für Übergangs-Analyse).cross_count— Anzahl Selbstüberkreuzungen (Topologie-Indikator).
Pro Hand (ein Schreiber, ggf. über mehrere Sources) und pro
(glyph, position, variant)-Bucket:
- Cluster-Mittelpunkt der Kontrollpunkte (Median pro Punkt nach
Ausreißer-Entfernung — §6 Stufe 1 in
architektur.md). - Abweichungs-Hüllkurve (MAD pro Kontrollpunkt oder Kovarianzmatrix).
- Mittelwerte der Schicht-1-Stats.
Resultat: pro Hand eine „Personal Canonical"-Instanz, die als Template für
beliebige neue Wörter dient (Multi-Stil-Konsequenz aus
architektur.md §10).
M5(C) der MVP-Roadmap liefert die erste Implementierung für die eigene Hand. Voller Ausbau zur P3-Phase.
Speicherung: die Tabelle aggregates (Migration 0004,
core/database/models.py), gekeyt pro (hand, glyph, position, variant)
— die Hand ist die Aggregationseinheit, nicht die Source. Das Schema
liegt bereits an; befüllt wird es durch den Post-MVP-Aggregationsjob
(P3).
Klassische Hinge-Features nach Bulacu/Schomaker. Textunabhängig heißt: zwei Texte derselben Hand werden ähnlich, ohne dass dieselben Wörter darin stehen müssen. Goldstandard für forensische Writer-ID.
Für jeden Konturpunkt der Schrift:
- Zwei Vektoren betrachten — einer zum Konturpunkt
nSchritte vorher, einer zunSchritten danach. - Beide Winkel relativ zur Bildachse messen → Tupel
(φ1, φ2). - Über die gesamte Probe einen 2D-Histogramm
P(φ1, φ2)bauen.
Dieses Joint-Distribution-Histogramm ist der Hinge-Feature-Vector pro Hand. Vergleich zweier Hände via χ²-Distanz oder Earth-Mover's-Distance.
Rotationsinvariante Variante aus Groningen: statt absoluter Winkel Winkeldifferenzen speichern. Robust gegen leicht gedrehte Scans.
EfficientNet-B7 / ResNet-50 + NetVLAD + Triplet Loss erreicht 98–99 % auf Writer-ID-Benchmarks (AHAWP, Khatt, LAMIS-MSHD). Black-Box, didaktisch unbrauchbar — daher nur als optionale Ähnlichkeits-Engine, nicht als Feedback-Geber für „Optimieren"-Pfad.
Pro Glyph-Instanz die Abweichung von der Per-Hand-Aggregation (Schicht 2) visualisieren:
- Welche Glyphe(n) bist du am inkonsistensten? — höchste Streuung der
Kontrollpunkt-Cluster pro
(glyph, position). - Wo weichst du am stärksten von der Norm (Loth) ab? — Abstand Personal Canonical → Loth Canonical, pro Glyph.
- Konkretes Feedback, keine pauschalen Tipps.
Sobald die Per-Hand-Aggregation genug Datenpunkte hat (≥ 10 Instanzen
pro Glyph-Bucket): die aggregierte Personal Canonical wird selbst zum
Template für die Synthese-Pipeline. „In meiner Hand, aber jeden Text" —
das ist exakt der MVP-Gate-3-Mechanismus (denen aus aggregierten Stats),
nur jetzt produktiv für beliebige Wörter.
Side-by-Side mehrerer Sources mit Heatmaps:
- Schräglage-Heatmap:
slant_degpro Glyph × Hand → Farbcode. - Schwellzug-Heatmap:
mean_half_width_pxpro Glyph × Hand. - Glyph-Frequenz-Heatmap: (für Beispieltext-Imports) Glyphen- Verteilung pro Hand.
- Hinge-Heatmap: 2D-Joint-Distribution side-by-side.
Kombiniert mit der Animation aus §11 lassen sich Animationen derselben Glyphe in mehreren Händen direkt nebeneinander abspielen.
Hochlevel-API auf D3. Wenig Code, gute Defaults für Histogramme, Box-Plots, Violins, faceted plots. Standard für „Verteilung pro Glyph"- Reports.
// Pseudo-Code für Slant-Verteilung
Plot.plot({
facet: { data: instances, x: "glyph" },
marks: [Plot.boxX(instances, { x: "slant_deg", y: "source_id" })],
});Maßgeschneiderte 2D-Heatmaps (Hinge-Joint-Distributions als 2D-Histogramm) und Side-by-Side-Vergleiche „Hand A vs. Hand B" mit Difference-Map. D3 für maximale Layout-Kontrolle.
Performant bei großen Daten, eingebaute Heatmap-Komponente. Größerer Bundle (~1 MB+), weniger anpassbar bei wissenschaftlichen Sonderformen. Nicht erste Wahl, aber Option für späteren Performance-Druck.
Wissenschaftliche Plots out-of-the-box (Heatmaps, Box-Plots, Violinen), Hover-Tooltips kostenlos. Großer Footprint (3 MB+), Lizenz für kommerzielles Hosting prüfen. Nur, wenn Tooltips-Komfort wichtig wird.
Default-Wahl: Observable Plot für Standard-Plots, D3.js für die Heatmap-Side-by-Side-Vergleiche.
DigiPal und Archetype (King's Digital Lab) sind ein etabliertes Framework für allograph-basierte paläografische Analyse. Modelliert die Hierarchie:
Konkrete Instanz → Allograph → Abstrakter Buchstabe
Das ist 1:1 unser Datenmodell
(architektur.md §3). Wir übernehmen es
nicht als Code-Dependency (Wartungslage 2024+ unklar; Django-Monolith
ist Übernahme-Aufwand), sondern als konzeptionelle Vorlage.
- PIL + scipy.ndimage + scikit-image für Vorverarbeitung —
skeletonize,threshold_local,distance_transform_edtsind schon im Einsatz (core/extract.py). OpenCV ist bewusst keine Dependency; nur als Option, falls eine Vorverarbeitung es später erzwingt. - NumPy / SciPy für statistische Aggregation und Cluster-Analyse (Mahalanobis, MAD, KDE).
- scikit-learn optional für Cluster-Diagnostik (Silhouette, GMM für Multi-Variant-Trennung).
- PyTorch / HuggingFace nur falls ML-Embeddings hinzukommen — kein Default-Pfad.
- Observable Plot + D3.js als oben beschrieben.
- React-Komponenten als „Stat Cards" pro Glyph-Bucket (Slant, Schwellzug, Konsistenz).
- Kein Deep-Learning-First-Ansatz. Per-Instanz-Stats + Per-Hand- Aggregation + Hinge-Features sind klassische, erklärbare Methoden. ML nur dort, wo es unverzichtbar wird (Hand-Ähnlichkeits-Suche bei vielen Hände).
- Keine Forensik-Behauptungen. Schreiber-Identifikation als forensisches Beweismittel ist nicht das Ziel. Stil-Analyse ist didaktisch — sie hilft Lernenden, ihre eigene Hand zu sehen.
- Keine Black-Box-Heatmaps. Jede Statistik muss zurückführbar sein auf konkrete Instanzen — sonst funktioniert „Optimieren" nicht.
- Directional Hinge Features for Writer Identification (Springer)
- Writer Identification Using Edge-Based Directional Features (Bulacu/Schomaker)
- Delta-n Hinge: Rotation-invariant Features (Groningen)
- Writer Identification using Directional Ink-Trace Width (ScienceDirect)
- Skeleton Hinge Distribution (Aegean)
- Arabic Handwriting DL Writer ID 2024 (arXiv)
- End-to-End DL Writer ID Arabic (Springer 2023)
- Archetype (Zenodo)
- DigiPal Wiki
- DigiPal Project
- Artificial Paleography (Speculum)
- Computational Paleography of Medieval Hebrew Scripts (CEUR)
- scikit-image Skeletonize Docs
- D3 by Observable
- D3 Heatmap Gallery
- Observable Plot
- Plotly Heatmaps JS