Migration de Charlesw Tesseract vers IronOcr
Ce guide guide les développeurs .NET à travers la migration à partir du paquet NuGet charlesw/tesseract (Tesseract) vers IronOCR. La migration se concentre sur un problème spécifique : le modèle de déploiement binaire natif que le wrapper charlesw impose et le code conditionnel à la plateforme que ce modèle oblige les développeurs à écrire. Les équipes qui ont lutté DllNotFoundException dans CI, se sont battues avec les chemins de la bibliothèque Leptonica sous Linux, ou ont écrit des blocs de détection de système d'exploitation qui n'ont rien à voir avec l'OCR trouveront que ce guide montre exactement ce qui disparaît après le changement.
Pourquoi migrer depuis Charlesw Tesseract
Le paquet archivé charlesw/tesseract met les nouveaux projets en difficulté non pas parce que l'API est mauvaise, mais parce que le modèle de déploiement qu'il nécessite a été conçu autour d'hypothèses qui ne tiennent pas dans l'infrastructure moderne de .NET. Voici les facteurs qui déterminent les décisions de migration :
Déploiement binaire natif par plateforme. Le paquet NuGet Tesseract distribue des binaires natifs spécifiques à la plateforme : tesseract50.dll pour Windows x64, une version distincte pour x86, libtesseract.so pour Linux x64. Ces binaires doivent se retrouver au bon endroit à l'exécution pour que les appels P/Invoke réussissent. Sur un poste de travail de développeur, le SDK les copie automatiquement. Dans un conteneur Docker, un agent de construction ARM64 ou un service d'application Azure avec une racine d'application non standard, ce n'est pas le cas. Chaque nouvelle cible de déploiement devient une session de débogage.
Leptonica comme dépendance cachée. Le chargement des images dans Tesseract est géré par la bibliothèque Leptonica, fournie sous forme de DLL natives distinctes, en plus des binaires de Tesseract. Sur Windows, leptonica-1.82.0.dll doit être présent dans le répertoire de sortie. Sous Linux, la bibliothèque partagée Leptonica doit être soit intégrée au système, soit installée en tant que paquet système. Les images Docker basées sur Debian sans libleptonica-dev échouent à Pix.LoadFromFile() avec une exception native peu utile, et le corriger nécessite de savoir quel paquet système résout la dépendance.
Code conditionnel à la plateforme dans la logique de l'application. La combinaison du chargement binaire natif et de la résolution du chemin tessdata force les développeurs à écrire des vérifications RuntimeInformation.IsOSPlatform(), à détecter les variables d'environnement pour les contextes de conteneurs, et à créer une logique de construction de chemin qui varie selon la cible. Ce code ne contient aucune logique OCR. Il s'agit d'une infrastructure de déploiement qui existe uniquement parce que la gestion binaire du paquet est incomplète.
Paquet archivé sans possibilité de mise à jour. Ce dépôt est archivé depuis 2021. Lorsqu'une mise à jour système sur un hôte Linux modifie l'ABI Leptonica, ou lorsqu'une nouvelle version du runtime .NET modifie le comportement de chargement des binaires natifs, aucune version de mise à jour n'est disponible. Les seules options sont de dupliquer le pipeline de compilation natif ou de remplacer la bibliothèque.
Gel du moteur Tesseract 4.1.1. Ce package contient Tesseract 4.1.1. Le modèle LSTM réécrit de Tesseract 5 offre une précision nettement supérieure sur les documents dégradés. Cette mise à jour n'est pas disponible via le paquet charlesw ; elle nécessite un changement de bibliothèque.
Gestion de la confiance sans modèle standard. Le wrapper charlesw expose page.GetMeanConfidence() comme un flottant entre 0 et 1, mais l'application de seuils de confiance au niveau des mots ou des caractères nécessite le modèle d'itérateur avec iter.GetConfidence(PageIteratorLevel.Word). Il n'existe pas d'API de filtrage standard ; Chaque équipe met en œuvre sa propre logique de seuil différemment.
Le problème fondamental
Le wrapper charlesw nécessite une configuration binaire native spécifique à la plateforme avant que la reconnaissance optique de caractères (OCR) puisse s'exécuter :
// charlesw Tesseract: OS detection required just to find native DLLs
// DllNotFoundException on any platform where binaries do not resolve
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", "/app/lib");
}
var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var img = Pix.LoadFromFile(imagePath); // Requires leptonica native DLL
using var page = engine.Process(img);
return page.GetText();
// charlesw Tesseract: OS detection required just to find native DLLs
// DllNotFoundException on any platform where binaries do not resolve
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", "/app/lib");
}
var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var img = Pix.LoadFromFile(imagePath); // Requires leptonica native DLL
using var page = engine.Process(img);
return page.GetText();
Imports System
Imports System.Runtime.InteropServices
Imports Tesseract
' charlesw Tesseract: OS detection required just to find native DLLs
' DllNotFoundException on any platform where binaries do not resolve
If RuntimeInformation.IsOSPlatform(OSPlatform.Linux) Then
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", "/app/lib")
End If
Dim engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
Using img As Pix = Pix.LoadFromFile(imagePath) ' Requires leptonica native DLL
Using page As Page = engine.Process(img)
Return page.GetText()
End Using
End Using
IronOCR ne possède pas de configuration binaire native :
// IronOCR: no path management, no OS detection, no leptonica dependency
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read(imagePath).Text;
// IronOCR: no path management, no OS detection, no leptonica dependency
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read(imagePath).Text;
' IronOCR: no path management, no OS detection, no leptonica dependency
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text As String = New IronTesseract().Read(imagePath).Text
IronOCR vs Charlesw Tesseract : Comparaison des fonctionnalités
Le tableau suivant récapitule les fonctionnalités pertinentes pour les équipes évaluant cette migration :
| Fonction | Tesseract de Charles | IronOCR |
|---|---|---|
| État de la maintenance | Archivé (aucune mise à jour depuis 2021) | Maintenance active |
| version du moteur Tesseract | 4.1.1 (gelé) | 5 (actuel, optimisé) |
| Licence | Apache 2.0 (gratuit) | Commercial ($999–2 999 $ perpétuel) |
| Installation de NuGet | Tesseract |
IronOcr |
| Gestion des binaires natifs | Déploiement manuel des DLL par plateforme | Intégré, aucune configuration requise |
| dépendance à Leptonica | Nécessite leptonica-1.82.0.dll / libleptonica-dev |
Sans objet (traité en interne) |
| Gestion de Tessdata | Téléchargement manuel et entrée de copie .csproj |
Packs de langue NuGet |
| Code conditionnel à la plateforme | Nécessaire pour le déploiement multi-cibles | Non requis |
| Déploiement Docker | Nécessite un COPY tessdata explicite + Leptonica apt-get |
Configuration requise pour les conteneurs .NET standard uniquement |
| Prise en charge ARM64 | Archives non confirmées | Regroupé, validé |
| Formats d'entrée d'image | TIFF, PNG, BMP, JPG (via Leptonica) | JPG, PNG, BMP, TIFF, GIF et plus encore |
| TIFF multipage | Itération manuelle du cadre | input.LoadImageFrames() |
| Entrée PDF native | Non (nécessite une bibliothèque secondaire) | Oui |
| Sortie PDF consultable | Non | Oui (result.SaveAsSearchablePdf()) |
| Prétraitement intégré | None | Redresser, réduire le bruit, contraster, binariser, accentuer, mettre à l'échelle, dilater, éroder, inverser |
| API de filtrage de confiance | Itérateur manuel avec GetConfidence() |
result.Confidence, word.Confidence |
| Résultats structurés | Modèle d'itérateur (ResultIterator) |
Collections directes (Pages, Paragraphes, Lignes, Mots) |
| Lecture de codes-barres | Non | Oui (lors du passage de l'OCR) |
| OCR basé sur la région | Non | Oui (CropRectangle) |
| Sécurité des threads | Responsabilité de l'appelant | Intégré |
| Plus de 125 packs de langues | Téléchargements manuels de tessdata | dotnet add package IronOcr.Languages.* |
| .NET multiplateforme | Oui (.NET Standard 2.0) | Oui (.NET Framework 4.6.2+, .NET 5/6/7/8/9) |
| Fréquence des correctifs de sécurité | Aucun (archivé) | Publications régulières |
Démarrage rapide : Migration de Tesseract de Charles vers IronOCR
Étape 1 : Remplacer le package NuGet
Supprimez le paquet charlesw Tesseract :
dotnet remove package Tesseract
dotnet remove package Tesseract
Installez IronOCR depuis NuGet :
dotnet add package IronOcr
Étape 2 : Mise à jour des espaces de noms
// Before (charlesw Tesseract)
using Tesseract;
// After (IronOCR)
using IronOcr;
// Before (charlesw Tesseract)
using Tesseract;
// After (IronOCR)
using IronOcr;
Imports IronOcr
Étape 3 : initialisation de la licence
Ajoutez cet appel une seule fois au démarrage de l'application, avant toute opération OCR :
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Une licence d'essai gratuite est disponible sur la page de licences d' IronOCR . La version d'essai supprime le filigrane des données de sortie et active l'accès complet à l'API.
Exemples de migration de code
Suppression de la configuration du chemin binaire natif
Le modèle d'initialisation le plus courant dans les projets charlesw/tesseract est une classe fabrique ou une classe d'assistance qui construit le chemin tessdata et configure le chargement de la bibliothèque native en fonction de l'environnement. Ce code existe uniquement en raison du modèle de déploiement du wrapper.
Approche du tesseract de Charles :
// A realistic factory found in production charlesw/Tesseract projects
public static class OcrEngineFactory
{
private static string GetTessDataPath()
{
// Different path per environment — all wrong until explicitly configured
if (Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true")
return "/app/tessdata"; // Docker
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return Path.Combine(AppContext.BaseDirectory, "tessdata"); // Linux bare metal
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return "/usr/local/share/tessdata"; // macOS Homebrew install
return @".\tessdata"; // Windows dev machine
}
public static TesseractEngine Create(string language = "eng")
{
// If leptonica-1.82.0.dll is not in output directory: DllNotFoundException at this line
// If tessdata folder is missing: TesseractException at engine construction
return new TesseractEngine(GetTessDataPath(), language, EngineMode.Default);
}
}
// Call site
using var engine = OcrEngineFactory.Create();
using var img = Pix.LoadFromFile("invoice.jpg");
using var page = engine.Process(img);
Console.WriteLine(page.GetText());
// A realistic factory found in production charlesw/Tesseract projects
public static class OcrEngineFactory
{
private static string GetTessDataPath()
{
// Different path per environment — all wrong until explicitly configured
if (Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true")
return "/app/tessdata"; // Docker
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return Path.Combine(AppContext.BaseDirectory, "tessdata"); // Linux bare metal
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
return "/usr/local/share/tessdata"; // macOS Homebrew install
return @".\tessdata"; // Windows dev machine
}
public static TesseractEngine Create(string language = "eng")
{
// If leptonica-1.82.0.dll is not in output directory: DllNotFoundException at this line
// If tessdata folder is missing: TesseractException at engine construction
return new TesseractEngine(GetTessDataPath(), language, EngineMode.Default);
}
}
// Call site
using var engine = OcrEngineFactory.Create();
using var img = Pix.LoadFromFile("invoice.jpg");
using var page = engine.Process(img);
Console.WriteLine(page.GetText());
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports Tesseract
Public Module OcrEngineFactory
Private Function GetTessDataPath() As String
' Different path per environment — all wrong until explicitly configured
If Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") = "true" Then
Return "/app/tessdata" ' Docker
End If
If RuntimeInformation.IsOSPlatform(OSPlatform.Linux) Then
Return Path.Combine(AppContext.BaseDirectory, "tessdata") ' Linux bare metal
End If
If RuntimeInformation.IsOSPlatform(OSPlatform.OSX) Then
Return "/usr/local/share/tessdata" ' macOS Homebrew install
End If
Return ".\tessdata" ' Windows dev machine
End Function
Public Function Create(Optional language As String = "eng") As TesseractEngine
' If leptonica-1.82.0.dll is not in output directory: DllNotFoundException at this line
' If tessdata folder is missing: TesseractException at engine construction
Return New TesseractEngine(GetTessDataPath(), language, EngineMode.Default)
End Function
End Module
' Call site
Using engine As TesseractEngine = OcrEngineFactory.Create()
Using img As Pix = Pix.LoadFromFile("invoice.jpg")
Using page As Page = engine.Process(img)
Console.WriteLine(page.GetText())
End Using
End Using
End Using
Approche IronOCR :
// IronOCR: no factory, no path logic, no OS detection
// Runs identically on Windows, Linux, macOS, and ARM64
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var result = new IronTesseract().Read("invoice.jpg");
Console.WriteLine(result.Text);
// IronOCR: no factory, no path logic, no OS detection
// Runs identically on Windows, Linux, macOS, and ARM64
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var result = new IronTesseract().Read("invoice.jpg");
Console.WriteLine(result.Text);
' IronOCR: no factory, no path logic, no OS detection
' Runs identically on Windows, Linux, macOS, and ARM64
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim result = New IronTesseract().Read("invoice.jpg")
Console.WriteLine(result.Text)
La classe entière OcrEngineFactory est supprimée. La logique de chemin conditionnel à la plateforme, la vérification DOTNET_RUNNING_IN_CONTAINER, et la dépendance à la DLL Leptonica disparaissent toutes avec elle. Chaque environnement (poste de travail de développeur, agent CI, conteneur Docker, VM cloud) exécute les mêmes deux lignes. Le guide d'installation d'IronTesseract aborde les options de configuration lorsque les valeurs par défaut doivent être ajustées, mais pour la plupart des déploiements, aucune n'est nécessaire.
Remplacement de conversion d'image Leptonica
Le wrapper charlesw utilise le type Pix de Leptonica comme sa représentation d'image. Tout code qui manipule des images avant l'OCR doit passer par Pix, ce qui nécessite que la DLL native Leptonica soit chargée et opérationnelle. Remplacer ce modèle par OcrInput élimine entièrement la dépendance à Leptonica.
Approche du tesseract de Charles :
// Pix is Leptonica's image type — requires leptonica native DLL
// Converting from System.Drawing.Bitmap requires a temp file round-trip
public string ProcessInMemoryImage(Bitmap bitmap)
{
// Non direct Bitmap → Pix conversion; must write to temp file
var tempPath = Path.Combine(Path.GetTempPath(), $"ocr_{Guid.NewGuid()}.png");
try
{
bitmap.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png);
using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var pix = Pix.LoadFromFile(tempPath); // Leptonica file I/O
using var page = engine.Process(pix);
return page.GetText();
}
finally
{
if (File.Exists(tempPath)) File.Delete(tempPath);
}
}
// Pix is Leptonica's image type — requires leptonica native DLL
// Converting from System.Drawing.Bitmap requires a temp file round-trip
public string ProcessInMemoryImage(Bitmap bitmap)
{
// Non direct Bitmap → Pix conversion; must write to temp file
var tempPath = Path.Combine(Path.GetTempPath(), $"ocr_{Guid.NewGuid()}.png");
try
{
bitmap.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png);
using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var pix = Pix.LoadFromFile(tempPath); // Leptonica file I/O
using var page = engine.Process(pix);
return page.GetText();
}
finally
{
if (File.Exists(tempPath)) File.Delete(tempPath);
}
}
Imports System
Imports System.Drawing
Imports System.IO
Imports Tesseract
Public Class ImageProcessor
' Pix is Leptonica's image type — requires leptonica native DLL
' Converting from System.Drawing.Bitmap requires a temp file round-trip
Public Function ProcessInMemoryImage(bitmap As Bitmap) As String
' Non direct Bitmap → Pix conversion; must write to temp file
Dim tempPath As String = Path.Combine(Path.GetTempPath(), $"ocr_{Guid.NewGuid()}.png")
Try
bitmap.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png)
Using engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
Using pix As Pix = Pix.LoadFromFile(tempPath) ' Leptonica file I/O
Using page As Page = engine.Process(pix)
Return page.GetText()
End Using
End Using
End Using
Finally
If File.Exists(tempPath) Then File.Delete(tempPath)
End Try
End Function
End Class
Approche IronOCR :
// OcrInput accepts byte arrays and streams — no temp file, no Leptonica
public string ProcessInMemoryImage(byte[] imageBytes)
{
using var input = new OcrInput();
input.LoadImage(imageBytes); // Direct byte array loading
var result = new IronTesseract().Read(input);
return result.Text;
}
// Or from a stream — same pattern
public string ProcessFromStream(Stream imageStream)
{
using var input = new OcrInput();
input.LoadImage(imageStream);
var result = new IronTesseract().Read(input);
return result.Text;
}
// OcrInput accepts byte arrays and streams — no temp file, no Leptonica
public string ProcessInMemoryImage(byte[] imageBytes)
{
using var input = new OcrInput();
input.LoadImage(imageBytes); // Direct byte array loading
var result = new IronTesseract().Read(input);
return result.Text;
}
// Or from a stream — same pattern
public string ProcessFromStream(Stream imageStream)
{
using var input = new OcrInput();
input.LoadImage(imageStream);
var result = new IronTesseract().Read(input);
return result.Text;
}
Imports System.IO
' OcrInput accepts byte arrays and streams — no temp file, no Leptonica
Public Function ProcessInMemoryImage(imageBytes As Byte()) As String
Using input As New OcrInput()
input.LoadImage(imageBytes) ' Direct byte array loading
Dim result = New IronTesseract().Read(input)
Return result.Text
End Using
End Function
' Or from a stream — same pattern
Public Function ProcessFromStream(imageStream As Stream) As String
Using input As New OcrInput()
input.LoadImage(imageStream)
Dim result = New IronTesseract().Read(input)
Return result.Text
End Using
End Function
Le fichier temporaire fait l'aller-retour. Aucun fichier n'est écrit sur le disque, aucune DLL Leptonica n'est invoquée pour la conversion, et il n'y a pas de bloc finally à nettoyer. Le guide d'entrée d'image et le guide d'entrée de flux documentent toutes les sources d'entrée prises en charge, y compris le chargement à partir d'URL et de fichiers mappés en mémoire.
Filtrage par seuil de confiance
Le wrapper charlesw expose la confiance à deux niveaux : page.GetMeanConfidence() pour toute la page et iter.GetConfidence(PageIteratorLevel.Word) pour les mots individuels. Le filtrage des mots à faible confiance dans le résultat nécessite la gestion manuelle d'une boucle d'itération. IronOCR expose directement le niveau de confiance sur les objets de résultat, faisant de la logique de seuil une expression LINQ.
Approche du tesseract de Charles :
// Word-level confidence filtering requires iterator boilerplate
public List<string> ExtractHighConfidenceWords(string imagePath, float minConfidence = 0.8f)
{
var highConfidenceWords = new List<string>();
using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var img = Pix.LoadFromFile(imagePath);
using var page = engine.Process(img);
// Page-level confidence only: fine-grained requires the iterator
Console.WriteLine($"Page confidence: {page.GetMeanConfidence():P1}");
using var iter = page.GetIterator();
iter.Begin();
do
{
if (iter.IsAtBeginningOf(PageIteratorLevel.Word))
{
var wordText = iter.GetText(PageIteratorLevel.Word)?.Trim();
var wordConf = iter.GetConfidence(PageIteratorLevel.Word) / 100f; // Returns 0-100
if (!string.IsNullOrEmpty(wordText) && wordConf >= minConfidence)
highConfidenceWords.Add(wordText);
}
} while (iter.Next(PageIteratorLevel.Para, PageIteratorLevel.Word));
return highConfidenceWords;
}
// Word-level confidence filtering requires iterator boilerplate
public List<string> ExtractHighConfidenceWords(string imagePath, float minConfidence = 0.8f)
{
var highConfidenceWords = new List<string>();
using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var img = Pix.LoadFromFile(imagePath);
using var page = engine.Process(img);
// Page-level confidence only: fine-grained requires the iterator
Console.WriteLine($"Page confidence: {page.GetMeanConfidence():P1}");
using var iter = page.GetIterator();
iter.Begin();
do
{
if (iter.IsAtBeginningOf(PageIteratorLevel.Word))
{
var wordText = iter.GetText(PageIteratorLevel.Word)?.Trim();
var wordConf = iter.GetConfidence(PageIteratorLevel.Word) / 100f; // Returns 0-100
if (!string.IsNullOrEmpty(wordText) && wordConf >= minConfidence)
highConfidenceWords.Add(wordText);
}
} while (iter.Next(PageIteratorLevel.Para, PageIteratorLevel.Word));
return highConfidenceWords;
}
Imports System
Imports Tesseract
Public Class WordExtractor
Public Function ExtractHighConfidenceWords(imagePath As String, Optional minConfidence As Single = 0.8F) As List(Of String)
Dim highConfidenceWords As New List(Of String)()
Using engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
Using img As Pix = Pix.LoadFromFile(imagePath)
Using page As Page = engine.Process(img)
' Page-level confidence only: fine-grained requires the iterator
Console.WriteLine($"Page confidence: {page.GetMeanConfidence():P1}")
Using iter As ResultIterator = page.GetIterator()
iter.Begin()
Do
If iter.IsAtBeginningOf(PageIteratorLevel.Word) Then
Dim wordText As String = iter.GetText(PageIteratorLevel.Word)?.Trim()
Dim wordConf As Single = iter.GetConfidence(PageIteratorLevel.Word) / 100.0F ' Returns 0-100
If Not String.IsNullOrEmpty(wordText) AndAlso wordConf >= minConfidence Then
highConfidenceWords.Add(wordText)
End If
End If
Loop While iter.Next(PageIteratorLevel.Para, PageIteratorLevel.Word)
End Using
End Using
End Using
End Using
Return highConfidenceWords
End Function
End Class
Approche IronOCR :
// Confidence is a property on each result object — no iterator required
public List<string> ExtractHighConfidenceWords(string imagePath, double minConfidence = 80.0)
{
var result = new IronTesseract().Read(imagePath);
Console.WriteLine($"Page confidence: {result.Confidence}%");
// LINQ directly on the word collection — no iterator state management
return result.Pages
.SelectMany(p => p.Lines)
.SelectMany(l => l.Words)
.Where(w => w.Confidence >= minConfidence && !string.IsNullOrWhiteSpace(w.Text))
.Select(w => w.Text)
.ToList();
}
// Confidence is a property on each result object — no iterator required
public List<string> ExtractHighConfidenceWords(string imagePath, double minConfidence = 80.0)
{
var result = new IronTesseract().Read(imagePath);
Console.WriteLine($"Page confidence: {result.Confidence}%");
// LINQ directly on the word collection — no iterator state management
return result.Pages
.SelectMany(p => p.Lines)
.SelectMany(l => l.Words)
.Where(w => w.Confidence >= minConfidence && !string.IsNullOrWhiteSpace(w.Text))
.Select(w => w.Text)
.ToList();
}
Imports System
Imports System.Collections.Generic
Imports System.Linq
Public Function ExtractHighConfidenceWords(imagePath As String, Optional minConfidence As Double = 80.0) As List(Of String)
Dim result = New IronTesseract().Read(imagePath)
Console.WriteLine($"Page confidence: {result.Confidence}%")
' LINQ directly on the word collection — no iterator state management
Return result.Pages _
.SelectMany(Function(p) p.Lines) _
.SelectMany(Function(l) l.Words) _
.Where(Function(w) w.Confidence >= minConfidence AndAlso Not String.IsNullOrWhiteSpace(w.Text)) _
.Select(Function(w) w.Text) _
.ToList()
End Function
La machine à états itérateurs a disparu. Les valeurs de confiance dans IronOCR sont systématiquement sur une échelle de 0 à 100, aucune division par 100 n'est nécessaire. Le guide des scores de confiance couvre les modèles d'accès à la confiance par mot, par ligne et par page. Le guide de lecture des résultats explique comment naviguer dans l'intégralité de la hiérarchie structurée des résultats.
Traitement par lots TIFF multipages
Les fichiers TIFF à images multiples sont courants dans les flux de travail de numérisation de documents. Le wrapper charlesw ne prend pas en charge les formats TIFF multi-images intégrés ; Chaque image doit être extraite manuellement avant traitement. IronOCR gère nativement les fichiers TIFF multi-images avec un seul appel de chargement.
Approche du tesseract de Charles :
// charlesw/Tesseract has no multi-frame TIFF support
// Each frame must be extracted via System.Drawing before OCR can run
public string ProcessMultiFrameTiff(string tiffPath)
{
var fullText = new StringBuilder();
using var tiffImage = Image.FromFile(tiffPath);
var frameCount = tiffImage.GetFrameCount(FrameDimension.Page);
using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
for (int i = 0; i < frameCount; i++)
{
tiffImage.SelectActiveFrame(FrameDimension.Page, i);
// Must save each frame as a temp file for Pix to load
var tempPath = Path.Combine(Path.GetTempPath(), $"tiff_frame_{i}.png");
try
{
tiffImage.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png);
using var pix = Pix.LoadFromFile(tempPath);
using var page = engine.Process(pix);
fullText.AppendLine(page.GetText());
}
finally
{
if (File.Exists(tempPath)) File.Delete(tempPath);
}
}
return fullText.ToString();
}
// charlesw/Tesseract has no multi-frame TIFF support
// Each frame must be extracted via System.Drawing before OCR can run
public string ProcessMultiFrameTiff(string tiffPath)
{
var fullText = new StringBuilder();
using var tiffImage = Image.FromFile(tiffPath);
var frameCount = tiffImage.GetFrameCount(FrameDimension.Page);
using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
for (int i = 0; i < frameCount; i++)
{
tiffImage.SelectActiveFrame(FrameDimension.Page, i);
// Must save each frame as a temp file for Pix to load
var tempPath = Path.Combine(Path.GetTempPath(), $"tiff_frame_{i}.png");
try
{
tiffImage.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png);
using var pix = Pix.LoadFromFile(tempPath);
using var page = engine.Process(pix);
fullText.AppendLine(page.GetText());
}
finally
{
if (File.Exists(tempPath)) File.Delete(tempPath);
}
}
return fullText.ToString();
}
Imports System.Drawing
Imports System.Drawing.Imaging
Imports Tesseract
Imports System.IO
Imports System.Text
Public Function ProcessMultiFrameTiff(tiffPath As String) As String
Dim fullText As New StringBuilder()
Using tiffImage As Image = Image.FromFile(tiffPath)
Dim frameCount As Integer = tiffImage.GetFrameCount(FrameDimension.Page)
Using engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
For i As Integer = 0 To frameCount - 1
tiffImage.SelectActiveFrame(FrameDimension.Page, i)
' Must save each frame as a temp file for Pix to load
Dim tempPath As String = Path.Combine(Path.GetTempPath(), $"tiff_frame_{i}.png")
Try
tiffImage.Save(tempPath, Imaging.ImageFormat.Png)
Using pix As Pix = Pix.LoadFromFile(tempPath)
Using page As Page = engine.Process(pix)
fullText.AppendLine(page.GetText())
End Using
End Using
Finally
If File.Exists(tempPath) Then File.Delete(tempPath)
End Try
Next
End Using
End Using
Return fullText.ToString()
End Function
Approche IronOCR :
// LoadImageFrames handles multi-frame TIFFs natively — no frame extraction loop
public string ProcessMultiFrameTiff(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // All frames loaded in one call
var result = new IronTesseract().Read(input);
// Pages maps directly to TIFF frames
foreach (var page in result.Pages)
Console.WriteLine($"Frame {page.PageNumber}: {page.Words.Count()} words");
return result.Text;
}
// LoadImageFrames handles multi-frame TIFFs natively — no frame extraction loop
public string ProcessMultiFrameTiff(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // All frames loaded in one call
var result = new IronTesseract().Read(input);
// Pages maps directly to TIFF frames
foreach (var page in result.Pages)
Console.WriteLine($"Frame {page.PageNumber}: {page.Words.Count()} words");
return result.Text;
}
Imports System
Imports IronOcr
Public Class TiffProcessor
' LoadImageFrames handles multi-frame TIFFs natively — no frame extraction loop
Public Function ProcessMultiFrameTiff(tiffPath As String) As String
Using input As New OcrInput()
input.LoadImageFrames(tiffPath) ' All frames loaded in one call
Dim result = New IronTesseract().Read(input)
' Pages maps directly to TIFF frames
For Each page In result.Pages
Console.WriteLine($"Frame {page.PageNumber}: {page.Words.Count()} words")
Next
Return result.Text
End Using
End Function
End Class
La boucle d'extraction des fichiers temporaires et la chaîne de suppression par image ont disparu. La détection du nombre de trames via FrameDimension.Page disparaît. IronOCR cartographie les trames TIFF à OcrResult.Pages, donc l'accès texte par trame ne nécessite aucune logique d'itération supplémentaire. Le guide d'entrée TIFF/GIF couvre des options supplémentaires pour la sélection d'images et le traitement partiel des fichiers TIFF.
Génération de PDF consultables
Le module Charlesw ne produit qu'une sortie texte. Convertir un document scanné en un PDF consultable — une exigence courante pour les systèmes de gestion de documents — nécessite une bibliothèque PDF secondaire (IronPDF, PDFSharp ou similaire) pour superposer le texte extrait sur les pages d'image originales. IronOCR génère des PDF consultables en un seul appel de méthode, sans bibliothèque secondaire.
Approche du tesseract de Charles :
// charlesw/Tesseract produces text only.
// Creating a searchable PDF requires a second library and significant code.
// The pattern below is representative — actual implementation varies by PDF library.
public void CreateSearchablePdf(string imagePath, string outputPdfPath)
{
// Step 1: Extract text from image
string extractedText;
using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var img = Pix.LoadFromFile(imagePath);
using var page = engine.Process(img);
extractedText = page.GetText();
// Step 2: Build a PDF with the image as background and text overlay
// Requires a separate PDF library (not shown — 50-100+ additional lines)
// The text layer must be positioned to match the original image layout
// Word-level coordinates from the iterator are needed for accurate alignment
throw new NotImplementedException(
"Searchable PDF generation requires a separate PDF library. " +
"Add PdfSharp, IronPDF, or similar, then implement text layer overlay.");
}
// charlesw/Tesseract produces text only.
// Creating a searchable PDF requires a second library and significant code.
// The pattern below is representative — actual implementation varies by PDF library.
public void CreateSearchablePdf(string imagePath, string outputPdfPath)
{
// Step 1: Extract text from image
string extractedText;
using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var img = Pix.LoadFromFile(imagePath);
using var page = engine.Process(img);
extractedText = page.GetText();
// Step 2: Build a PDF with the image as background and text overlay
// Requires a separate PDF library (not shown — 50-100+ additional lines)
// The text layer must be positioned to match the original image layout
// Word-level coordinates from the iterator are needed for accurate alignment
throw new NotImplementedException(
"Searchable PDF generation requires a separate PDF library. " +
"Add PdfSharp, IronPDF, or similar, then implement text layer overlay.");
}
Imports Tesseract
Public Sub CreateSearchablePdf(imagePath As String, outputPdfPath As String)
' Step 1: Extract text from image
Dim extractedText As String
Using engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
Using img As Pix = Pix.LoadFromFile(imagePath)
Using page As Page = engine.Process(img)
extractedText = page.GetText()
End Using
End Using
End Using
' Step 2: Build a PDF with the image as background and text overlay
' Requires a separate PDF library (not shown — 50-100+ additional lines)
' The text layer must be positioned to match the original image layout
' Word-level coordinates from the iterator are needed for accurate alignment
Throw New NotImplementedException("Searchable PDF generation requires a separate PDF library. " & _
"Add PdfSharp, IronPDF, or similar, then implement text layer overlay.")
End Sub
Approche IronOCR :
// SaveAsSearchablePdf produces a PDF/A-compatible searchable document
// Non secondary library, no text overlay code, no coordinate mapping
public void CreateSearchablePdf(string imagePath, string outputPdfPath)
{
var result = new IronTesseract().Read(imagePath);
result.SaveAsSearchablePdf(outputPdfPath);
Console.WriteLine($"Searchable PDF saved: {outputPdfPath}");
}
// Same API works for multi-page TIFF or existing PDF input
public void MakePdfSearchable(string scannedPdfPath, string outputPdfPath)
{
var result = new IronTesseract().Read(scannedPdfPath);
result.SaveAsSearchablePdf(outputPdfPath);
}
// SaveAsSearchablePdf produces a PDF/A-compatible searchable document
// Non secondary library, no text overlay code, no coordinate mapping
public void CreateSearchablePdf(string imagePath, string outputPdfPath)
{
var result = new IronTesseract().Read(imagePath);
result.SaveAsSearchablePdf(outputPdfPath);
Console.WriteLine($"Searchable PDF saved: {outputPdfPath}");
}
// Same API works for multi-page TIFF or existing PDF input
public void MakePdfSearchable(string scannedPdfPath, string outputPdfPath)
{
var result = new IronTesseract().Read(scannedPdfPath);
result.SaveAsSearchablePdf(outputPdfPath);
}
Public Sub CreateSearchablePdf(imagePath As String, outputPdfPath As String)
Dim result = New IronTesseract().Read(imagePath)
result.SaveAsSearchablePdf(outputPdfPath)
Console.WriteLine($"Searchable PDF saved: {outputPdfPath}")
End Sub
Public Sub MakePdfSearchable(scannedPdfPath As String, outputPdfPath As String)
Dim result = New IronTesseract().Read(scannedPdfPath)
result.SaveAsSearchablePdf(outputPdfPath)
End Sub
SaveAsSearchablePdf() intègre le texte OCR comme une couche invisible alignée sur les mots reconnus, rendant le document entièrement indexable sans altérer son apparence visuelle. Le guide pratique au format PDF consultable couvre la sélection de la plage de pages et les options de compression. Un exemple fonctionnel est disponible sur la page d'exemple PDF consultable .
Référence de mappage de l'API Tesseract de Charlesw vers IronOCR
| Tesseract de Charles | Équivalent d'IronOCR |
|---|---|
new TesseractEngine(tessDataPath, "eng", EngineMode.Default) |
new IronTesseract() |
Pix.LoadFromFile(imagePath) |
input.LoadImage(imagePath) |
Pix.LoadFromMemory(bytes) |
input.LoadImage(imageBytes) |
engine.Process(pix) |
ocr.Read(input) |
page.GetText() |
result.Text |
page.GetMeanConfidence() |
result.Confidence (échelle de 0 à 100) |
page.GetIterator() |
result.Pages, result.Words (collections directes) |
iter.GetText(PageIteratorLevel.Word) |
word.Text |
iter.GetConfidence(PageIteratorLevel.Word) |
word.Confidence |
iter.TryGetBoundingBox(PageIteratorLevel.Word, out var b) |
word.X, word.Y, word.Width, word.Height |
iter.GetText(PageIteratorLevel.Para) |
paragraph.Text |
iter.IsAtBeginningOf(PageIteratorLevel.Block) |
page.Paragraphs (itérer directement) |
EngineMode.Default |
Automatique (paramètre par défaut de Tesseract 5 LSTM) |
EngineMode.TesseractOnly |
ocr.Configuration.PageSegmentationMode |
Fichier .traineddata tessdata manuel |
dotnet add package IronOcr.Languages.French |
Constante TessDataPath + entrée de copie .csproj |
Non applicable — groupé |
Pix.LoadFromFile() via la DLL Leptonica |
input.LoadImage() —aucune DLL native requise |
Méthode GetTessDataPath() pour la plateforme |
Non applicable — éliminé |
leptonica-1.82.0.dll / libleptonica-dev |
Non applicable — aucune dépendance à Leptonica |
| Extraction manuelle des images du fichier temporaire pour TIFF | input.LoadImageFrames(tiffPath) |
| Aucun fichier PDF consultable | result.SaveAsSearchablePdf(outputPath) |
new TesseractEngine() par thread |
Un IronTesseract — sûr pour les threads |
Problèmes de migration courants et solutions
Problème 1 : Exception DllNotFoundException pour les binaires Leptonica ou Tesseract
Charlesw Tesseract : System.DllNotFoundException: Unable to load DLL 'leptonica-1.82.0': The specified module could not be found. Cette exception se déclenche lorsque la DLL native Leptonica n'est pas dans l'emplacement attendu. Elle est courante dans les nouveaux conteneurs Docker, les agents CI, ou tout environnement où le dossier runtimes/ du paquet NuGet n'a pas été copié correctement.
Solution : Supprimez le paquet Tesseract. Installez IronOcr. IronOCR intègre tous les binaires natifs en interne et n'utilise pas P/Invoke dans Leptonica système. L'exception ne peut pas se produire car il n'existe aucune dépendance externe à Leptonica :
dotnet remove package Tesseract
:InstallCmd dotnet add package IronOcr
dotnet remove package Tesseract
:InstallCmd dotnet add package IronOcr
Aucun apt-get install libleptonica-dev requis. Aucune entrée <CopyToOutputDirectory> pour les DLL natives.
Problème n° 2 : Erreurs de chemin d'accès à Tessdata après le déploiement
Charlesw Tesseract : Tesseract.TesseractException: Failed to initialise tesseract engine. Cela se déclenche lorsque TessDataPath ne se résout pas à l'exécution. Cela compile sans erreur, échoue seulement à l'exécution, et le chemin d'échec dépend de l'environnement de déploiement.
Solution : Le concept de chemin tessdata n'existe pas dans IronOCR. Supprimez la constante, supprimez le XML CopyToOutputDirectory dans .csproj et supprimez la méthode factory qui le construit. Les données linguistiques sont distribuées sous forme de packages NuGet :
# Replace this manual tessdata file management:
# tessdata/eng.traineddata (15 MB, manually downloaded)
# tessdata/fra.traineddata (15 MB, manually downloaded)
# .csproj <CopyToOutputDirectory> entry
# With NuGet packages:
dotnet add package IronOcr.Languages.French
# Replace this manual tessdata file management:
# tessdata/eng.traineddata (15 MB, manually downloaded)
# tessdata/fra.traineddata (15 MB, manually downloaded)
# .csproj <CopyToOutputDirectory> entry
# With NuGet packages:
dotnet add package IronOcr.Languages.French
Le guide multilingue explique comment configurer la reconnaissance multilingue après l'ajout de modules linguistiques.
Problème 3 : La création du conteneur échoue lors de la mise à jour de l'image de base
Charlesw Tesseract : Le Dockerfile inclut apt-get install -y libleptonica-dev pour satisfaire la dépendance native de Leptonica. Lorsque l'image de base passe de Debian Bullseye à Bookworm, ou lorsque le nom du paquet Leptonica change d'une distribution à l'autre, la compilation échoue avec une erreur apt. Pour résoudre ce problème, il faut savoir quel nom de paquet utiliser sur la nouvelle distribution.
Solution : Supprimez entièrement la ligne Leptonica apt-get. IronOCR sous Linux ne nécessite que le paquet standard libgdiplus dont toute application .NET utilisant System.Drawing a déjà besoin :
# Before: Leptonica explicit install — breaks on base image updates
RUN apt-get update && apt-get install -y libleptonica-dev
# After: standard .NET Linux requirement only
RUN apt-get update && apt-get install -y libgdiplus
Le guide de déploiement Docker fournit des modèles Dockerfile testés pour les images de base courantes. Aucun code d'infrastructure spécifique à charlesw n'est requis.
Problème 4 : Rupture du modèle d'itération sur les pages vides ou contenant des espaces blancs
Charlesw Tesseract : Le ResultIterator renvoie null de iter.GetText() sur certains segments de page, nécessitant des vérifications null explicites tout au long de la boucle. Oublier une vérification null provoque NullReferenceException sur des pages vierges ou des images sans texte reconnaissable.
Solution : Les collections de résultats IronOCR ne sont jamais nulles. Les pages vides renvoient des collections vides. Vérifiez le contenu textuel plutôt que les références nulles :
// Before: null checks required at every iterator level
var wordText = iter.GetText(PageIteratorLevel.Word);
if (wordText != null && wordText.Trim().Length > 0)
results.Add(wordText.Trim());
// After: collection is safe to enumerate; check content as needed
foreach (var word in result.Pages.SelectMany(p => p.Lines).SelectMany(l => l.Words))
{
if (!string.IsNullOrWhiteSpace(word.Text))
results.Add(word.Text);
}
// Before: null checks required at every iterator level
var wordText = iter.GetText(PageIteratorLevel.Word);
if (wordText != null && wordText.Trim().Length > 0)
results.Add(wordText.Trim());
// After: collection is safe to enumerate; check content as needed
foreach (var word in result.Pages.SelectMany(p => p.Lines).SelectMany(l => l.Words))
{
if (!string.IsNullOrWhiteSpace(word.Text))
results.Add(word.Text);
}
' Before: null checks required at every iterator level
Dim wordText = iter.GetText(PageIteratorLevel.Word)
If wordText IsNot Nothing AndAlso wordText.Trim().Length > 0 Then
results.Add(wordText.Trim())
End If
' After: collection is safe to enumerate; check content as needed
For Each word In result.Pages.SelectMany(Function(p) p.Lines).SelectMany(Function(l) l.Words)
If Not String.IsNullOrWhiteSpace(word.Text) Then
results.Add(word.Text)
End If
Next
Problème n° 5 : Non-respect des règles de sécurité relatives aux filetages sous charge
Charlesw Tesseract : TesseractEngine n'est pas sûr pour les threads. Le partage d'une même instance entre plusieurs requêtes simultanées dans une application ASP.NET entraîne des violations d'accès ou des résultats corrompus. La solution standard consiste à créer un moteur par thread, mais cela n'est pas évident à partir de l'API et les messages d'erreur en cas de problème sont des exceptions natives cryptiques.
Solution : IronTesseract est sûr pour les threads. Une instance peut servir des requêtes concurrentes, ou pour un débit maximal, créez-en une par thread dans un Parallel.ForEach — les deux modèles fonctionnent sans modification :
// Thread-safe parallel processing — IronTesseract handles concurrent access
var results = new System.Collections.Concurrent.ConcurrentBag<string>();
Parallel.ForEach(imageFiles, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
results.Add(result.Text);
});
// Thread-safe parallel processing — IronTesseract handles concurrent access
var results = new System.Collections.Concurrent.ConcurrentBag<string>();
Parallel.ForEach(imageFiles, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
results.Add(result.Text);
});
Imports System.Collections.Concurrent
Imports System.Threading.Tasks
' Thread-safe parallel processing — IronTesseract handles concurrent access
Dim results As New ConcurrentBag(Of String)()
Parallel.ForEach(imageFiles, Sub(imagePath)
Dim ocr As New IronTesseract()
Dim result = ocr.Read(imagePath)
results.Add(result.Text)
End Sub)
Le guide OCR asynchrone couvre les modèles asynchrones pour les contrôleurs ASP.NET Core où le blocage des threads n'est pas acceptable.
Problème n° 6 : Binaire ARM64 manquant à l'exécution
Charlesw Tesseract : Sur les agents AWS Graviton (Linux ARM64) ou Apple Silicon CI, le package archivé peut ne pas contenir de binaire natif ARM64. L'échec est un DllNotFoundException ou un BadImageFormatException à la création du moteur — une erreur d'exécution sur une plateforme que le package n'a aucun moyen de prendre en charge.
Solution : IronOCR fournit des binaires ARM64 validés pour Linux et macOS. Déploiement sur ARM64 sans modification du code. Les guides de déploiement Linux et macOS confirment les identifiants d'exécution pris en charge.
Liste de contrôle de migration de Charlesw Tesseract
Pré-migration
Auditez le code source pour identifier tous les modèles qui vont changer :
# Find all references to Tesseract namespace (engine creation, Pix usage, iterator usage)
grep -rn "using Tesseract" --include="*.cs" .
# Find TesseractEngine instantiation points
grep -rn "TesseractEngine" --include="*.cs" .
# Find Pix usage (Leptonica image type)
grep -rn "Pix\." --include="*.cs" .
# Find tessdata path constants and methods
grep -rn "tessdata\|TessDataPath\|traineddata" --include="*.cs" .
# Find platform-conditional deployment code
grep -rn "IsOSPlatform\|DOTNET_RUNNING_IN_CONTAINER\|LD_LIBRARY_PATH" --include="*.cs" .
# Find iterator pattern usage
grep -rn "GetIterator\|ResultIterator\|PageIteratorLevel" --include="*.cs" .
# Find confidence calls
grep -rn "GetMeanConfidence\|GetConfidence" --include="*.cs" .
# Find .csproj tessdata copy entries
grep -rn "tessdata" --include="*.csproj" .
# Find all references to Tesseract namespace (engine creation, Pix usage, iterator usage)
grep -rn "using Tesseract" --include="*.cs" .
# Find TesseractEngine instantiation points
grep -rn "TesseractEngine" --include="*.cs" .
# Find Pix usage (Leptonica image type)
grep -rn "Pix\." --include="*.cs" .
# Find tessdata path constants and methods
grep -rn "tessdata\|TessDataPath\|traineddata" --include="*.cs" .
# Find platform-conditional deployment code
grep -rn "IsOSPlatform\|DOTNET_RUNNING_IN_CONTAINER\|LD_LIBRARY_PATH" --include="*.cs" .
# Find iterator pattern usage
grep -rn "GetIterator\|ResultIterator\|PageIteratorLevel" --include="*.cs" .
# Find confidence calls
grep -rn "GetMeanConfidence\|GetConfidence" --include="*.cs" .
# Find .csproj tessdata copy entries
grep -rn "tessdata" --include="*.csproj" .
Notez les environnements de déploiement ciblés par le projet (Docker, Linux, ARM64, Azure, AWS) — ce sont les environnements où charlesw/tesseract nécessite le plus de configuration IronOCR élimine.
Migration de code
- Exécutez
dotnet remove package Tesseractpour désinstaller le wrapper charlesw - Exécutez
dotnet add package IronOcrpour installer IronOCR - Ajoutez
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";au démarrage de l'application - Remplacez toutes les déclarations
using Tesseract;parusing IronOcr; - Supprimez la constante de chemin tessdata et toute méthode qui construit le chemin pour chaque environnement.
- Supprimez tous les blocs
RuntimeInformation.IsOSPlatform()écrits pour la sélection de chemin tessdata - Supprimez toutes les entrées
<CopyToOutputDirectory>pour les fichiers tessdata de tous les fichiers.csproj - Supprimez les fichiers
.traineddatatessdata du contrôle source ou des magasins d'artefacts de déploiement - Ajoutez
dotnet add package IronOcr.Languages.*pour chaque langue précédemment déployée en tant que fichier.traineddata - Remplacez les chaînes
TesseractEngine+Pix.LoadFromFile()+engine.Process()parnew IronTesseract().Read() - Remplacez tous les appels
Pix.LoadFromFile()etPix.LoadFromMemory()parinput.LoadImage() - Remplacez tous les appels
page.GetText()parresult.Text - Remplacez l'extraction de mots/lignes basée sur l'itérateur par l'accès direct aux collections sur
result.Pages - Remplacez la logique de seuil
iter.GetConfidence()par LINQ surresult.Wordsouresult.Lines - Supprimez
libleptonica-dev/leptonica-1.82.0.dlldes Dockerfiles et des scripts de déploiement
Après la migration
Après avoir effectué les mises à jour du code, veuillez vérifier les points suivants :
- La reconnaissance optique de caractères (OCR) fonctionne correctement sous Windows sans aucune erreur de DLL native.
- L'OCR fonctionne avec succès dans un conteneur Linux Docker sans aucun changement
apt-getau-delà delibgdiplus - La reconnaissance optique de caractères (OCR) produit un résultat textuel sur ARM64 si cette plateforme figure dans la matrice de déploiement. Les fichiers TIFF multipages renvoient le texte de toutes les images, et non seulement de la première.
- Le filtrage par confiance renvoie le même ensemble logique de mots à haute confiance que l'implémentation d'itérateur précédente.
- Les documents spécifiques à une langue (français, allemand, etc.) sont correctement reconnus après l'installation des packages NuGet de langue.
- Opérations OCR parallèles terminées sans exception ni sortie corrompue
- Un fichier PDF interrogeable est désormais généré, alors que l'implémentation précédente ne renvoyait que du texte.
- Génération de pipelines CI/CD sans aucune étape de téléchargement de tessdata ni commande d'installation de Leptonica
- Test de fumée sur le même corpus d'images utilisé pour valider l'implémentation précédente
Principaux avantages de la migration vers IronOCR
Modèle de déploiement autonome. Après la migration, la dépendance OCR est entièrement décrite par une seule référence de package NuGet . Pas de fichiers tessdata dans le contrôle source, pas d'entrées CopyToOutputDirectory, pas d'étapes de déploiement de DLL natives, pas de paquets système Leptonica. Les pipelines CI/CD qui nécessitaient précédemment une gestion d'artefacts en plusieurs étapes se réduisent à dotnet publish. Le code relatif au déploiement qui s'était accumulé pour prendre en charge le wrapper charlesw a disparu définitivement.
Portabilité de la plateforme sans logique conditionnelle. Le même fichier binaire d'application s'exécute sans modification sur Windows x64, Linux x64, Linux ARM64, macOS x64 et macOS ARM64. Les équipes qui ajoutent une cible de déploiement ARM64 (qu'il s'agisse d'AWS Graviton, d'Apple Silicon CI ou de Raspberry Pi) n'écrivent pas de nouveau code de détection de plateforme. Le guide de déploiement Linux et le guide de déploiement AWS confirment les configurations testées.
Amélioration de la précision de Tesseract 5 grâce au prétraitement intégré. Le passage de Tesseract 4.1.1 à Tesseract 5 améliore la reconnaissance sur les documents dégradés. IronOCR ajoute un prétraitement automatique à la mise à niveau du moteur, appliquant un redressement, une réduction du bruit, une normalisation du contraste et une binarisation avant que le moteur ne traite chaque image. Les documents qui nécessitaient auparavant un pipeline de prétraitement personnalisé pour atteindre des seuils de précision acceptables atteignent désormais ces seuils sans code supplémentaire. Le guide de correction de la qualité d'image documente explicitement les options de prétraitement pour les cas nécessitant un réglage au-delà des paramètres par défaut.
Naviguer directement vers les résultats remplace le modèle d'itérateur. Le modèle d'itérateur charlesw — GetIterator(), Begin(), Next(), IsAtBeginningOf(), vérifications null tout au long — est remplacé par de simples collections. Les mots, les lignes, les paragraphes et les pages sont des propriétés de l'objet résultat. Le filtrage basé sur la confiance est une expression LINQ. Le code qui extrayait des données au niveau des mots nécessitait auparavant 15 à 30 lignes de gestion d'itérateurs ; L'équivalent IronOCR est de 2 à 3 lignes. La page présentant les résultats de la reconnaissance optique de caractères (OCR) résume le modèle de sortie structurée complet.
Sortie PDF consultable sans bibliothèque secondaire. result.SaveAsSearchablePdf() produit un PDF avec une couche de texte alignée sur les mots reconnus, ne nécessitant aucune bibliothèque PDF secondaire. Les systèmes de gestion documentaire qui importent des PDF interrogeables ne nécessitent plus d'étape de génération de PDF distincte. Le même objet de résultat qui fournit le texte extrait génère également le fichier interrogeable, ce qui simplifie le traitement des documents en le réduisant à une seule bibliothèque dépendante.
Maintenance active et couverture des correctifs de sécurité. IronOCR bénéficie de mises à jour régulières intégrant les améliorations du modèle Tesseract 5, la validation de la compatibilité avec l'environnement d'exécution .NET et la couverture des correctifs de sécurité pour le moteur C++ sous-jacent. La dépendance ne présente plus le profil de risque d'un package archivé : les audits de conformité ne signalent plus l'absence de correctifs de sécurité. À mesure que .NET 10 sera disponible pour tous d'ici 2026, le centre de documentation IronOCR reflétera la compatibilité actuelle sans nécessiter de solutions de contournement ni de forks.
Questions Fréquemment Posées
Pourquoi devrais-je migrer de charlesw/tesseract (.NET Tesseract wrapper) vers IronOCR ?
Parmi les motivations communes, citons l'élimination de la complexité de l'interopérabilité COM, le remplacement de la gestion des licences basée sur les fichiers, l'absence de facturation à la page, l'activation du déploiement Docker/conteneur et l'adoption d'un flux de travail NuGet-natif qui s'intègre à l'outillage .NET standard.
Quels sont les principaux changements de code lors de la migration de charlesw/tesseract (.NET Tesseract wrapper) vers IronOCR ?
Remplacer les séquences d'initialisation charlesw/tesseract par l'instanciation IronTesseract, supprimer la gestion du cycle de vie COM (modèles explicites Create/Load/Close), et mettre à jour les noms des propriétés des résultats. Le résultat est une réduction significative du nombre de lignes de code.
Comment installer IronOCR pour commencer la migration ?
Exécutez "Install-Package IronOcr" dans la console du Package Manager ou "dotnet add package IronOcr" dans le CLI. Les packs de langues sont des paquets distincts : 'dotnet add package IronOcr.Languages.French' pour le français, par exemple.
IronOCR offre-t-il la même précision d'OCR que charlesw/tesseract (.NET Tesseract wrapper) pour les documents commerciaux standard ?
IronOcr atteint un niveau de précision élevé pour les contenus commerciaux standard, notamment les factures, les contrats, les reçus et les formulaires dactylographiés. Les filtres de prétraitement d'image (désalignement, suppression du bruit, amélioration du contraste) améliorent encore la reconnaissance sur des données dégradées.
Comment IronOCR traite-t-il les données linguistiques que charlesw/tesseract (.NET Tesseract wrapper) installe séparément ?
Les données linguistiques de l'IronOcr sont distribuées sous forme de packages NuGet. 'dotnet add package IronOcr.Languages.German' installe la prise en charge de l'allemand. Il n'y a pas de placement manuel de fichiers ou de chemins d'accès aux répertoires.
La migration de charlesw/tesseract (.NET Tesseract wrapper) vers IronOCR nécessite-t-elle des changements dans l'infrastructure de déploiement ?
IronOCR nécessite moins de changements d'infrastructure que charlesw/tesseract (.NET Tesseract wrapper). Il n'y a pas de chemin d'accès au binaire SDK, de placement de fichier de licence ou de configuration de serveur de licence. Le package NuGet contient le moteur OCR complet, et la clé de licence est une chaîne de caractères définie dans le code de l'application.
Comment configurer les licences IronOCR après la migration ?
Attribuer IronOcr.License.LicenseKey = "YOUR-KEY" dans le code de démarrage de l'application. Dans Docker ou Kubernetes, stockez la clé dans une variable d'environnement et lisez-la au démarrage. Utilisez License.IsValidLicense pour valider avant d'accepter le trafic.
IronOCR peut-il traiter les PDF de la même manière que charlesw/tesseract ?
Oui, IronOCR lit aussi bien les PDF natifs que les PDF numérisés. Instanciez IronTesseract, appelez ocr.Read(input) où l'input est un chemin PDF ou OcrPdfInput, et itérez les pages OcrResult. Aucun pipeline de rendu PDF séparé n'est nécessaire.
Comment IronOcr gère-t-il le threading dans le cadre d'un traitement à haut volume ?
IronTesseract est sûr pour l'instanciation par thread. Créez une instance par thread dans un Parallel.ForEach ou un Task pool, exécutez l'OCR simultanément et disposez de chaque instance lorsque vous avez terminé. Aucun état global ou verrouillage n'est nécessaire.
Quels formats de sortie IronOCR prend-il en charge après l'extraction du texte ?
IronOCR renvoie des résultats structurés comprenant le texte, les coordonnées des mots, les scores de confiance et la structure des pages. Les options d'exportation comprennent le texte brut, le PDF interrogeable et les objets de résultats structurés pour le traitement en aval.
La tarification d'IronOCR est-elle plus prévisible que celle de charlesw/tesseract (.NET Tesseract wrapper) pour la mise à l'échelle des charges de travail ?
IronOCR utilise des licences perpétuelles forfaitaires sans frais par page ou par volume. Que vous traitiez 10 000 ou 10 millions de pages, le coût de la licence reste constant. Les options de licence en volume et en équipe sont disponibles sur la page de tarification d'IronOcr.
Qu'advient-il de mes tests existants après avoir migré de charlesw/tesseract (.NET Tesseract wrapper) vers IronOCR ?
Les tests qui vérifient le contenu du texte extrait doivent continuer à passer après la migration. Les tests qui valident les modèles d'appel d'API ou le cycle de vie des objets COM devront être mis à jour pour refléter le modèle d'initialisation et de résultat plus simple d'IronOcr.

