Reconnaître le texte dans des images (OCR) en Rust
Créez un programme en ligne de commande Rust qui prend un nom de fichier image et affiche le texte reconnu par Tesseract. Commencez par une image générée contenant un numéro de facture connu, puis essayez votre propre image. Le même programme inclut un traitement optionnel en niveaux de gris et renvoie un code de sortie non nul lorsqu’il ne parvient pas à reconnaître de texte.
Ce tutoriel utilise des fichiers locaux et les données de langue anglaise. Un résultat correct sur l’échantillon vérifie que les liaisons Rust, les bibliothèques natives et le modèle fonctionnent ensemble ; il n’établit pas la précision sur des tickets de caisse, de l’écriture manuscrite ou des mises en page complexes.
Prérequis
- Linux et Bash, avec Rust et Cargo installés.
- Tesseract et Leptonica natifs, y compris leurs en-têtes et bibliothèques de développement.
pkg-config, un compilateur C/C++ et libclang pour les liaisons natives.- Les données de langue anglaise,
eng.traineddata. - ImageMagick 7 et la police Liberation Sans pour générer l’image d’exemple.
L’exemple a été exécuté avec Rust/Cargo 1.98.1, Tesseract 5.5.3, Leptonica 1.87.0 et
ImageMagick 7.1.2-31. Utilisez cette chaîne d’outils pour ce tutoriel. La version minimale de Rust
déclarée par la crate image elle-même est 1.88.0, mais ce n’est pas un minimum testé
pour ce projet complet.
Installer Tesseract
La crate Rust n’installe pas Tesseract elle-même. Suivez le guide d’installation native pour votre distribution et installez les bibliothèques de développement ainsi que le moteur et le modèle anglais.
Sous Ubuntu/Debian, les noms de paquets concernés incluent libtesseract-dev, libleptonica-dev et
tesseract-ocr-eng. Les paquets des distributions peuvent fournir des versions différentes de la chaîne
d’outils testée.
Les instructions exécutables présentées ici couvrent Linux, pas une configuration macOS ou Windows vérifiée. Vérifiez les dépendances natives avant de créer le projet :
rustc --version &&
cargo --version &&
tesseract --version &&
pkg-config --modversion tesseract lept &&
tesseract --list-langs &&
magick -version
La liste des langues doit inclure eng. Si pkg-config ne trouve pas tesseract ou lept, corrigez le
paquet de développement manquant ou son chemin de recherche avant de compiler. La liste des polices
d’ImageMagick (magick -list font) devrait inclure Liberation-Sans.
Configurer le projet
Choisissez un répertoire situé hors d’un espace de travail Cargo existant. Collez ce bloc pour créer
un nouveau projet binaire. Il refuse un répertoire rust-ocr existant et reste dans votre répertoire
d’origine :
(cargo new --bin --edition 2021 --vcs none rust-ocr)
Dans rust-ocr, remplacez l’intégralité de Cargo.toml par :
[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"
La première compilation crée Cargo.lock. Conservez ce fichier avec votre application et utilisez --locked
lors des compilations suivantes afin que Cargo refuse toute modification de la résolution des
dépendances. Les bibliothèques natives et les données de langue sont installées séparément ; le
fichier de verrouillage ne les fige pas.
Implémentation OCR de base
Remplacez rust-ocr/src/main.rs par ce programme complet :
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(())
}
None permet à Tesseract de localiser son répertoire de modèles installé ; Some("eng") sélectionne
explicitement l’anglais. L’API de la liaison charge
l’image avec set_image et renvoie le texte UTF-8 reconnu via get_text. Les erreurs se propagent hors de
main au lieu d’être affichées et traitées comme un succès.
Exécuter le programme sur un texte connu
Depuis le répertoire contenant rust-ocr, collez ce bloc. Son sous-shell laisse votre répertoire de
travail et vos options de shell inchangés, y compris lorsqu’une étape échoue :
(
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
)
Les options d’annotation d’ImageMagick créent un PNG 8 bits opaque et lisible. Dans l’environnement testé, stdout contient :
INVOICE 12345
Cette commande remplace rust-ocr/input.png lors d’une réexécution réussie. Réservez ce nom de fichier à
l’échantillon, et non à une image que vous souhaitez conserver. Si la compilation échoue, la chaîne
&& ne génère pas l’image et n’exécute pas un exécutable plus ancien. Tesseract peut aussi afficher
des diagnostics sur stderr.
Gérer différents formats d’image
Pour tester le traitement en niveaux de gris sur le même échantillon :
(cd rust-ocr && cargo run --quiet --locked -- input.png --grayscale)
Il produit le même texte reconnu. Ce traitement décode le PNG ou le JPEG via image, convertit les
pixels en niveaux de gris et écrit un PNG dans son propre répertoire temporaire sans modifier
l’entrée. Il rejette délibérément les images comportant un canal alpha et les images 16 bits plutôt
que de supprimer silencieusement la transparence ou de modifier les plages de valeurs des
échantillons. Utilisez des images 8 bits opaques et correctement orientées pour ce tutoriel ; les
autres formats et la correction automatique de l’orientation sortent de son cadre.
L’objet TempDir reste en vie jusqu’à la fin de la reconnaissance. Son destructeur tente un nettoyage
aussi bien en cas de succès qu’en cas de retour d’erreur ordinaire. Comme le
documente le code source de tempfile, un arrêt
forcé peut laisser des fichiers derrière lui, et les erreurs de nettoyage du destructeur ne sont pas
signalées. Ce n’est pas une garantie d’effacement sécurisé.
Configuration OCR avancée
Le programme sélectionne PsmSingleBlock, le mode 6 de Tesseract, car l’échantillon forme un seul bloc de
texte. Il ne demande pas de détection de l’orientation et de l’écriture : ce traitement nécessite
donc les données eng, mais pas osd. Choisissez la segmentation en fonction de la mise en page
réelle plutôt que de supposer qu’un seul mode convient à toutes les images ; le
guide de qualité de Tesseract
explique les alternatives.
La conversion en niveaux de gris est une option à comparer, pas une amélioration de précision promise. Tesseract effectue déjà un prétraitement en interne. Les lettres floues, l’inclinaison et le faible contraste nécessitent toujours une meilleure image d’entrée ou un traitement adapté à la tâche. Une liste blanche de caractères exclurait aussi la ponctuation légitime ; l’exemple n’en applique donc pas.
Bonnes pratiques pour l’OCR en Rust
Considérez un code de sortie de réussite du processus comme signifiant uniquement « du texte a été reconnu », et non « le texte est correct ». Comparez les valeurs importantes avec l’image avant de les utiliser. Une entrée vierge est une erreur dans cette CLI, bien qu’un résultat vide puisse être un comportement valide pour un moteur OCR. Essayez-le explicitement :
(
cd rust-ocr &&
magick -size 900x180 xc:white PNG24:blank.png &&
cargo run --quiet --locked -- blank.png
)
Ce bloc remplace l’échantillon blank.png et se termine avec un code non nul et le message
No text recognized. D’autres échecs appellent des solutions différentes :
- Un nom de fichier manquant ou un argument supplémentaire affiche le message d’utilisation. Placez
--grayscaleaprès l’image. - Une image inexistante signale Could not open input image.
- Un échec du décodeur signale Could not decode input image.
- L’absence des données anglaises signale Could not initialize English OCR; check eng.traineddata.
Le décodage n’est pas une vérification de l’intégrité du fichier. Un JPEG endommagé peut tout de même être décodé, en particulier dans le traitement en niveaux de gris, et produire un texte incomplet au lieu d’une erreur de décodeur. Comparez le résultat à l’original ; cette CLI ne certifie pas qu’une image est intacte.
Si le modèle anglais est installé dans un emplacement personnalisé, TESSDATA_PREFIX doit désigner le
répertoire existant contenant eng.traineddata, et non le fichier lui-même. C’est la recherche utilisée par
Tesseract 5.5.3.
Vérifiez le répertoire indiqué par tesseract --list-langs ; une surcharge d’environnement obsolète peut diriger le
programme Rust vers un autre répertoire de modèles.
Gérer plusieurs langues
Cette CLI sélectionne délibérément l’anglais uniquement. Installer des modèles supplémentaires ne modifie pas cette sélection. Tesseract prend en charge les identifiants de langues combinés, mais une application multilingue a aussi besoin de ces modèles et d’images représentatives pour évaluer ses résultats. Consultez la documentation sur la configuration des langues lorsque vous l’étendez ; l’image de test anglaise ne vérifie pas la reconnaissance multilingue.
Conclusion
Pour votre propre image, remplacez input.png dans la commande d’exécution par son nom de fichier, en
mettant entre guillemets les chemins contenant des espaces. Conservez l’image originale afin de
pouvoir y comparer le texte reconnu. Si votre prochaine étape est un flux de travail documentaire
hébergé plutôt qu’une CLI locale, consultez le
service de traitement de documents de Transloadit.
