跳至頁尾內容
影片

從 Charlesw Tesseract 遷移到 IronOCR

本指南指導.NET開發人員從charlesw/tesseract NuGet包(Tesseract)遷移到IronOCR。 遷移主要針對一個特定問題:charlesw封裝器強加的原生二進制部署模型以及該模型迫使開發人員編寫的平台條件程式碼。曾經在CI中徘徊於DllNotFoundException、在Linux上與Leptonica程式庫路徑角力、或編寫與OCR無關的OS檢測塊的團隊會發現,此指南顯示了切換後消失的確切內容。

為什麼從Charlesw Tesseract遷移

存檔的charlesw/tesseract包給新專案帶來麻煩不是因為API不好,而是因為它所要求的部署模型是圍繞不再成立的假設設計的,而這些假設不適合現代.NET基礎設施。 以下是驅動遷移決策的因素:

每個平台的原生二進制部署。 Tesseract NuGet包隨平台特定的原生二進制作為:tesseract50.dll適用於Windows x64,對於x86有單獨的構建,libtesseract.so適用於Linux x64。這些二進制文件必須在執行時正確放置以使P/Invoke調用成功。 在開發人員工作站上,SDK會自動複製它們。 在Docker容器、ARM64構建代理或具有非標準應用程式根目錄的Azure App Service中,它們不會自動複製。 每個新的部署物件都會變成一個除錯會話。

Leptonica作為隱藏的依賴。 Tesseract的圖像載入是由Leptonica庫處理的,它與Tesseract二進制作為自己的原生DLL集分發。 在Windows上,leptonica-1.82.0.dll必須存在於輸出目錄中。 在Linux上,Leptonica共享庫必須捆綁或作為系統包安裝。 沒有Pix.LoadFromFile()處失敗,會出現無助於除錯的原生異常,並且修復它需要知道哪個系統包能解決依賴問題。

應用程式邏輯中的平台條件程式碼。 僅憑原生二進制載入和tessdata路徑解析的結合,迫使開發人員編寫RuntimeInformation.IsOSPlatform()檢查、容器上下文的環境變數檢測和按目標而異的路徑生成邏輯。 這些程式碼都不是OCR邏輯。 這是純粹因為包的二進制管理不完整而存在的部署箝制。

沒有補救路徑的存檔包。 自2021年以來,儲存庫已被存檔。當Linux主機上的系統包更新更改Leptonica ABI,或新.NET運行時更改原生二進制載入行為時,沒有版本可以更新。 唯一的選擇是fork原生構建管道或更換庫。

Tesseract 4.1.1 引擎凍結。 該包封裝了Tesseract 4.1.1。Tesseract 5重新編寫的LSTM模型在劣化文件上提供了顯著更高的精度。 該升級無法透過charlesw包獲得——需要更換庫。

缺乏標準模式的信心處理。 charlesw封裝器將iter.GetConfidence(PageIteratorLevel.Word)。 沒有標準的過濾API; 每個團隊都以不同的方式實施他們自己的門檻邏輯。

根本問題

charlesw封裝器需要在OCR運行之前配置平台特定的原生二進制:

// 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
$vbLabelText   $csharpLabel

IronOCR沒有原生二進制配置:

// 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
$vbLabelText   $csharpLabel

IronOCRvs Charlesw Tesseract:功能比較

下表涵蓋與評估此遷移相關的功能:

功能 Charlesw Tesseract IronOCR
維護狀態 存檔(自2021年起無更新) 積極維護
Tesseract引擎版本 4.1.1(凍結) 5(目前,已優化)
授權 Apache 2.0(免費) 商業($999–$2,999 永久)
NuGet安裝 Tesseract IronOcr
原生二進制管理 每個平台的DLL部署需要手動進行 捆綁,不需設定
Leptonica依賴 需要leptonica-1.82.0.dll / libleptonica-dev 不適用(內部處理)
Tessdata管理 手動下載和.csproj複製條目 NuGet語言包
平台條件程式碼 多目標部署需要 不需要
Docker部署 需要明確的tessdata COPY + Leptonica apt-get 僅標準.NET容器要求
ARM64支援 存檔後未確認 捆綁,已驗證
圖像輸入格式 TIFF、PNG、BMP、JPG(透過Leptonica) JPG、PNG、BMP、TIFF、GIF等
多頁TIFF 手動框架迭代 input.LoadImageFrames()
本地PDF輸入 不(需要次要庫)
可搜尋的PDF輸出 不是 是(result.SaveAsSearchablePdf()
內嵌預處理 None Deskew、去噪、對比度、二值化、銳化、縮放、膨脹、侵蝕、反轉
信心過濾API 手動迭代器與GetConfidence() result.Confidence, word.Confidence
結構化結果 迭代器模式(ResultIterator 直接集合(頁、段落、行、詞)
條碼識別 不是 是(在OCR處理期間)
基於區域的OCR 不是 是(CropRectangle
執行緒安全 呼叫者責任 內建
超過125種語言包 手動tessdata下載 dotnet add package IronOcr.Languages.*
跨平台.NET 是(.NET Standard 2.0) 是(.NET Framework 4.6.2+、.NET 5/6/7/8/9)
安全補丁節奏 無(存檔) 定期發佈

快速啟動:Charlesw Tesseract到IronOCR的遷移

步驟1:替換NuGet包

移除charlesw Tesseract包:

dotnet remove package Tesseract
dotnet remove package Tesseract
SHELL

NuGet安裝IronOCR:

dotnet add package IronOcr

步驟2:更新命名空間

// Before (charlesw Tesseract)
using Tesseract;

// After (IronOCR)
using IronOcr;
// Before (charlesw Tesseract)
using Tesseract;

// After (IronOCR)
using IronOcr;
Imports IronOcr
$vbLabelText   $csharpLabel

步驟3:初始化許可證

在應用程式啟動時新增此調用一次,在任何OCR操作運行之前:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

免費試用授權在IronOCR授權頁面可獲得。 試用去除了輸出水印,並啟用了完整API存取。

程式碼遷移範例

移除原生二進制路徑配置

charlesw/tesseract專案中最常見的初始化模式是一個構建tessdata路徑並配置每個環境的原生庫載入的工廠或助手類。 這段程式碼純粹是由於封裝器的部署模型存在。

Charlesw Tesseract 方法:

// 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
$vbLabelText   $csharpLabel

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)
$vbLabelText   $csharpLabel

整個OcrEngineFactory類被刪除。 平台條件的路徑邏輯、DOTNET_RUNNING_IN_CONTAINER檢查和Leptonica DLL依賴都隨之消失。 每個環境——開發人員工作站、CI代理、Docker容器、雲VM——都運行相同的兩行程式碼。 IronTesseract安裝指南涵蓋了當預設設定需要調整時的配置選項,但對於大多數部署來說不需要這些調整。

Leptonica圖像轉換替換

charlesw封裝器使用Leptonica的Pix型別作為其圖像表示。 任何在OCR之前操作圖像的程式碼都必須透過Pix進行轉換,這需要Leptonica原生DLL載入和操作。 使用OcrInput替換此模式完全消除了Leptonica依賴。

Charlesw Tesseract 方法:

// 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)
{
    //不是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)
{
    //不是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
        '不是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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

臨時文件的往返消失。 沒有文件寫入磁碟,沒有調用Leptonica DLL進行轉換,也沒有finally塊需要清理。圖像輸入指南流輸入指南記錄了所有支持的輸入來源,包括從URL和記憶體映射文件載入。

信心門檻過濾

charlesw封裝器在兩個層次上暴露信心:iter.GetConfidence(PageIteratorLevel.Word)對個別字詞。 從輸出中過濾低置信度的單詞需要手動管理迭代器迴圈。 IronOCR直接在結果物件中暴露信心,將門檻邏輯轉化為LINQ表達式。

Charlesw Tesseract 方法:

// 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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

迭代器狀態機消失。 IronOCR的信心值始終在0到100範圍內,不需要除以100。 信心分數指南涵蓋了每個單詞、每行和每頁的信心存取模式。 閱讀結果指南展示了如何導航完整的結構化結果層級。

多頁TIFF批處理

在文件掃描工作流中,多幀TIFF文件很常見。 charlesw封裝器沒有內建的多幀TIFF支持; 每個幀必須在處理前手動提取。 IronOCR原生處理多幀TIFF,只需一次載入調用。

Charlesw Tesseract 方法:

// 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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

臨時文件提取迴圈和每幀處理鏈消失。 透過FrameDimension.Page檢測幀數消失。 IronOCR將TIFF幀映射到OcrResult.Pages,因此每幀文字存取不需要額外的迭代邏輯。 TIFF/GIF輸入指南涵蓋了幀選擇和部分TIFF處理的其他選項。

可搜尋PDF生成

charlesw封裝器僅生成文字輸出。 將掃描文件轉換為可搜尋的PDF——文件管理系統的一個常見要求——需要一個次要的PDF庫(IronPDF、PDFSharp或類似庫)將提取的文字覆蓋在原始圖像頁上。 IronOCR透過一個方法調用生成可搜尋的PDF,無需次級庫。

Charlesw Tesseract 方法:

// 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
$vbLabelText   $csharpLabel

IronOCR方法:

// SaveAsSearchablePdf produces a PDF/A-compatible searchable document
//不是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
//不是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
'不是secondary 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
$vbLabelText   $csharpLabel

SaveAsSearchablePdf()將OCR文字嵌入為對齊到識別字詞的隱藏層,使文件變得全文字可搜尋,並且不改變其外觀。 可搜尋PDF操作指南涵蓋頁面範圍選擇和壓縮選項。 可用的工作範例在可搜尋PDF範例頁面上有提供。

Charlesw TesseractAPI 到IronOCR映射參考

Charlesw Tesseract 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(0–100範圍)
page.GetIterator() result.Words(直接集合)
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(直接迭代)
EngineMode.Default 自動(Tesseract 5 LSTM預設)
EngineMode.TesseractOnly ocr.Configuration.PageSegmentationMode
手動tessdata .traineddata文件 dotnet add package IronOcr.Languages.French
TessDataPath常數 + .csproj複製條目 不適用──捆綁
Pix.LoadFromFile()透過Leptonica DLL input.LoadImage() ——無需原生DLL
平台GetTessDataPath()方法 不適用——淘汰
leptonica-1.82.0.dll / libleptonica-dev 不適用——無Leptonica依賴
手動臨時文件框架提取供TIFF使用 input.LoadImageFrames(tiffPath)
無可搜尋PDF輸出 result.SaveAsSearchablePdf(outputPath)
new TesseractEngine()每執行緒 一個IronTesseract——執行緒安全

常見的遷移問題与解決方案

問題1:Leptonica 或 Tesseract 二進制未找到的DllNotFoundException

Charlesw Tesseract: System.DllNotFoundException: Unable to load DLL 'leptonica-1.82.0': The specified module could not be found. 當Leptonica原生DLL不在預期位置時會觸發此異常。 在全新Docker容器、CI代理或NuGet包的runtimes/目錄未正確複製的任何環境中很常見。

解決方案: 移除Tesseract包。 安裝IronOcr。 IronOCR將所有原生二進制捆綁在內部,不會P/Invoke到系統Leptonica。 由於沒有外部Leptonica依賴,因此不會發生例外狀況:

dotnet remove package Tesseract
:InstallCmd dotnet add package IronOcr
dotnet remove package Tesseract
:InstallCmd dotnet add package IronOcr
SHELL

無需apt-get install libleptonica-dev。 原生DLL的<CopyToOutputDirectory>條目同樣不需要。

問題2:部署後tessdata路徑錯誤

Charlesw Tesseract: Tesseract.TesseractException: Failed to initialise tesseract engine.TessDataPath在運行時無法解析時觸發。它在編譯時沒有報錯,僅在運行時失敗,失敗路徑取決於部署環境。

解決方案: IronOCR中不存在tessdata路徑概念。 刪除常量、刪除.csproj中的XML,並刪除構建它的工廠方法。 語言資料作為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
SHELL

多語言指南顯示如何在新增語言包後配置多語言識別。

問題3:基礎映像更新時容器構建崩潰

Charlesw Tesseract: Dockerfile包含apt-get install -y libleptonica-dev以滿足Leptonica的原生依賴。 當基本映像從Debian Bullseye移動到Bookworm,或在分發過程中更改Leptonica包名稱時,構建會因apt錯誤而崩潰。 修復它需要知道在新分發上使用哪個包名。

解決方案:完全移除Leptonica apt-get行。 Linux上的IronOCR僅需標準libgdiplus包,此任何使用System.Drawing的.NET應用程式已經需要:

# 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

Docker部署指南提供經測試的Dockerfile模板適用於常見的基本映像。 不需要特定於charlesw的基礎設施程式碼。

問題4:迭代器模式在空白或空格頁上失效

Charlesw Tesseract: NullReferenceException

解決方案: IronOCR結果集合從不為null。 空白頁面返回空集合。 檢查文字內容而非空值引用:

// 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
$vbLabelText   $csharpLabel

問題5:負載下的執行緒安全違規

Charlesw Tesseract: TesseractEngine不支持執行緒安全。 在ASP.NET應用程式中共享一個實例給並發請求會導致存取違規或結果損壞。 標準修正是在每個執行緒建立一個引擎,但這不是從API可以明顯看出的,當錯誤發生時,錯誤消息是難以理解的原生異常。

解決方案: IronTesseract支持執行緒安全。 一個實例可以服務並發請求,或為最大吞吐量,每個執行緒建立一個Parallel.ForEach——這兩種模式的工作不需要修改:

// 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)
$vbLabelText   $csharpLabel

async OCR指南涵蓋ASP.NET Core控制器的异步模式,執行緒阻塞不被接受。

問題6:運行時缺少ARM64二進制

Charlesw Tesseract:在AWS Graviton(Linux ARM64)或Apple Silicon CI代理上,存檔包可能不提供ARM64原生二進制。 故障是BadImageFormatException在引擎建立時——一個包無法支持的平台上的運行時錯誤。

解決方案: IronOCR提供經驗證的ARM64二進制適用於Linux和macOS。 部署到ARM64無需程式碼更改。 Linux部署指南macOS部署指南確認了支持的運行時標識符。

Charlesw Tesseract遷移清單

遷移前

審計程式碼庫以識別所有將改變的模式:

# 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" .
SHELL

註釋項目所針對的部署環境(Docker、Linux、ARM64、Azure、AWS)——這些是charlesw/tesseract需要最多配置而IronOCR消除這種配置的環境。

程式碼遷移

1.運行dotnet remove package Tesseract解除安裝charlesw包裝器 2.運行dotnet add package IronOcr安裝IronOCR 3.在應用程式啟動時新增IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; 4.用using Tesseract;語句 5.刪除tessdata路徑常量及任何每環境建立路徑的方法 6.刪除為選擇tessdata路徑而寫的所有RuntimeInformation.IsOSPlatform()塊 7.從所有<CopyToOutputDirectory>條目 8.從源控管或部署工件儲存中刪除tessdata .traineddata文件 9.對每個先前部署作為dotnet add package IronOcr.Languages.* 10.用TesseractEngine + Pix.LoadFromFile() + engine.Process()鏈 11.將所有input.LoadImage() 12.將所有result.Text 13.用result.Pages上的直接集合存取替換基於迭代器的單詞/行提取 14.用LINQ在iter.GetConfidence()門檻邏輯 15.從 Dockerfile 和部署腳本中移除 libleptonica-dev / leptonica-1.82.0.dll

遷移後

完成程式碼更新後檢查以下內容:

  • OCR在Windows上運行成功,沒有任何原生DLL錯誤
  • OCR在Docker Linux容器中運行成功,除apt-get變更
  • 如果部署矩陣中包含該平台,OCR在ARM64上產生文字輸出
  • 多頁TIFF文件不只在第一幀返回文字,而是在所有幀上返回文字
  • 信任過濾返回與之前迭代器實現相同邏輯集的高信任度單詞
  • 安裝語言NuGet包後,語言特定文件(法語、德語等)正確識別
  • 並行OCR操作無異常或損壞輸出完成
  • 以前僅返回文字的實現現在產生可搜尋PDF輸出
  • CI/CD管道構建時沒有任何tessdata下載步驟或Leptonica安裝命令 對同一圖像組進行驗證,做為過去實現的煙霧測試

遷移至IronOCR的主要好處

自包裝部署模型。 遷移後,OCR依賴由一個NuGet包引用完全描述。 源控制中無tessdata文件,無CopyToOutputDirectory條目,無原生DLL部署步驟,無Leptonica系統包。 以前需要多步工件管理的CI/CD管道簡化為dotnet publish。 為支持charlesw包裝器而積累的與部署相關的程式碼永久消失。

平台可移植性無需條件邏輯。 相同的應用程式二進制作為可在Windows x64、Linux x64、Linux ARM64、macOS x64和macOS ARM64上運行,無需修改。 無論是AWS Graviton、Apple Silicon CI還是樹莓派,增加ARM64部署目標的團隊都不再編寫新的平台檢測程式碼。 Linux部署指南AWS部署指南確認了經測試的配置。

Tesseract 5在內建前處理的準確性。從Tesseract 4.1.1到Tesseract 5的躍升提高了在劣化文件上的識別。 IronOCR在引擎升級之上增加了自動預處理,在引擎處理每個圖片前應用Deskew、去噪、對比度正規化和二值化。 以前需要自定義預處理管道才能達到可接受準確度門檻的文件現在不需要額外程式碼即可達到這些門檻。 圖像質量校正指南記錄了需要超過預設值調整的情況時的明確預處理選項。

直接結果導航替換了迭代器樣板。 charlesw迭代器模式——GetIterator(), Begin(), Next(), IsAtBeginningOf(), 全程空值檢查——被簡單集合取代。 詞、行、段落和頁為結果物件上的屬性。 基於信心的過濾是一個LINQ表達式。 提取詞彙資料的程式碼以前需要15–30行迭代器管理; IronOCR等價只需2–3行。 OCR結果功能頁匯總了完整的結構化輸出模型。

無需次級庫即可生成可搜尋PDF輸出。result.SaveAsSearchablePdf()產生一個帶有對齊到識別字詞的文字層的PDF,不需要次級PDF庫。 接受可搜尋PDF的文件管理系統不再需要單獨的PDF生成步驟。提供提取文字的相同結果物件還寫入可搜尋文件,將文件處理管道保持在單一庫依賴。

積極維護和安全補丁覆蓋。 IronOCR接收定期更新,跟踪Tesseract 5模型的改進、.NET運行環境相容性驗證以及基礎C++引擎的安全補丁覆蓋。依賴不再承擔存檔包的風險,合規審查不會為缺少的安全補丁路徑生成發現。 隨著.NET 10自2026年普遍可用,IronOCR文件中心將反映當前相容性,無需變通或分支。

請注意PDFSharp 和 Tesseract 是它們各自所有者的注冊商標。 本網站與Google或empira Software GmbH無關,未經其認可或贊助。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供資訊用途,並反映撰寫時獲得的公開資訊。

常見問題

為什麼我應該從charlesw/tesseract(.NET Tesseract包裝器)遷移到IronOCR?

常見的驅動因素包括消除COM互操作複雜性、更換基於文件的許可證管理、避免按頁收費、啟用Docker/容器部署,以及採取與標準.NET工具整合的NuGet本地工作流。

從charlesw/tesseract(.NET Tesseract包裝器)遷移到IronOCR時,主要的程式碼變更有哪些?

將charlesw/tesseract的初始化序列替換為IronTesseract實例化,移除COM生命周期管理(顯式建立/載入/關閉模式),並更新結果屬性名稱。結果是顯著減少了樣板程式碼行數。

如何安裝IronOCR以開始遷移?

在套件管理器控制台中運行 'Install-Package IronOcr' 或在CLI中運行 'dotnet add package IronOcr'。語言包是單獨的包:例如 'dotnet add package IronOcr.Languages.French' 安裝法語支持。

IronOCR的OCR準確度是否能與charlesw/tesseract(.NET Tesseract包裝器)對標準商務文件的準確度相匹配?

IronOCR在包括發票、合同、收據和鍵入的表單等標準業務內容上達到高準確性。圖像預處理過濾器(糾偏、噪音去除、對比度增強)進一步提高了變質輸入的識別。

IronOCR如何處理charlesw/tesseract(.NET Tesseract包裝器)需獨立安裝的語言資料?

IronOCR中的語言資料分發為NuGet包。'dotnet add package IronOcr.Languages.German' 安裝德語支持。不涉及手動文件放置或目錄路徑。

從charlesw/tesseract(.NET Tesseract包裝器)遷移到IronOCR是否需要對部署架構進行更改?

相較於charlesw/tesseract(.NET Tesseract包裝器),IronOCR所需的架構更改更少。無需SDK二進位路徑、授權文件放置或授權伺服器配置。NuGet套件包含完整的OCR引擎,而授權金鑰是應用程式程式碼中的一個字串。

遷移後如何配置IronOCR許可證?

在應用啟動程式碼中分配IronOcr.License.LicenseKey = "YOUR-KEY"。在Docker或Kubernetes中,將金鑰儲存為環境變數並在啟動時讀取。在接受流量之前,使用License.IsValidLicense驗證。

IronOCR是否能以與charlesw/tesseract相同的方式處理PDF?

是的。IronOCR能讀取本地和掃描的PDF。實例化IronTesseract,調用ocr.Read(input),其中input是PDF路徑或OcrPdfInput,並迭代OcrResult頁面。不需要單獨的PDF渲染管道。

IronOCR如何處理大批量處理中的多執行緒?

IronTesseract可以安全地在每個執行緒中實例化。在Parallel.ForEach或Task池中為每個執行緒建立一個實例,並發併運行OCR,當完成時處置每個實例。不需要全域狀態或鎖定。

IronOCR在文字提取後支持哪些輸出格式?

IronOCR返回結構化結果,包括文字、單詞坐標、信心分數和頁面結構。導出選項包括純文字、可搜索PDF以及下游處理的結構化結果物件。

在擴展工作負載時,IronOCR的價格是否比charlesw/tesseract(.NET Tesseract包裝器)更具可預測性?

IronOCR使用固定費率的永久性許可證,沒有按頁或按量收費。無論您處理10000頁還是1000萬頁,許可證費用保持不變。團隊和批量許可證選項可在IronOCR定價頁面上找到。

遷移從charlesw/tesseract(.NET Tesseract包裝器)到IronOCR後,我現有的測試會怎麼樣?

遷移後,斷言提取的文字內容的測試應繼續通過。需要更新的測試是驗證API調用模式或COM物件生命週期,這需要反映IronOCR較簡單的初始化和結果模型。

Kannaopat Udonpant
軟體工程師
在成為軟體工程師之前,Kannapat在日本北海道大學完成了環境資源博士學位。在攻讀學位期間,Kannapat還成為車輛機器人實驗室的一員,該實驗室隸屬於生產工程系。在2022年,他憑藉C#技能加入了Iron Software的工程團隊,專注於IronPDF。Kannapat珍視他的工作,因為他能直接向撰寫大部分IronPDF程式碼的開發者學習。除了同儕學習,Kannapat還喜歡在Iron Software工作的社交方面。不寫程式碼或文件時,Kannapat通常在他的PS5上玩遊戲或重看The Last of Us。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話