- README: Ablauf für PDF-Bücher mit --formulas, Quelle pdf2md --formulas, Satzzeichen nach eingebetteten Formeln, Stand Corral (10 %: 79 % automatisch, ~2 h ganzes Buch), Pilot 70 → ~24 min, Einstellung pdftext, crops/ und bericht/ im Arbeitsordner, 8B-Modell gemessen und verworfen - BEDIENUNGSANLEITUNG: llama-server --parallel 8 -c 32768, pix2text auf freiester GPU, pdf2md --formulas, Statuszeile mit Zeiten je Stufe, Dauer, EPUB mit --from-md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
23 KiB
formula_img2latex
Nachbearbeitungs-Werkzeug für die Markdown-Ausgaben von epub2md und pdf2md: Formeln, die nur als Bild vorliegen, werden durch LaTeX ersetzt – aber nur, wenn zwei unabhängige Erkenner dieselbe Formel lesen (zuerst das Formel-OCR pix2text, bestätigt vom Bildmodell Qwen; bei Uneinigkeit darf Gemma pix2text bestätigen) und ein grober Bildabgleich nicht widerspricht. Alles andere geht in eine Review-Galerie oder bleibt Bild.
Für PDF-Bücher findet pdf2md --formulas jede Formel auf der Seite, auch im Fließtext und in Merkkästen,
und schneidet sie als Bild aus; formula_img2latex übersetzt sie dann ebenso (siehe Quellen).
Schritt-für-Schritt-Anleitung: BEDIENUNGSANLEITUNG.md. Änderungen je Version:
CHANGELOG.md. Hintergrund und ursprüngliche Planung: Idee/.
Annahmeregel
Jedes Zeichen muss stimmen und an der richtigen Stelle relativ zu den anderen stehen. Abstände, Pfeil- und Bruchstrichlängen, Schriftgröße, kursiv/aufrecht und Fettdruck dürfen abweichen.
Eine Formel wird automatisch ersetzt (Regel p2t, Standard), wenn
- pix2text (Formel-OCR MFR 1.5, lokal, GPU) sie zuerst liest und Qwen3-VL-30B-A3B (Bildmodell,
lokal, llama.cpp) dieselbe Formel liest oder, wenn die beiden uneinig sind, Gemma-4-26B-A4B
(lokal) die Lesart von pix2text bestätigt. Übernommen wird immer pix2texts Lesart – sie trifft den
Fettdruck am besten. Ihre überflüssigen Leerzeichen entfernt vorher
post_processaus pix2tex (LaTeX-OCR):\frac{\alpha} {3 6 0}→\frac{\alpha}{360}; am gesetzten Bild ändert das nichts, geprüft an 400 Lesarten. Auch der Schlusspunkt muss bestätigt sein, - Pandoc sie nach MathML umsetzen kann (sonst bliebe sie im EPUB/PDF roher TeX-Text) und
- das gerenderte LaTeX dem Original grob ähnelt (Bild-Veto, elastischer Vergleich, Ähnlichkeit ≥ 0,65).
Sind Qwen und Gemma gemeinsam gegen pix2text einig, entscheidet ein Mensch: Genau das sind die Fehler,
die beide Bildmodelle teilen (\mathcal{E}_r statt \varepsilon_r, erfundenes \tilde{z}).
Die frühere Regel vlm3 (Qwen = Gemma, bestätigt von GLM-4.6V über OpenRouter) bleibt wählbar:
"consensus_rule": "vlm3" unter settings in workspace.json des Arbeitsordners.
„Dieselbe Formel“ prüft consensus.py: gleiche Normalform (Abstände, \left/\right, überflüssige
Klammern, \vec/\overrightarrow, \frac/\dfrac, \iff/\Leftrightarrow, pmatrix/\left(\begin{matrix},
TeX-Umlaute, \atop/\substack, \cdot\cdot\cdot/\cdots, \root3\of{x}/\sqrt[3]{x}, kursiv/aufrecht,
fett/normal …) oder – als Rückfallebene – zeichengleiches Rendering der beiden Lesarten (Render gegen
Render, nicht gegen das verrauschte Original). Eine Gleichungsnummer muss in allen Lesarten
übereinstimmen und wird als Text hinter die Formel gesetzt.
Mehrzeilige Formeln (seit 0.4.0): gleich, wenn sie dieselben Zeilen mit denselben Zeichen haben,
egal in welchem Rahmen. aligned/gathered/split und ihr & fallen weg (a\\b =
\begin{aligned}a&\\b\end{aligned}), eine leere letzte Zeile zählt nicht; cases,
\left\{\begin{array}{ll}…\right. und pix2texts \left\{\begin{aligned}…\right. sind dasselbe.
Matrizen bleiben Matrizen: Dort trennt & Spalten (1&2 ≠ 12). Ob eine Gruppe ein Argument ist,
entscheidet die Argumentzahl des Befehls (\frac 2, \sqrt 1, \Delta 0), nicht ihre Stellung:
t^{2}\,{\sqrt{2}} = t^2\sqrt{2}, \Delta{x_{n}} = \Delta x_n.
Gleiche Struktur (structure.py, sympy, optional, standardmäßig aus): Beide Lesarten ergeben
denselben unausgewerteten Ausdrucksbaum (\frac{a}{b} = a/b, a\cdot b = ab); nichts wird
umgerechnet oder umgestellt (a+b ≠ b+a, 2x=4 ≠ x=2, a-b ≠ a+(-b)). Relationen gehen nie an
sympy (es wertet v=(3,4)ᵀ und \nu=(3,4)ᵀ beide zu False aus), jedes Zeichen wird durch einen
Platzhalter geschützt (sympy macht aus \varepsilon und \epsilon ein Symbol), sichtbare Klammern
zählen, Ungedecktes fällt auf den Render-Vergleich zurück. Gemessen: vor der mehrzeiligen Normalform
+1 Formel bei 400, danach nichts mehr – deshalb aus. Einschalten: structural = 1 oder
FORMULA_STRUCTURAL=1; braucht pip install sympy lark.
Sind sich die Modelle uneinig oder widerspricht das Veto, entscheidet ein Mensch im Review.
Messung
Regel p2t (Standard)
Göllmann Band 1, 150 echte Bilder und 150 Nachbildungen im Gehrke-Stil, Lesarten aller Modelle:
| Regel | echt: automatisch / falsch | Gehrke-Stil: automatisch / falsch |
|---|---|---|
| pix2text = Qwen | 81 % / 0 | 76 % / 0 |
| + Stichwahl: Gemma bestätigt pix2text, Qwens Lesart (erste Fassung) | 85 % / 0 | 80 % / 0 |
| pix2text zuerst und übernommen, bereinigt, Stichwahl Gemma (Standard) | 86 % / 0 | 85 % / 0 |
| + Stichwahl auch Qwen = Gemma gegen pix2text | 92 % / 1 | 91 % / 2 |
Qwen = Gemma = GLM (Regel vlm3) |
78 % / 0 | 70 % / 0 |
Ab 0.4.0 mit mehrzeiliger Normalform, gleiche Lesarten (--reuse): 89 % / 0 (134) und 88 % / 0
(132); Band 2 (tools/regeltest.py, zwei Stichproben zu 50): 44 und 45 automatisch statt 39 und 43,
0 falsch, 6 bzw. 5 Review. Zusammen +17 Formeln bei 400. Die Tabelle und die folgenden Absätze
zeigen den Stand 0.3.0.
Allein richtig: pix2text 90 % / 85 %, Qwen 86 % / 84 %, Gemma 86 % / 80 %, GLM 86 % / 83 %.
Zeit je Formel (seriell, 15 Formeln): pix2text 0,10 s (GPU) bzw. 0,51 s (CPU), Qwen 0,72 s, GLM 1,19 s,
Gemma 1,77 s. Gegenprobe an Göllmann Band 2 (tools/regeltest.py, zwei getrennte Stichproben zu 50
Formeln): 39 bzw. 43 automatisch (78 % bzw. 86 %), 0 falsch, 11 bzw. 7 Review; Gemma wurde für 14
bzw. 9 Formeln gefragt. Lesen je Formel im Mittel 2,3 bzw. 1,5 s (alle Tools nacheinander, ohne Bildprüfung).
pix2text ist nicht unfehlbar: In den Reviews standen auch Fälle, in denen nur pix2text sich verlesen hatte
(fehlende Wurzelexponenten, zerfallene Vektoren, \nu statt fettem v) – deshalb bleibt die Bestätigung
durch Qwen Pflicht.
Bild-Schiedsrichter (0.4.0, gemessen, aus): Bei „Qwen = Gemma gegen pix2text“ misst
verify.image_arbiter, wie deutlich das Original Qwens Lesart zeigt (gleiches Kontrastmaß wie der
Variantentest). In 16 solchen Fällen (Band 1 und 2) hatte Qwen 14-mal recht, mit Belegen von 3 bis 50.
Aber: Beim gemeinsamen Fehler \mathcal{E}_r statt \varepsilon_r sprach das Bild mit 7,2 sogar für
die falsche Lesart. Ab Schwelle 8 wären es +11 Formeln bei 0 falsch – der Abstand ist bei zwei
Gegenbeispielen nicht belastbar. Einschalten: arbiter = 1, arbiter_margin (5).
Prompt-Stilvorgabe (0.4.0, gemessen, verworfen): feste Schreibweisen für aligned, pmatrix,
cases, \dots, \text. Band 2: 44 und 44 statt 44 und 45 – die Normalform gleicht die Schreibweisen
schon aus, und mit der Zeilenvorgabe schrieben beide Modelle nach \\ ein wörtliches \n.
Regel vlm3 (Standard bis 0.2.0)
An Formelbildern mit bekanntem TeX (Göllmann, Springer: TeX im alt-Text), je 150 echte Bilder und 150 Nachbildungen im Stil von Gehrke (LaTeX + dvipng mit Bitmap-Schriften, ~102 dpi, JPEG):
| Regel | echt: automatisch / davon falsch | Gehrke-Stil: automatisch / davon falsch |
|---|---|---|
| Qwen = Gemma | 73 % / 1 | 69 % / 2 |
| Qwen = Gemma = Gemini 2.5 Flash | 67 % / 0 | 57 % / 1 |
| Qwen = Gemma = GLM-4.6V ohne Nachdenken (Standard) | 68 % / 0 | 63 % / 0 |
- Fehler, bei denen zwei Modelle gemeinsam irren, gibt es:
\mathcal{E}_rstatt\varepsilon_r, ein erfundenes\tilde{z},x^{f}stattx'. Die dritte Lesart aus einer anderen Modellfamilie fängt sie ab; Gemini (mit Gemma verwandt) machte einen davon mit. - Selbstauskünfte der Modelle („95 % sicher“) sind wertlos. Token-Wahrscheinlichkeiten (Logprobs) werden gespeichert, brachten aber neben der dritten Lesart keinen Gewinn (Schwellen bleiben einstellbar).
- „Nachdenken“ (Reasoning) ist für alle Modelle abgeschaltet: Gemma 4 wird ~10× schneller, GLM-4.6V liest ohne Nachdenken sogar besser (85 % statt 79 % allein richtig) und braucht ~25× weniger Tokens.
- Fettdruck lesen alle Modelle schlecht (fette Vektoren werden zu normalen Buchstaben); nach Vorgabe zählt
er nicht. Mit
bold_relevant=1würden diese Fälle ins Review gehen. - Das Bild-Veto fing den einzigen Fall ab, in dem alle drei Modelle gemeinsam irrten (Ähnlichkeit 0,5–0,6); richtige Lesarten lagen bei ≥ 0,66. Daher die Schwelle 0,65. Eine Prüfung der Schriftgröße (Pixel pro Punkt gegen das Buchmittel) erzeugte nur Fehlalarme und ist abgeschaltet.
- Die Messung lief ohne Textausschnitt um die Formel;
rungibt den Modellen einen kurzen Textausschnitt (≤ 240 Zeichen) mit. Die Stichproben am Buch (62 von 62 korrekt) sprechen nicht gegen den Kontext, gemessen ist er aber nicht.
Gehrke, Brückenkurs Mathematik (EPUB, 1505 Formelbilder): siehe Stand.
Ablauf
scan Bildverweise in chapters/*.md (bzw. pdf2md-Markdown) finden, Formel/Abbildung vorklassifizieren
run in Paketen zu 50: pix2text, dann Qwen lesen, prüfen, Gemma nur für Uneinige, prüfen;
nach jedem Paket eine Statuszeile mit Zeiten je Stufe (Regel vlm3: Qwen + Gemma, GLM nur
für Einige). Die GPUs lesen schon das nächste Paket, während die CPU das vorige prüft.
review Zweifelsfälle im Browser: Original / Render / Overlay / Diff, LaTeX korrigieren und neu prüfen
apply angenommene Formeln ins Markdown schreiben (aus einer Sicherung, idempotent)
revert Markdown-Dateien auf den Stand vor apply zurücksetzen
recognize einzelne Engine (local, local2, cloud, p2t) laufen lassen
verify prüfen und entscheiden (ohne neue Modellabfragen)
status Zählung je Status
calibrate Messung an Formelbildern mit bekanntem TeX (--consensus: Konsensregel)
python3 formula_img2latex.py run output/buch # epub2md-Ausgabeordner
python3 formula_img2latex.py review output/buch
python3 formula_img2latex.py apply output/buch
python3 epub2md_merge.py output/buch --force # Gesamtdatei danach neu bauen
PDF-Buch mit allen Formeln, auch im Fließtext:
cd ~/Python_Programs/pdf2md
python3 pdf2md.py --formulas --epub buch.pdf Output/buch/buch.md # Formeln als Bilder + Liste
cd ~/Python_Programs/formula_img2latex
python3 formula_img2latex.py run ~/Python_Programs/pdf2md/Output/buch/buch.md --pdf buch.pdf
python3 formula_img2latex.py apply ~/Python_Programs/pdf2md/Output/buch/buch.md
cd ~/Python_Programs/pdf2md && python3 pdf2md.py --from-md Output/buch/buch.md # EPUB mit MathML
Status je Formel: auto_accepted, needs_review, rejected_keep_image, render_failed, no_candidate,
not_formula, nach Review accepted_by_human, corrected_by_human, kept_by_human.
Modelle und Server
| Engine | Standard | Konfiguration |
|---|---|---|
local |
llama.cpp http://127.0.0.1:8011/v1 (Qwen3-VL-30B-A3B-Instruct Q4_K_M + mmproj), 8 parallele Anfragen |
FORMULA_LOCAL_URL, FORMULA_LOCAL_MODEL |
local2 |
llama.cpp http://127.0.0.1:8012/v1 (Gemma-4-26B-A4B-it Q4_0 + mmproj) |
FORMULA_LOCAL2_URL, FORMULA_LOCAL2_MODEL |
cloud |
OpenRouter, z-ai/glm-4.6v (nur Regel vlm3) |
OPENROUTER_API_KEY, FORMULA_CLOUD_MODEL |
p2t |
pix2text MFR 1.5 (ONNX) im Prozess, die sichtbare GPU mit dem meisten freien Speicher, sonst CPU; gebündelt nach Pixelbudget | FORMULA_P2T_DEVICE (auto, cpu, cuda:N), FORMULA_P2T_MODEL |
pix2text auf der GPU braucht onnxruntime-gpu statt onnxruntime (cuDNN kommt aus den nvidia-Paketen
von torch). Für post_process wird pix2tex ohne seine Abhängigkeiten installiert
(pip install --no-deps pix2tex munch), weil es sonst timm==0.5.4 erzwingen würde. cuda:N zählt innerhalb von CUDA_VISIBLE_DEVICES.
FORMULA_<ENGINE>_THINKING=1 schaltet das Nachdenken wieder ein. Antworten sind auf 800 Tokens begrenzt
(lange mehrzeilige Formeln brauchen ~400; einzelne Antworten von Gemma liefen sonst in
Wiederholungsschleifen bis 165 s). Jede Lesart wird mit Modell, Prompt-Version und Nachdenk-Einstellung
gespeichert; dieselbe Frage wird nie zweimal gestellt, ein abgebrochener Lauf setzt dort fort.
Qwen-Server mit --parallel 8 -c 32768 (je Platz 4096 Tokens) starten; run stellt bis zu 8 Anfragen
gleichzeitig (BEDIENUNGSANLEITUNG). Gemessen und verworfen: Qwen3-VL-8B statt 30B-A3B ist nicht schneller
(das MoE-Modell rechnet je Token nur ~3B Parameter) und liest etwas schlechter (Göllmann 42/44 statt 44/45
automatisch).
Kosten der Cloud-Stufe (nur Regel vlm3): GLM liest nur Formeln, bei denen Qwen und Gemma einig sind. Gehrke: 967
Anfragen, Ø 2,6 s, zusammen rund 0,15–0,20 $.
Bildvergleich (Veto)
compare.py rendert die Lesart mit pdflatex (Schrift je Buch automatisch: cm, times, txfonts,
palatino, stix, euler), richtet sie auf das Original aus und verzerrt sie elastisch
(dynamische Zeitverzerrung über Spalten und Zeilen; Dehnen kostet proportional zur Tinte), damit
Abstände und Längen keine Rolle spielen. Die Ähnlichkeit danach ist das Veto. Geprüft wird nur
die Lesart, die übernommen werden kann: die von pix2text (Regel vlm3: die von Qwen). Bestätigende
Lesarten werden nie übernommen und brauchen keine Prüfung. Die Prüfergebnisse tragen eine
Versionsnummer des Verfahrens und werden nach Änderungen neu berechnet. Der alte Pixel-Entscheider mit
Verwechslungsvarianten und Kontrasttest bleibt als Modus decide=pixel erhalten.
Sicherheit: Kandidaten kommen von Modellen und gelten als unsicher. Vor pdflatex werden Befehle wie
\input, \write, \def, \catcode abgelehnt; pdflatex läuft mit -no-shell-escape,
openout_any=p, Zeitlimit.
Arbeitsordner
<ausgabe>.formulas/ # neben der Ausgabe, weil epub2md --force die Ausgabe ersetzt
├── workspace.json # Quelle, Schrift, Einstellungen, apply-Zustand
├── formulas/f-<sha12>-<d|i>.json # je Bild und Darstellung: Lesarten, Prüfung, Entscheidung
├── crops/<id>.png # Original je Formel, einmal ausgeschnitten (PDF-Quellen)
├── review/<id>-{orig,render,rigid,diff}.png
├── bericht/ # Ergebnisseite (tools/buch_bericht.py)
└── backup/ # Markdown-Dateien vor dem ersten apply
Die Datensätze hängen am SHA-256 des Bildes: Ein erneuter epub2md-Lauf verliert keine Entscheidungen.
Einstellungen in workspace.json → settings.consensus_thresholds: require_third (1),
bold_relevant (0), structural (0), arbiter (0), arbiter_margin (5), veto_ncc (0,65),
veto_scale_dev (0 = aus), min_p_mean/min_p_min (0), pdftext (0: die PDF-Textebene bestätigt nie;
gemessen: in 12 von 319 Fällen fehlten dort Punkte, Striche oder Indizes, die Qwen sah).
Quellen
| Quelle | Erkennung | Begrenzer |
|---|---|---|
| epub2md-Ordner | conversion-report.json; Warnungen formula-image markieren sichere Formeln |
--math auto: $…$/$$…$$, --math tex: \(…\)/\[…\]; deutsche Bücher: 3{,}6 |
pdf2md (<name>.md + <name>_images/ oder --split-Ordner) |
Bildname <pdf>-<seite>-<box>; mit --pdf per Template-Matching auf der Seite gefunden und mit 600 dpi aus dem Vektor-PDF neu ausgeschnitten |
$…$/$$…$$ |
pdf2md --formulas |
Bildname <pdf>-<seite>-f<nr>.png (300 dpi), Liste <name>_images/formulas-*.json mit Seite, Rechteck, Art (im Text/abgesetzt) und PDF-Text; das Bild wird direkt verwendet |
$…$/$$…$$ |
Mit pdf2md --formulas findet die Formelerkennung von pix2text (MFD) jede Formel auf der Seite, auch im
Fließtext und in Merkkästen; pdf2md schneidet sie zeichengenau aus dem Text (statt Glyphensalat wie x4n).
Ein Satzzeichen am Ende einer eingebetteten Formel wird vor dem Vergleich abgetrennt und als Text hinter
die Formel gesetzt ($a^{x}$,). Codeblöcke werden nie verändert. Formeln in Tabellen erfasst die
Erkennung noch nicht.
Werkzeuge zum Einstellen
tools/vergleich.py AUSGABE– feste Stichprobe (50 Formeln), verarbeitet wierun, schreibtvergleich/<name>/index.htmlmit Original, gerenderten Lesarten, Entscheidung und Veto-Overlay.tools/konsens_bericht.py BERICHT.json EPUB– Übersichtsseite zucalibrate --consensus --report.tools/zeittest.py EPUB– Zeit und Trefferquote je Tool, seriell an 15 Formeln mit bekanntem TeX.tools/regeltest.py EPUB [--n 50] [--reuse ergebnis.json] [--refresh local,local2] [--arbiter 8]– die Standardregel an Formeln mit bekanntem TeX, wierun; Seite mit Original, wahrer Formel, allen Lesarten und Entscheidung.--refreshfragt trotz--reusediese Engines neu (Prompt-Test).tools/buch_bericht.py AUSGABE– Ergebnisseite eines ganzen Buchs nachrun: jede Formel mit Original, gesetztem LaTeX, Status, Begründung und allen Lesarten, filterbar; liegt in<arbeitsordner>/bericht/index.html(Buchausschnitte, nicht versioniert).tools/vergleich_bericht.py --regeltest VORHER:NACHHER --kalibrierung VORHER.json:NACHHER.json– Vorher/Nachher-Seite zweier Läufe auf denselben Lesarten: Zahlen, jede geänderte Entscheidung und jedes geänderte Urteil gegen die Wahrheit, mit Original und gerenderten Lesarten.calibrate --consensus --engines local,local2,cloud,p2t --report X.jsonmisst alle Regeln;--reuse X.jsonrechnet sie ohne Modellabfragen neu.vergleich/ist nicht versioniert (Ausschnitte aus Büchern).
Stand
Formeln im Fließtext (unveröffentlicht, nach 0.4.0): Corral mit pdf2md --formulas: 9239 Formelbilder
(davon ~88 % eingebettet). Stichprobe 10 % (940): 747 automatisch (79 %), im Text 83 %, abgesetzte
Box-Bilder (Herleitungen, Kästen) nur ~29 %; 174 Review, 19 keine Formel; 13 Minuten, hochgerechnet ~2 h
für das ganze Buch. Beschleunigung am Pilot (869 Formeln): 70 → ~24 Minuten, Entscheidungen zu 863/876
gleich (die Abweichungen kommen von den Modellen selbst). Qualität ist hier ohne bekannte Lösung –
vor dem Einsatz eine Stichprobe der übernommenen Formeln von Hand prüfen.
Version 0.4.0 (Regel p2t, mehrzeilige Normalform) ist an Göllmann Band 1 und 2 gemessen (siehe
Messung), aber noch nicht am ganzen Gehrke gelaufen.
Erstes ganzes PDF-Buch (0.4.0): Corral, Elementary Calculus (346 Seiten, TeX-PDF, pdf2md mit
600-dpi-Neuausschnitt): 1150 Ausschnitte → 429 automatisch ersetzt (37 %), 633 Review, 61 keine
Formel, 27 Abbildungen. EPUB (pdf2md --from-md, jetzt mit --mathml): 429 Formeln als MathML, kein
TeX-Rest. Laufzeit rund 4 Stunden (pix2text Ø 3,9 s, Qwen Ø 8,1 s, Gemma Ø 15 s je Anfrage – große
Ausschnitte). Das Review besteht überwiegend aus Ausschnitten, die keine einzelne Formel sind
(Merkkästen mit Text, Tabellen, Diagramme, ganze Herleitungen) – das muss pdf2md besser trennen. Die folgenden Zahlen stammen von Version 0.2.0 (Regel vlm3, mit GLM).
Version 0.2.0 (Konsens), getestet am Gehrke, Brückenkurs Mathematik (EPUB, CM-Formeln als kleine JPGs):
| Anzahl | |
|---|---|
| Formelbilder verarbeitet (sicher oder unklar klassifiziert) | 1505 |
| automatisch ersetzt | 942 (63 %) |
| Review: Qwen und Gemma uneinig | 410 |
| Review: GLM weicht ab | 65 |
| Review: Bild-Veto / Pandoc | 2 / 1 |
| keine Formel (laut Modellen) | 85 |
| nicht geprüft (Abbildungen, Symbole) | 539 |
- Von Hand geprüft: die 42 automatisch ersetzten Formeln der festen 50er-Stichprobe und 20 zufällig
gezogene weitere – 62 von 62 Zeichen für Zeichen korrekt (Brüche, Wurzeln mit Index,
cases, Grenzwerte, Integrale, Vektorpfeile, Überstriche über mehreren Buchstaben). - apply an einer Kopie: 946 Ersetzungen in 258 Kapiteldateien (manche Formeln kommen mehrfach vor).
epub2md_merge.py→ 945 Formeln in der Gesamtdatei (eine stand in einer doppelten Fußnote, die das Zusammenfügen entfernt). Pandoc--mathml: 945 von 945 als MathML, keine „Could not convert TeX math“-Meldung. EPUB daraus in 10 s gebaut. - Laufzeit mit beiden lokalen Modellen parallel (zwei RTX 3090) und GLM: ~5 Minuten je 50 Formeln, das Buch also rund 2,5 Stunden.
Grenzen und offene Punkte:
- Mehrzeilige Rechnungen: Rahmen und
&gleicht die Normalform seit 0.4.0 aus; verschiedene Zeilenumbrüche,\underbraceund fehlende Integrationsgrenzen bleiben im Review. - Formeln auf farbig hinterlegten Kästen verlieren beim Ersetzen die Hinterlegung.
- Fettdruck wird nicht geprüft (Vorgabe).
- Die Messung umfasst 2 × 150 Formeln eines Buches ohne Textausschnitt; „0 Fehler“ bedeutet eine Fehlerquote sehr wahrscheinlich unter ~2 %.
- pdf2md-Bücher: am ganzen Corral getestet (ohne
--formulas0.4.0, mit--formulas10 %); Formeln in Tabellen fehlen noch. - Einzelne Riesenausschnitte (Grafiken, dreizeilige Herleitungen mit völlig anderer Lesart) werden ohne Bildvergleich abgelehnt: über 2,5 MP oder mehr als 2,5-fach falsche Proportionen; breite Originale werden für den Vergleich auf 1600 px verkleinert.
Installation
sudo apt install texlive-latex-extra texlive-fonts-extra texlive-science pandoc dvipng
pip install -r requirements.txt # pymupdf, numpy, scipy, scikit-image, opencv, Pillow, lxml, requests
pip install -r requirements-dev.txt # pytest
Modelle: siehe BEDIENUNGSANLEITUNG (llama-server starten).
Tests
python3 -m pytest -q # ca. 45 s; synthetische Bilder, kein Modellserver, keine Buchinhalte
Rückgabecodes: 0 Erfolg, 1 Bedienfehler, 2 Eingabe ist keine epub2md-/pdf2md-Ausgabe,
3 externes Werkzeug fehlt (pdflatex, pandoc, Modellserver), 4 interner Fehler.
Architektur
formula_img2latex/
├── cli.py Unterbefehle, Exit-Codes
├── pipeline.py scan, recognize, verify, Entscheidung (Konsens/Pixel), run in Paketen, apply/revert
├── consensus.py Normalform, Render-Gleichheit: sagen zwei Lesarten dasselbe?
├── decide.py Annahmeregeln und Schwellen (Konsens- und Pixel-Modus)
├── engines/ Vision-Modelle über die OpenAI-API (llama.cpp, OpenRouter), Logprobs, Prompt-Version;
│ p2t.py: pix2text-Formel-OCR (ONNX, CPU/GPU)
├── compare.py Ausrichtung, elastische Verzerrung, Kennzahlen, Kontrasttest, Diff-Bilder
├── confusables.py Verwechslungsvarianten (Pixel-Modus)
├── verify.py Bildprüfung einer Lesart (Veto bzw. Pixel-Entscheider)
├── render.py pdflatex-Batch, Schrift-Presets, Rasterung
├── imageio.py Originale laden (PNG/GIF/JPG/SVG, Transparenz, Tönung)
├── sources/ epub2md.py, pdf2md.py, base.py (Markdown-Scan, Begrenzer, Dezimalkomma)
├── structure.py Strukturvergleich mit sympy (optional, aus)
├── pdfcrop.py Formelbild auf der PDF-Seite finden, 600-dpi-Neuausschnitt
├── classify.py Formel / unklar / Abbildung
├── checks.py Pandoc/MathML-Prüfung
├── calibrate.py Messung an Formelbildern mit bekanntem TeX
├── store.py Arbeitsordner, Datensätze
└── review/ lokaler Review-Server + Seite