Text in Bildern erkennen (OCR) mit Rust
Erstellen Sie ein Rust-Kommandozeilenprogramm, das einen Bilddateinamen entgegennimmt und den von Tesseract erkannten Text ausgibt. Beginnen Sie mit einem generierten Bild, das eine bekannte Rechnungsnummer enthält, und testen Sie danach Ihr eigenes Bild. Das Programm bietet außerdem einen optionalen Graustufenpfad und gibt einen Exit-Status ungleich null zurück, wenn es keinen Text erkennen kann.
Diese Anleitung verwendet lokale Dateien und englische Sprachdaten. Ein korrektes Ergebnis beim Beispiel bestätigt, dass die Rust-Bindings, nativen Bibliotheken und das Modell zusammenarbeiten. Es belegt keine Genauigkeit bei Belegen, Handschrift oder komplexen Seitenlayouts.
Voraussetzungen
- Linux und Bash mit installiertem Rust und Cargo.
- Natives Tesseract und Leptonica, einschließlich ihrer Entwicklungsheader und Bibliotheken.
pkg-config, einen C/C++-Compiler und libclang für die nativen Bindings.- Englische Sprachdaten,
eng.traineddata. - ImageMagick 7 und die Schriftart Liberation Sans zum Generieren des Beispielbilds.
Das Beispiel wurde mit Rust/Cargo 1.98.1, Tesseract 5.5.3, Leptonica 1.87.0 und ImageMagick
7.1.2-31 ausgeführt. Verwenden Sie diese Toolchain für diese Anleitung. Die Crate
image selbst deklariert 1.88.0
als Rust-Mindestversion. Diese wurde jedoch nicht als Mindestversion für das gesamte Projekt getestet.
Tesseract installieren
Die Rust-Crate installiert Tesseract nicht selbst. Folgen Sie der nativen Installationsanleitung für Ihre Distribution und installieren Sie neben der Engine und dem englischen Modell auch die Entwicklungsbibliotheken.
Unter Ubuntu/Debian gehören libtesseract-dev, libleptonica-dev und
tesseract-ocr-eng zu den relevanten Paketnamen. Die Pakete Ihrer Distribution können
andere Versionen als die getestete Toolchain bereitstellen.
Die ausführbaren Anweisungen hier gelten für Linux, nicht für eine verifizierte Einrichtung unter macOS oder Windows. Prüfen Sie die nativen Abhängigkeiten, bevor Sie das Projekt erstellen:
rustc --version &&
cargo --version &&
tesseract --version &&
pkg-config --modversion tesseract lept &&
tesseract --list-langs &&
magick -version
Die Sprachliste muss eng enthalten. Wenn pkg-config
tesseract oder lept nicht findet, installieren Sie vor
dem Kompilieren das fehlende Entwicklungspaket oder korrigieren Sie dessen Suchpfad. Die Schriftliste
von ImageMagick (magick -list font) sollte Liberation-Sans enthalten.
Projekt einrichten
Wählen Sie ein Verzeichnis außerhalb eines bestehenden Cargo-Workspaces. Fügen Sie diesen Block ein,
um ein neues Projekt für ein ausführbares Programm zu erstellen. Der Block verweigert die Ausführung,
wenn das Verzeichnis rust-ocr bereits existiert, und verbleibt in Ihrem
ursprünglichen Verzeichnis:
(cargo new --bin --edition 2021 --vcs none rust-ocr)
Ersetzen Sie in rust-ocr die gesamte Datei Cargo.toml durch:
[package]
name = "rust-ocr"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "=1.0.104"
image = { version = "=0.25.10", default-features = false, features = ["jpeg", "png"] }
tempfile = "=3.27.0"
tesseract = "=0.15.2"
Der erste Build erstellt Cargo.lock. Bewahren Sie die Datei mit Ihrer Anwendung
auf und verwenden Sie bei späteren Builds --locked, damit Cargo Änderungen an
der Abhängigkeitsauflösung ablehnt. Die nativen Bibliotheken und Sprachdaten werden separat
installiert; die Lockdatei fixiert deren Versionen nicht.
Grundlegende OCR-Implementierung
Ersetzen Sie rust-ocr/src/main.rs durch dieses vollständige Programm:
use std::path::PathBuf;
use anyhow::{bail, ensure, Context, Result};
use tesseract::{PageSegMode, Tesseract};
const USAGE: &str = "Usage: rust-ocr <image> [--grayscale]";
fn main() -> Result<()> {
let mut arguments = std::env::args_os().skip(1);
let input = PathBuf::from(arguments.next().context(USAGE)?);
let grayscale = match arguments.next() {
None => false,
Some(flag) if flag == "--grayscale" => true,
_ => bail!(USAGE),
};
ensure!(arguments.next().is_none(), USAGE);
let input = input.canonicalize().context("Could not open input image")?;
let temporary_directory = if grayscale {
Some(tempfile::tempdir().context("Could not create temporary directory")?)
} else {
None
};
let image_path = match &temporary_directory {
Some(directory) => {
let decoded = image::open(&input).context("Could not decode input image")?;
ensure!(
matches!(decoded.color(), image::ColorType::L8 | image::ColorType::Rgb8),
"Grayscale mode requires opaque 8-bit PNG or JPEG"
);
let processed = directory.path().join("processed.png");
decoded.grayscale().save(&processed)
.context("Could not write grayscale image")?;
processed.canonicalize().context("Could not resolve temporary image")?
}
None => input,
};
let filename = image_path.to_str().context("Image path must be valid UTF-8")?;
let mut ocr = Tesseract::new(None, Some("eng"))
.context("Could not initialize English OCR; check eng.traineddata")?
.set_image(filename)
.context("Could not decode input image")?;
ocr.set_page_seg_mode(PageSegMode::PsmSingleBlock);
let text = ocr.get_text().context("Recognition failed")?;
ensure!(!text.trim().is_empty(), "No text recognized");
print!("{text}");
Ok(())
}
Mit None kann Tesseract sein installiertes Modellverzeichnis finden;
Some("eng") wählt explizit Englisch aus. Die
Binding-API lädt das Bild mit set_image
und gibt erkannten UTF-8-Text über get_text zurück. Fehler werden aus
main weitergereicht, statt nur ausgegeben und als Erfolg behandelt zu werden.
Mit bekanntem Text ausführen
Fügen Sie diesen Block im Verzeichnis ein, das rust-ocr enthält. Seine Subshell
lässt Ihr Arbeitsverzeichnis und Ihre Shell-Optionen unverändert, auch wenn ein Schritt fehlschlägt:
(
cd rust-ocr &&
cargo build &&
magick -size 900x180 xc:white -font Liberation-Sans -pointsize 64 \
-fill black -gravity center -annotate +0+0 'INVOICE 12345' PNG24:input.png &&
cargo run --quiet --locked -- input.png
)
Die Annotationsoptionen von ImageMagick erstellen ein lesbares, opakes 8-Bit-PNG. In der getesteten Umgebung enthält stdout:
INVOICE 12345
Dieser Befehl ersetzt rust-ocr/input.png bei einer erfolgreichen erneuten Ausführung.
Reservieren Sie diesen Dateinamen für das Beispiel, nicht für ein Bild, das Sie behalten möchten.
Wenn der Build fehlschlägt, generiert die Kette mit && weder das Bild noch
führt sie eine ältere ausführbare Datei aus. Tesseract kann außerdem Diagnosemeldungen auf stderr
ausgeben.
Verschiedene Bildformate verarbeiten
So testen Sie den Graustufenpfad mit demselben Beispiel:
(cd rust-ocr && cargo run --quiet --locked -- input.png --grayscale)
Er liefert denselben erkannten Text. Dieser Pfad decodiert PNG oder JPEG mit
image, wandelt die Pixel in Graustufen um und schreibt ein PNG in ein eigenes
temporäres Verzeichnis, ohne die Eingabe zu verändern. Er lehnt Bilder mit Alphakanal und
16-Bit-Bilder bewusst ab, statt stillschweigend Transparenz zu verwerfen oder Wertebereiche zu
verändern. Verwenden Sie für diese Anleitung aufrechte, opake 8-Bit-Bilder; andere Formate und eine
automatische Ausrichtungskorrektur liegen außerhalb ihres Umfangs.
Das Objekt TempDir bleibt bis zum Abschluss der Erkennung bestehen.
Sein Destruktor versucht sowohl bei Erfolg als auch bei regulären Fehlerrückgaben aufzuräumen.
Wie im Quellcode von tempfile dokumentiert, kann eine erzwungene
Beendigung Dateien zurücklassen. Fehler beim Aufräumen durch den Destruktor werden nicht gemeldet.
Dies ist keine Garantie für sicheres Löschen.
Erweiterte OCR-Konfiguration
Das Programm wählt PsmSingleBlock, den Modus 6 von Tesseract, da das Beispiel aus
einem Textblock besteht. Es fordert keine Erkennung der Ausrichtung oder des Schriftsystems an.
Daher benötigt dieser Pfad die Daten eng, aber nicht
osd. Wählen Sie die Segmentierung anhand des tatsächlichen Layouts,
statt anzunehmen, dass ein Modus zu allen Bildern passt. Der
Qualitätsleitfaden von Tesseract erläutert die Alternativen.
Die Graustufenumwandlung ist eine Option zum Vergleichen, keine zugesicherte Verbesserung der Genauigkeit. Tesseract führt intern bereits eine Vorverarbeitung durch. Unscharfe Buchstaben, Schräglagen und geringer Kontrast erfordern weiterhin bessere Eingaben oder eine aufgabenspezifische Verarbeitung. Eine Positivliste für Zeichen würde auch zulässige Satzzeichen ausschließen, daher verwendet das Beispiel keine solche Liste.
Bewährte Verfahren für OCR in Rust
Verstehen Sie eine erfolgreiche Beendigung als „es wurde Text erkannt“, nicht als „der Text ist korrekt“. Gleichen Sie wichtige Werte mit dem Bild ab, bevor Sie sie verwenden. Eine leere Eingabe ist in dieser CLI ein Fehler, obwohl ein leeres Ergebnis für eine OCR-Engine gültiges Verhalten sein kann. Testen Sie dies explizit:
(
cd rust-ocr &&
magick -size 900x180 xc:white PNG24:blank.png &&
cargo run --quiet --locked -- blank.png
)
Dieser Block ersetzt das Beispiel blank.png und endet mit einem Exit-Status
ungleich null sowie der Meldung No text recognized.
Andere Fehler erfordern andere Maßnahmen:
- Bei fehlendem Dateinamen oder einem zusätzlichen Argument erscheint der Verwendungshinweis.
Setzen Sie
--grayscalehinter das Bild. - Bei einem nicht vorhandenen Bild erscheint Could not open input image.
- Bei einem Decoderfehler erscheint Could not decode input image.
- Bei fehlenden englischen Sprachdaten erscheint Could not initialize English OCR; check eng.traineddata.
Das Decodieren ist keine Prüfung der Dateiintegrität. Ein beschädigtes JPEG lässt sich möglicherweise trotzdem decodieren, insbesondere im Graustufenpfad, und liefert unvollständigen Text statt eines Decoderfehlers. Vergleichen Sie das Ergebnis mit dem Original; diese CLI bestätigt nicht, dass ein Bild unbeschädigt ist.
Wenn das englische Modell an einem benutzerdefinierten Speicherort installiert ist, muss
TESSDATA_PREFIX das vorhandene Verzeichnis mit eng.traineddata
bezeichnen, nicht die Datei selbst. Dies ist das Suchverfahren von
Tesseract 5.5.3. Prüfen Sie das von
tesseract --list-langs aufgeführte Verzeichnis; eine veraltete Umgebungsvariable kann das
Rust-Programm auf ein anderes Modellverzeichnis verweisen lassen.
Mehrere Sprachen verarbeiten
Diese CLI wählt bewusst nur Englisch aus. Die Installation weiterer Modelle ändert diese Auswahl nicht. Tesseract unterstützt kombinierte Sprachkennungen, doch eine mehrsprachige Anwendung benötigt auch diese Modelle und repräsentative Bilder, um ihre Ergebnisse zu bewerten. Ziehen Sie bei einer Erweiterung die Dokumentation zur Sprachkonfiguration heran; die englische Fixture verifiziert keine mehrsprachige Erkennung.
Fazit
Für Ihr eigenes Bild ersetzen Sie input.png im Ausführungsbefehl durch dessen
Dateinamen. Setzen Sie Pfade mit Leerzeichen in Anführungszeichen. Bewahren Sie das Originalbild auf,
um den erkannten Text damit vergleichen zu können. Wenn Ihr nächster Schritt ein gehosteter
Dokumentenworkflow statt einer lokalen CLI ist, sehen Sie sich den
Dienst zur Dokumentenverarbeitung von Transloadit an.
