Umstellung von Charlesw Tesseract auf IronOCR
Diese Anleitung führt .NET-Entwickler durch die Migration vom charlesw/tesseract NuGet-Paket (Tesseract) zu IronOCR. Die Migration konzentriert sich auf ein spezifisches Problem: das native Binärbereitstellungsmodell, das der charlesw-Wrapper auferlegt, und den plattformabhängigen Code, den dieses Modell Entwickler zwingen kann zu schreiben. Teams, die in CI mit DllNotFoundException gekämpft haben, sich mit Leptonica-Bibliothekspfaden unter Linux auseinandersetzen mussten oder Betriebssystem-Erkennungsblöcke geschrieben haben, die nichts mit OCR zu tun hatten, werden feststellen, dass diese Anleitung genau zeigt, was nach dem Wechsel verschwindet.
Warum von Charles Tesserakt migrieren?
Das archivierte charlesw/tesseract Paket bringt neue Projekte in Schwierigkeiten, nicht weil die API schlecht ist, sondern weil das erforderliche Bereitstellungsmodell auf Annahmen basiert, die in moderner .NET-Infrastruktur nicht mehr gültig sind. Folgendes beeinflusst Migrationsentscheidungen:
Native Binärbereitstellung pro Plattform. Das Tesseract NuGet-Paket enthält plattformspezifische native Binärdaten: tesseract50.dll für Windows x64, ein separates Build für x86, libtesseract.so für Linux x64. Diese Binärdaten müssen zur Laufzeit am richtigen Ort landen, damit die P/Invoke-Aufrufe erfolgreich sind. Auf einer Entwickler-Workstation kopiert das SDK sie automatisch. In einem Docker-Container, einem ARM64-Build-Agent oder einem Azure App Service mit einem nicht standardmäßigen Anwendungsstammverzeichnis ist dies nicht der Fall. Jedes neue Bereitstellungsziel wird zu einer Debugging-Sitzung.
Leptonica als versteckte Abhängigkeit. Das Laden von Bildern durch Tesseract wird von der Leptonica-Bibliothek übernommen, die als eigener Satz nativer DLLs zusammen mit den Tesseract-Binärdateien ausgeliefert wird. Unter Windows muss leptonica-1.82.0.dll im Ausgabeverzeichnis vorhanden sein. Unter Linux muss die Leptonica-Shared-Library entweder als Paket mitgeliefert oder als Systempaket installiert werden. Debian-basierte Docker-Images ohne libleptonica-dev schlagen bei Pix.LoadFromFile() mit einer wenig hilfreichen nativen Ausnahme fehl, und die Behebung erfordert das Wissen, welches Systempaket die Abhängigkeit auflöst.
Plattformabhängiger Code in der Anwendungslogik. Die Kombination aus nativem Binärladen und der Lösung des Tessdata-Pfads zwingt Entwickler, RuntimeInformation.IsOSPlatform() Überprüfungen zu schreiben, Umgebungsvariablen für Containerkontexte zu erkennen und eine Pfadlogik zu erstellen, die je nach Ziel variiert. Keiner dieser Codeabschnitte ist OCR-Logik. Es handelt sich um eine Bereitstellungsinfrastruktur, die nur deshalb existiert, weil die Binärverwaltung des Pakets unvollständig ist.
Archiviertes Paket ohne Aktualisierungsmöglichkeit. Das Repository ist seit 2021 archiviert. Wenn ein Systempaket-Update auf einem Linux-Host die Leptonica-ABI ändert oder eine neue .NET Laufzeitumgebung das Verhalten beim Laden nativer Binärdateien ändert, steht keine Version zum Aktualisieren zur Verfügung. Die einzigen Optionen sind entweder das Forken der nativen Build-Pipeline oder das Ersetzen der Bibliothek.
Tesseract 4.1.1 Engine-Absturz. Das Paket enthält Tesseract 4.1.1. Das neu geschriebene LSTM-Modell von Tesseract 5 liefert eine deutlich höhere Genauigkeit bei Dokumenten mit Qualitätsverlust. Dieses Upgrade ist nicht über das charlesw-Paket verfügbar – es erfordert einen Bibliothekswechsel.
Vertrauensbehandlung ohne einen Standardmuster. Der charlesw-Wrapper stellt page.GetMeanConfidence() als Float zwischen 0 und 1 bereit, aber die Anwendung von Vertrauensschwellenwerten auf Wort- oder Zeichenebene erfordert das Iteratormuster mit iter.GetConfidence(PageIteratorLevel.Word). Es gibt keine standardisierte Filter-API; Jedes Team implementiert seine eigene Schwellenwertlogik auf unterschiedliche Weise.
Das grundsätzliche Problem
Der CharlesW-Wrapper benötigt eine plattformspezifische native Binärkonfiguration, bevor die OCR-Funktion ausgeführt werden kann:
// 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 verfügt über keine native Binärkonfiguration:
// 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. Charles Tesseract: Funktionsvergleich
Die folgende Tabelle beschreibt die für Teams, die diese Migration bewerten, relevanten Funktionen:
| Feature | Charles Tesserakt | IronOCR |
|---|---|---|
| Wartungsstatus | Archiviert (keine Aktualisierungen seit 2021) | Aktiv gepflegt |
| Tesseract-Engine-Version | 4.1.1 (eingefroren) | 5 (aktuell, optimiert) |
| Lizenz | Apache 2.0 (kostenlos) | Kommerziell ($999–$2.999 unbefristet) |
| NuGet -Installation | Tesseract |
IronOcr |
| Native Binärverwaltung | Manuelle DLL-Bereitstellung pro Plattform | Komplett ausgestattet, keine Konfiguration erforderlich |
| Leptonica-Abhängigkeit | Erfordert leptonica-1.82.0.dll / libleptonica-dev |
Nicht zutreffend (wird intern bearbeitet) |
| Tessdata-Management | Manueller Download und .csproj Kopieren-Eintrag |
NuGet Sprachpakete |
| Plattformbedingter Code | Erforderlich für die Bereitstellung auf mehreren Zielplattformen | Nicht erforderlich |
| Docker-Bereitstellung | Erfordert explizite Tessdata COPY + Leptonica apt-get |
Nur Standardanforderungen an .NET Container |
| ARM64-Unterstützung | Unbestätigter Post-Archiv-Beitrag | Gebündelt, validiert |
| Bildeingabeformate | TIFF, PNG, BMP, JPG (über Leptonica) | JPG, PNG, BMP, TIFF, GIF und mehr |
| Mehrseitiges TIFF | Manuelle Frame-Iteration | input.LoadImageFrames() |
| Native PDF-Eingabe | Nein (erfordert eine zusätzliche Bibliothek) | Ja |
| Durchsuchbare PDF-Ausgabe | Nein | Ja (result.SaveAsSearchablePdf()) |
| Eingebaute Vorverarbeitung | None | Entzerren, Rauschen entfernen, Kontrast erhöhen, Binärisierung, Schärfen, Skalieren, Dilatieren, Erodieren, Invertieren |
| API für Konfidenzfilterung | Manueller Iterator mit GetConfidence() |
result.Confidence, word.Confidence |
| Strukturierte Ergebnisse | Iterator-Muster (ResultIterator) |
Direkte Sammlungen (Seiten, Absätze, Zeilen, Wörter) |
| Barcode-Lesung | Nein | Ja (während der OCR-Durchführung) |
| Regionsbasierte OCR | Nein | Ja (CropRectangle) |
| Thread-Sicherheit | Verantwortung des Anrufers | Eingebaut |
| Mehr als 125 Sprachpakete | Manuelle Tessdata-Downloads | dotnet add package IronOcr.Languages.* |
| Plattformübergreifendes .NET | Ja (.NET Standard 2.0) | Ja (.NET Framework 4.6.2+, .NET 5/6/7/8/9) |
| Sicherheitspatch-Kadenz | Keine (archiviert) | Regelmäßige Veröffentlichungen |
Schnellstart: Charles Tesserakt zu IronOCR Migration
Schritt 1: Ersetzen des NuGet-Pakets
Entfernen Sie das Paket "charlesw Tesseract":
dotnet remove package Tesseract
dotnet remove package Tesseract
Installieren Sie IronOCR über NuGet :
dotnet add package IronOcr
Schritt 2: Namespaces aktualisieren
// Before (charlesw Tesseract)
using Tesseract;
// After (IronOCR)
using IronOcr;
// Before (charlesw Tesseract)
using Tesseract;
// After (IronOCR)
using IronOcr;
Imports IronOcr
Schritt 3: Lizenz initialisieren
Fügen Sie diesen Aufruf einmalig beim Start der Anwendung hinzu, bevor OCR-Operationen ausgeführt werden:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Auf der IronOCR -Lizenzseite ist eine kostenlose Testlizenz erhältlich. Die Testversion entfernt das Wasserzeichen aus der Ausgabe und ermöglicht den vollen API-Zugriff.
Beispiele für die Code-Migration
Entfernen der Konfiguration des nativen Binärpfads
Das am häufigsten verwendete Initialisierungsmuster in charlesw/tesseract-Projekten ist eine Factory- oder Hilfsklasse, die den tessdata-Pfad erstellt und das Laden nativer Bibliotheken pro Umgebung konfiguriert. Dieser Code existiert ausschließlich aufgrund des Bereitstellungsmodells des Wrappers.
Charlesw Tesseract-Ansatz:
// 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
IronOCR Ansatz:
// 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)
Die gesamte OcrEngineFactory Klasse wird gelöscht. Die plattformabhängige Pfadlogik, der DOTNET_RUNNING_IN_CONTAINER Check und die Leptonica-DLL-Abhängigkeit verschwinden ebenfalls. In jeder Umgebung – Entwickler-Workstation, CI-Agent, Docker-Container, Cloud-VM – werden die gleichen zwei Zeilen ausgeführt. Die IronTesseract-Einrichtungsanleitung beschreibt Konfigurationsoptionen, wenn Standardeinstellungen angepasst werden müssen, für die meisten Einsatzszenarien ist dies jedoch nicht erforderlich.
Leptonica-Bildkonvertierung – Ersatz
Der charlesw-Wrapper verwendet Leptonicas Pix Typ als seine bildliche Darstellung. Jeder Code, der Bilder vor der OCR-Manipulation bearbeitet, muss durch Pix konvertiert werden, was erfordert, dass die Leptonica native DLL geladen und funktionsfähig ist. Das Ersetzen dieses Musters durch OcrInput eliminiert die Leptonica-Abhängigkeit vollständig.
Charlesw Tesseract-Ansatz:
// 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)
{
//Neindirect 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)
{
//Neindirect 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
' Neindirect 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
IronOCR Ansatz:
// 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
Der temporäre Dateiaustausch entfällt. Keine Datei wird auf die Festplatte geschrieben, keine Leptonica-DLL wird für die Konvertierung aufgerufen, und es gibt keinen finally Block zum Aufräumen. Der Eingabe-Bilder-Leitfaden und der Stream-Eingabe-Leitfaden dokumentieren alle unterstützten Eingabequellen, einschließlich des Ladens von URLs und speicherabbildeten Dateien.
Konfidenzschwellenfilterung
Der charlesw-Wrapper zeigt das Vertrauen auf zwei Ebenen: page.GetMeanConfidence() für die gesamte Seite und iter.GetConfidence(PageIteratorLevel.Word) für einzelne Wörter. Das Herausfiltern von Wörtern mit geringer Konfidenz aus der Ausgabe erfordert die manuelle Steuerung einer Iterationsschleife.IronOCR stellt die Konfidenz direkt in den Ergebnisobjekten dar, wodurch die Schwellenwertlogik zu einem LINQ-Ausdruck wird.
Charlesw Tesseract-Ansatz:
// 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
IronOCR Ansatz:
// 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
Der Iterator-Zustandsautomat ist verschwunden. Die Konfidenzwerte in IronOCR liegen durchgehend auf einer Skala von 0 bis 100, eine Division durch 100 ist nicht erforderlich. Der Leitfaden zu den Konfidenzwerten umfasst Konfidenzmuster pro Wort, pro Zeile und pro Seite. Der Leitfaden zu den Leseergebnissen zeigt, wie man durch die vollständige strukturierte Ergebnishierarchie navigiert.
Stapelverarbeitung von mehrseitigen TIFF-Dateien
TIFF-Dateien mit mehreren Einzelbildern sind in Dokumentenscanning-Workflows üblich. Der charlesw-Wrapper verfügt über keine integrierte Unterstützung für Multi-Frame-TIFF; Jedes Einzelbild muss vor der Weiterverarbeitung manuell extrahiert werden.IronOCR verarbeitet Mehrbild-TIFFs nativ mit einem einzigen Ladeaufruf.
Charlesw Tesseract-Ansatz:
// 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
IronOCR Ansatz:
// 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
Die Schleife zum Extrahieren temporärer Dateien und die Entsorgungskette pro Frame wurden entfernt. Die Erkennung der Bildanzahl über FrameDimension.Page verschwindet.IronOCR mappt TIFF-Frames zu OcrResult.Pages, sodass für den Zugriff auf Einzelbild-Text keine zusätzliche Iterationslogik erforderlich ist. Der Leitfaden zur TIFF/GIF-Eingabe beschreibt zusätzliche Optionen zur Einzelbildauswahl und zur partiellen TIFF-Verarbeitung.
durchsuchbare PDF-Generierung
Der charlesw-Wrapper erzeugt nur Textausgabe. Das Konvertieren eines gescannten Dokuments in ein durchsuchbares PDF — ein häufiges Erfordernis für Dokumentenverwaltungssysteme — benötigt eine sekundäre PDF-Bibliothek (IronPDF, PDFSharp oder Ähnliches), um den extrahierten Text auf die Originalbilderseiten zu überlagern.IronOCR erzeugt durchsuchbare PDFs mit nur einem Methodenaufruf, ohne dass eine zusätzliche Bibliothek benötigt wird.
Charlesw Tesseract-Ansatz:
// 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
IronOCR Ansatz:
// SaveAsSearchablePdf produces a PDF/A-compatible searchable document
//Neinsecondary 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
//Neinsecondary 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);
}
Imports System
' SaveAsSearchablePdf produces a PDF/A-compatible searchable document
' Neinsecondary library, no text overlay code, no coordinate mapping
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
' Same API works for multi-page TIFF or existing PDF input
Public Sub MakePdfSearchable(scannedPdfPath As String, outputPdfPath As String)
Dim result = New IronTesseract().Read(scannedPdfPath)
result.SaveAsSearchablePdf(outputPdfPath)
End Sub
SaveAsSearchablePdf() bettet den OCR-Text als unsichtbare Schicht ein, die an den erkannten Wörtern ausgerichtet ist, wodurch das Dokument volltextdurchsuchbar wird, ohne das visuelle Erscheinungsbild zu verändern. Die durchsuchbare PDF-Anleitung behandelt die Auswahl des Seitenbereichs und die Komprimierungsoptionen. Ein funktionierendes Beispiel finden Sie auf der durchsuchbaren PDF-Beispielseite .
Charles Tesserakt API zu IronOCR Mapping-Referenz
| Charles Tesserakt | IronOCR-Äquivalent |
|---|---|
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 (0–100 Skala) |
page.GetIterator() |
result.Pages, result.Words (direkte Sammlungen) |
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 (direkt iterieren) |
EngineMode.Default |
Automatisch (Tesseract 5 LSTM-Standard) |
EngineMode.TesseractOnly |
ocr.Configuration.PageSegmentationMode |
Manuelle Tessdata .traineddata Datei |
dotnet add package IronOcr.Languages.French |
TessDataPath Konstante + .csproj Kopieren-Eintrag |
Nicht zutreffend – gebündelt |
Pix.LoadFromFile() über Leptonica DLL |
input.LoadImage() — keine native DLL erforderlich |
Plattform GetTessDataPath() Methode |
Nicht zutreffend – gestrichen |
leptonica-1.82.0.dll / libleptonica-dev |
Nicht zutreffend – keine Abhängigkeit von Leptonica |
| Manuelle Extraktion von temporären Frames aus TIFF-Dateien | input.LoadImageFrames(tiffPath) |
| Keine durchsuchbare PDF-Ausgabe | result.SaveAsSearchablePdf(outputPath) |
new TesseractEngine() pro Thread |
Ein IronTesseract — thread-sicher |
Gängige Migrationsprobleme und Lösungen
Problem 1: DllNotFoundException für Leptonica- oder Tesseract-Binärdateien
Charlesw Tesseract: System.DllNotFoundException: Unable to load DLL 'leptonica-1.82.0': The specified module could not be found. Diese Ausnahme tritt auf, wenn die Leptonica native DLL nicht am erwarteten Ort ist. Dies ist in neuen Docker-Containern, CI-Agenten oder in jeder Umgebung üblich, in der der runtimes/ Ordner des NuGet-Pakets nicht korrekt kopiert wurde.
Lösung: Entfernen Sie das Tesseract Paket. Installieren Sie IronOcr.IronOCR bündelt alle nativen Binärdateien intern und ruft das System-Leptonica nicht per P/Invoke auf. Die Ausnahme kann nicht auftreten, da keine externe Leptonica-Abhängigkeit besteht:
dotnet remove package Tesseract
:InstallCmd dotnet add package IronOcr
dotnet remove package Tesseract
:InstallCmd dotnet add package IronOcr
Keine apt-get install libleptonica-dev erforderlich. Keine <CopyToOutputDirectory> Einträge für native DLLs.
Problem 2: Tessdata-Pfadfehler nach der Bereitstellung
Charlesw Tesseract: Tesseract.TesseractException: Failed to initialise tesseract engine. Dies tritt auf, wenn TessDataPath zur Laufzeit nicht aufgelöst wird. Es kompiliert ohne Fehler, schlägt nur zur Laufzeit fehl, und der Fehlerpfad hängt von der Bereitstellungsumgebung ab.
Lösung: Das Konzept des tessdata-Pfads existiert in IronOCR nicht. Löschen Sie die Konstante, löschen Sie die CopyToOutputDirectory XML in .csproj, und löschen Sie die Fabrikmethode, die sie erstellt. Sprachdaten werden als NuGet Pakete verteilt:
# 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
Der Leitfaden für mehrere Sprachen zeigt, wie die Mehrsprachenerkennung nach dem Hinzufügen von Sprachpaketen konfiguriert wird.
Problem 3: Container-Build schlägt fehl, wenn Basisimage aktualisiert wird
Charlesw Tesseract: Das Dockerfile enthält apt-get install -y libleptonica-dev, um die Leptonica native Abhängigkeit zu befriedigen. Wenn das Basis-Image von Debian Bullseye auf Bookworm umgestellt wird oder sich der Paketname von Leptonica in verschiedenen Distributionen ändert, schlägt der Build mit einem apt-Fehler fehl. Um das Problem zu beheben, muss man wissen, welcher Paketname in der neuen Distribution verwendet werden muss.
Lösung: Entfernen Sie die Leptonica apt-get Zeile vollständig.IronOCR unter Linux erfordert nur das Standard libgdiplus Paket, das jede .NET-Anwendung benötigt, die System.Drawing bereits verwendet:
# 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
Der Docker-Bereitstellungsleitfaden bietet getestete Dockerfile-Vorlagen für gängige Basis-Images. Es ist kein charlesw-spezifischer Infrastrukturcode erforderlich.
Problem 4: Iterator-Musterbrüche auf leeren Seiten oder Seiten mit Leerzeichen
Charlesw Tesseract: Der ResultIterator gibt null von iter.GetText() auf einigen Seitensegmenten zurück, was explizite Null-Überprüfungen in der gesamten Schleife erfordert. Ein Fehlen einer Null-Überprüfung verursacht NullReferenceException auf leeren Seiten oder Bildern ohne erkennbaren Text.
Lösung:IronOCR-Ergebnissammlungen sind niemals null. Leere Seiten liefern leere Sammlungen. Prüfen Sie den Textinhalt anstatt Nullreferenzen:
// 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
Problem 5: Gewindesicherheitsverletzungen unter Last
Charlesw Tesseract: TesseractEngine is not thread-safe. Die gemeinsame Nutzung einer Instanz durch mehrere gleichzeitige Anfragen in einer ASP.NET Anwendung führt zu Zugriffsverletzungen oder fehlerhaften Ergebnissen. Die übliche Lösung besteht darin, für jeden Thread eine eigene Engine zu erstellen. Dies ist jedoch aus der API nicht ersichtlich, und die Fehlermeldungen im Fehlerfall sind kryptische native Ausnahmen.
Lösung: IronTesseract ist thread-sicher. Eine Instanz kann gleichzeitigen Anfragen dienen, oder für maximalen Durchsatz erstellen Sie eine pro Thread in einem Parallel.ForEach — beide Muster funktionieren ohne Modifikation:
// 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)
Der Leitfaden zur asynchronen OCR behandelt asynchrone Muster für ASP.NET Core Controller, bei denen Thread-Blockierung nicht akzeptabel ist.
Problem 6: ARM64-Binärdatei fehlt zur Laufzeit
Charlesw Tesseract: Auf AWS Graviton (Linux ARM64) oder Apple Silicon CI-Agenten wird das archivierte Paket möglicherweise nicht als native ARM64-Binärdatei ausgeliefert. Der Fehler ist ein DllNotFoundException oder ein BadImageFormatException bei der Engine-Erstellung — ein Laufzeitfehler auf einer Plattform, die das Paket nicht unterstützt.
Lösung:IronOCR liefert validierte ARM64-Binärdateien sowohl für Linux als auch für macOS. Bereitstellung auf ARM64 ohne Codeänderungen. Die Bereitstellungsanleitung für Linux und die Bereitstellungsanleitung für macOS bestätigen die unterstützten Laufzeitkennungen.
Charles Tesserakt Migrations-Checkliste
Vor der Migration
Überprüfen Sie den Quellcode, um alle sich ändernden Muster zu identifizieren:
# 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" .
Beachten Sie, auf welche Bereitstellungsumgebungen das Projekt abzielt (Docker, Linux, ARM64, Azure, AWS) – dies sind die Umgebungen, in denen charlesw/tesseract die meisten Konfigurationen erfordert, die IronOCR überflüssig macht.
Code-Migration
- Führen Sie
dotnet remove package Tesseractaus, um den charlesw-Wrapper zu deinstallieren - Führen Sie
dotnet add package IronOcraus, um IronOCR zu installieren - Fügen Sie
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";beim Anwendungsstart hinzu - Ersetzen Sie alle
using Tesseract;Anweisungen durchusing IronOcr; - Löschen Sie die Tessdata-Pfadkonstante und alle Methoden, die den Pfad pro Umgebung erstellen.
- Entfernen Sie alle
RuntimeInformation.IsOSPlatform()Blöcke, die für die Auswahl des Tessdata-Pfads geschrieben wurden - Entfernen Sie
<CopyToOutputDirectory>Einträge für Tessdata-Dateien aus allen.csprojDateien - Löschen Sie Tessdata
.traineddataDateien aus der Versionskontrolle oder den Bereitstellungs-Artefaktspeichern - Fügen Sie
dotnet add package IronOcr.Languages.*für jede Sprache hinzu, die zuvor als.traineddataDatei bereitgestellt wurde - Ersetzen Sie
TesseractEngine+Pix.LoadFromFile()+engine.Process()Ketten durchnew IronTesseract().Read() - Ersetzen Sie alle
Pix.LoadFromFile()undPix.LoadFromMemory()Aufrufe durchinput.LoadImage() - Ersetzen Sie alle
page.GetText()Aufrufe durchresult.Text - Ersetzen Sie die Iterator-basierte Wort-/Zeilenausgabe durch den direkten Sammlungszugriff auf
result.Pages - Ersetzen Sie die
iter.GetConfidence()Schwellenwertlogik durch LINQ aufresult.Wordsoderresult.Lines - Entfernen Sie
libleptonica-dev/leptonica-1.82.0.dllaus Dockerfiles und Bereitstellungsskripten
Nach der Migration
Bitte überprüfen Sie nach Abschluss der Codeaktualisierungen Folgendes:
- Die OCR-Funktion läuft unter Windows erfolgreich ohne native DLL-Fehler.
- OCR läuft erfolgreich in einem Docker Linux-Container ohne jegliche
apt-getÄnderungen überlibgdiplushinaus - OCR erzeugt Textausgabe auf ARM64, wenn diese Plattform in der Bereitstellungsmatrix enthalten ist.
- Mehrseitige TIFF-Dateien enthalten den Text aller Frames, nicht nur des ersten.
- Die Konfidenzfilterung liefert dieselbe logische Menge von Wörtern mit hoher Konfidenz wie die vorherige Iteratorimplementierung.
- Sprachspezifische Dokumente (Französisch, Deutsch usw.) werden nach der Installation der sprachspezifischen NuGet Pakete korrekt erkannt.
- Parallele OCR-Operationen werden ohne Ausnahmen oder fehlerhafte Ausgabe abgeschlossen.
- Es wird nun eine durchsuchbare PDF-Datei generiert, wo die vorherige Implementierung nur Text zurückgegeben hat.
- CI/CD-Pipeline-Builds ohne Tessdata-Download-Schritte oder Leptonica-Installationsbefehle
- Funktionstest anhand desselben Bildkorpus, der zur Validierung der vorherigen Implementierung verwendet wurde
Wichtigste Vorteile der Migration zu IronOCR
Eigenständiges Bereitstellungsmodell. Nach der Migration wird die OCR-Abhängigkeit vollständig durch einen einzigen NuGet -Paketverweis beschrieben. Keine Tessdata-Dateien in der Versionskontrolle, keine CopyToOutputDirectory Einträge, keine nativen DLL-Bereitstellungsschritte, keine Leptonica-Systempakete. CI/CD-Pipelines, die zuvor eine mehrstufige Artefaktverwaltung erforderten, reduzieren sich auf dotnet publish. Der für die Bereitstellung benötigte Code, der sich zur Unterstützung des CharlesWrappers angesammelt hatte, ist endgültig verschwunden.
Plattformunabhängigkeit ohne bedingte Logik. Dieselbe Anwendungsdatei läuft ohne Änderungen unter Windows x64, Linux x64, Linux ARM64, macOS x64 und macOS ARM64. Teams, die ein ARM64-Bereitstellungsziel hinzufügen – sei es AWS Graviton, Apple Silicon CI oder Raspberry Pi – schreiben keinen neuen Code zur Plattformerkennung. Die Linux-Bereitstellungsanleitung und die AWS-Bereitstellungsanleitung bestätigen die getesteten Konfigurationen.
Tesseract 5: Höhere Genauigkeit dank integrierter Vorverarbeitung. Der Sprung von Tesseract 4.1.1 zu Tesseract 5 verbessert die Erkennung auch bei beschädigten Dokumenten.IronOCR bietet zusätzlich zum Engine-Upgrade eine automatische Vorverarbeitung, bei der Entzerrung, Rauschunterdrückung, Kontrastnormalisierung und Binarisierung angewendet werden, bevor die Engine jedes Bild verarbeitet. Dokumente, für deren Erreichen akzeptabler Genauigkeitsschwellenwerte bisher eine benutzerdefinierte Vorverarbeitungspipeline erforderlich war, erreichen diese Schwellenwerte nun ohne zusätzlichen Code. Der Leitfaden zur Bildqualitätskorrektur dokumentiert explizite Vorverarbeitungsoptionen für Fälle, die über die Standardeinstellungen hinaus angepasst werden müssen.
Direkte Ergebnisnavigation ersetzt Iterator-Boilerplate. Das charlesw Iteratormuster — GetIterator(), Begin(), Next(), IsAtBeginningOf(), Null-Überprüfungen überall — wird durch einfache Sammlungen ersetzt. Wörter, Zeilen, Absätze und Seiten sind Eigenschaften des Ergebnisobjekts. Konfidenzbasierte Filterung ist ein LINQ-Ausdruck. Code, der zuvor Daten auf Wortebene extrahierte, erforderte 15–30 Zeilen Iteratorverwaltung; Das IronOCR Äquivalent sind 2–3 Zeilen. Die Seite mit den OCR-Ergebnissen fasst das vollständige strukturierte Ausgabemodell zusammen.
Suchbare PDF-Ausgabe ohne eine sekundäre Bibliothek. result.SaveAsSearchablePdf() erzeugt ein PDF mit einer Textschicht, die an erkannte Wörter ausgerichtet ist, und erfordert keine sekundäre PDF-Bibliothek. Dokumentenmanagementsysteme, die durchsuchbare PDFs verarbeiten, benötigen keinen separaten PDF-Generierungsschritt mehr. Das Ergebnisobjekt, das den extrahierten Text liefert, erstellt auch die durchsuchbare Datei, wodurch die Dokumentenverarbeitungspipelines auf eine einzige Bibliotheksabhängigkeit beschränkt bleiben.
Aktive Wartung und Abdeckung von Sicherheitspatches.IronOCR erhält regelmäßige Updates, die Verbesserungen am Tesseract-5-Modell, die Validierung der .NET Laufzeitkompatibilität und die Abdeckung von Sicherheitspatches für die zugrunde liegende C++-Engine dokumentieren. Die Abhängigkeit birgt nicht mehr das Risikoprofil eines archivierten Pakets – Compliance-Prüfungen führen nicht mehr zu Beanstandungen aufgrund fehlender Sicherheitspatches. Da .NET 10 bis 2026 allgemein verfügbar sein wird, wird das IronOCR Dokumentationsportal die aktuelle Kompatibilität widerspiegeln, ohne dass Umwege oder Abspaltungen erforderlich sind.
Häufig gestellte Fragen
Warum sollte ich von charlesw/tesseract (.NET Tesseract Wrapper) zu IronOCR migrieren?
Zu den häufigsten Gründen gehören die Beseitigung der Komplexität der COM-Interoperabilität, die Ablösung der dateibasierten Lizenzverwaltung, die Vermeidung der seitenweisen Abrechnung, die Ermöglichung der Docker-/Container-Bereitstellung und die Einführung eines NuGet-nativen Workflows, der sich in die Standard-.NET-Werkzeuge integriert.
Was sind die wichtigsten Code-Änderungen bei der Migration von charlesw/tesseract (.NET Tesseract Wrapper) zu IronOCR?
Ersetzen Sie die charlesw/tesseract-Initialisierungssequenzen durch IronTesseract-Instanziierung, entfernen Sie das COM-Lebenszyklusmanagement (explizite Create/Load/Close-Muster) und aktualisieren Sie die Namen der Ergebniseigenschaften. Das Ergebnis sind deutlich weniger Boilerplate-Zeilen.
Wie installiere ich IronOCR, um die Migration zu beginnen?
Führen Sie 'Install-Package IronOcr' in der Paketmanager-Konsole oder 'dotnet add package IronOcr' in der CLI aus. Sprachpakete sind separate Pakete: 'dotnet add package IronOcr.Languages.French' für Französisch, zum Beispiel.
Erreicht IronOCR die OCR-Genauigkeit von charlesw/tesseract (.NET Tesseract Wrapper) für Standardgeschäftsdokumente?
IronOCR erzielt eine hohe Genauigkeit bei Standardgeschäftsinhalten wie Rechnungen, Verträgen, Quittungen und getippten Formularen. Bildvorverarbeitungsfilter (Schräglagenkorrektur, Rauschunterdrückung, Kontrastverbesserung) verbessern die Erkennungsgenauigkeit bei verschlechterten Eingaben weiter.
Wie geht IronOCR mit den Sprachdaten um, die charlesw/tesseract (.NET Tesseract Wrapper) separat installiert?
Die Sprachdaten in IronOCR werden als NuGet-Pakete verteilt. mit 'dotnet add package IronOcr.Languages.German' wird die deutsche Unterstützung installiert. Es sind keine manuellen Dateiplatzierungen oder Verzeichnispfade erforderlich.
Erfordert die Migration von charlesw/tesseract (.NET Tesseract Wrapper) zu IronOCR Änderungen an der Bereitstellungsinfrastruktur?
IronOCR erfordert weniger Änderungen an der Infrastruktur als charlesw/tesseract (.NET Tesseract Wrapper). Es gibt keine SDK-Binärpfade, keine Platzierung von Lizenzdateien oder Lizenzserverkonfigurationen. Das NuGet-Paket enthält die komplette OCR-Engine, und der Lizenzschlüssel ist eine im Anwendungscode festgelegte Zeichenfolge.
Wie konfiguriere ich die IronOCR-Lizenzierung nach der Migration?
Weisen Sie IronOcr.License.LicenseKey = "YOUR-KEY" im Startup-Code der Anwendung zu. In Docker oder Kubernetes speichern Sie den Schlüssel als Umgebungsvariable und lesen ihn beim Starten aus. Verwenden Sie License.IsValidLicense zur Validierung, bevor Sie den Datenverkehr akzeptieren.
Kann IronOCR PDFs auf die gleiche Weise verarbeiten wie charlesw/tesseract?
Ja, IronOCR liest sowohl native als auch gescannte PDFs. Instanziieren Sie IronTesseract, rufen Sie ocr.Read(input) auf, wobei input ein PDF-Pfad oder OcrPdfInput ist, und iterieren Sie die OcrResult-Seiten. Es ist keine separate PDF-Rendering-Pipeline erforderlich.
Wie handhabt IronOCR das Threading bei der Verarbeitung großer Datenmengen?
IronTesseract kann sicher pro Thread instanziiert werden. Sie können eine Instanz pro Thread in einem Parallel.ForEach- oder Task-Pool aufsetzen, OCR gleichzeitig ausführen und jede Instanz nach Abschluss entsorgen. Es ist kein globaler Zustand oder Sperren erforderlich.
Welche Ausgabeformate unterstützt IronOCR nach der Textextraktion?
IronOCR liefert strukturierte Ergebnisse mit Text, Wortkoordinaten, Konfidenzwerten und Seitenstruktur. Zu den Exportoptionen gehören reiner Text, durchsuchbare PDF-Dateien und strukturierte Ergebnisobjekte für die nachgeschaltete Verarbeitung.
Ist die Preisgestaltung von IronOCR für die Skalierung von Workloads vorhersehbarer als die von charlesw/tesseract (.NET Tesseract Wrapper)?
IronOCR verwendet eine pauschale, unbefristete Lizenzierung ohne Seiten- oder Volumengebühren. Egal, ob Sie 10.000 oder 10 Millionen Seiten verarbeiten, die Lizenzkosten bleiben konstant. Optionen für Volumen- und Teamlizenzen finden Sie auf der IronOCR-Preisseite.
Was passiert mit meinen bestehenden Tests, nachdem ich von charlesw/tesseract (.NET Tesseract Wrapper) zu IronOCR migriert habe?
Tests, die extrahierte Textinhalte überprüfen, sollten auch nach der Migration bestehen. Tests, die API-Aufrufmuster oder den Lebenszyklus von COM-Objekten validieren, müssen aktualisiert werden, um das einfachere Initialisierungs- und Ergebnismodell von IronOCR widerzuspiegeln.

