Skip to content

Latest commit

 

History

History
238 lines (174 loc) · 9.46 KB

File metadata and controls

238 lines (174 loc) · 9.46 KB

Stil-Analyse

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).


1. Schichten-Modell

Schicht 1 — Per-Instanz-Stats (liegt vor)

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).

Schicht 2 — Per-Hand-Aggregation

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).

Schicht 3 — Textunabhängige Writer-ID (optional, post-P4)

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.

Hinge-Feature

Für jeden Konturpunkt der Schrift:

  1. Zwei Vektoren betrachten — einer zum Konturpunkt n Schritte vorher, einer zu n Schritten danach.
  2. Beide Winkel relativ zur Bildachse messen → Tupel (φ1, φ2).
  3. Ü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.

Δn-Hinge

Rotationsinvariante Variante aus Groningen: statt absoluter Winkel Winkeldifferenzen speichern. Robust gegen leicht gedrehte Scans.

Alternative: ML-Embeddings

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.


2. Vision-Anwendungspfade

„Optimieren" (Vision §6, Pfad „Optimieren")

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.

„Neuer Stil als Basis" (Vision §6, Pfad „Neuer Stil als Basis")

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.

„Hände vergleichen" (Vision §6, Pfad „Hände vergleichen")

Side-by-Side mehrerer Sources mit Heatmaps:

  • Schräglage-Heatmap: slant_deg pro Glyph × Hand → Farbcode.
  • Schwellzug-Heatmap: mean_half_width_px pro 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.


3. Heatmap-Output

Observable Plot (Default)

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" })],
});

D3.js (Spezial-Layouts)

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.

ECharts (Alternative)

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.

Plotly.js

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.


4. Konzeptionelle Vorlage: DigiPal / Archetype

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.


5. Toolchain

Backend (Python)

  • PIL + scipy.ndimage + scikit-image für Vorverarbeitung — skeletonize, threshold_local, distance_transform_edt sind 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.

Frontend

  • Observable Plot + D3.js als oben beschrieben.
  • React-Komponenten als „Stat Cards" pro Glyph-Bucket (Slant, Schwellzug, Konsistenz).

6. Was wir nicht machen

  • 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.

7. Quellen