跳至页脚内容
视频

从 Charlesw Tesseract 迁移到 IronOCR

本指南指导.NET开发人员从charlesw/tesseract NuGet包(Tesseract)迁移到IronOCR。 迁移的重点在于一个特定问题:charlesw包装器强加的本机二进制部署模型以及该模型强制开发人员编写的平台条件代码。那些在CI中苦斗DllNotFoundException、处理Linux上的Leptonica库路径或编写与OCR无关的操作系统检测代码块的团队将发现本指南准确指出了切换后消失的内容。

为什么要从 查尔斯·特塞拉克 迁移?

存档的charlesw/tesseract包使新项目陷入麻烦的原因不是因为API不好,而是因为它要求的部署模型基于在现代.NET基础架构中不成立的假设。 以下是影响迁移决策的因素:

每个平台的本机二进制部署。 Tesseract NuGet包提供特定平台的本机二进制文件:Windows x64的tesseract50.dll,x86的单独构建,Linux x64的libtesseract.so。这些二进制文件必须在运行时放置在正确的位置才能使P/Invoke调用成功。 在开发者工作站上,SDK 会自动复制它们。 在 Docker 容器、ARM64 构建代理或具有非标准应用程序根目录的 Azure 应用服务中,它们不会。 每个新的部署目标都会变成一个调试会话。

Leptonica 作为隐藏依赖项。Tesseract的图像加载由 Leptonica 库处理,该库作为一套独立的本地 DLL 与 Tesseract 二进制文件一起发布。 在Windows上,leptonica-1.82.0.dll必须出现在输出目录中。 在 Linux 系统上,Leptonica 共享库必须捆绑安装或作为系统软件包安装。 没有Pix.LoadFromFile()时会出现无用的本机异常,修复它需要知道哪种系统包能解决此依赖关系。

应用程序逻辑中的平台条件代码。 本机二进制加载和tessdata路径解析的组合迫使开发人员编写RuntimeInformation.IsOSPlatform()检查、用于容器环境的环境变量检测以及因目标不同而异的路径构建逻辑。 这些代码中没有OCR逻辑。 它是部署基础设施,其存在的唯一原因是软件包的二进制管理不完善。

软件包已归档,无修复路径。该存储库自 2021 年起已归档。当 Linux 主机上的系统软件包更新更改 Leptonica ABI,或新的.NET运行时更改本机二进制文件加载行为时,没有可供更新的版本。 唯一的选择是修改原生构建流程或替换库。

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

IronOCR与 Charlesw Tesseract:功能对比

下表列出了评估此迁移方案的团队需要考虑的功能:

特征 查尔斯·特塞拉克 IronOCR
维护状态 已存档(自 2021 年以来未更新) 积极维护
Tesseract 引擎版本 4.1.1(已冻结) 5(当前,已优化)
许可 Apache 2.0(免费) 商业($999–$2,999永久)
NuGet安装 Tesseract IronOcr
原生二进制管理 手动按平台部署 DLL 捆绑式零配置
轻子依赖性 需要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 去斜、降噪、对比度、二值化、锐化、缩放、膨胀、腐蚀、反转
置信度过滤 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 路径并为每个环境配置本地库加载。 这段代码的存在完全是因为封装器的部署模型。

查尔斯·特塞拉克方法:

// 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 容器、云虚拟机——都会执行相同的两行代码。 IronTesseract 设置指南涵盖了在需要调整默认值时需要进行的配置选项,但对于大多数部署来说,不需要任何调整。

Leptonica图像转换替换

charlesw包装器使用Leptonica的Pix类型作为其图像表示。 任何在OCR之前处理图像的代码必须通过Pix进行转换,这需要加载并操作Leptonica本机DLL。 用OcrInput替换此模式可完全消除Leptonica依赖性。

查尔斯·特塞拉克方法:

// 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 表达式。

查尔斯·特塞拉克方法:

// 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 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 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);
}
Imports System

' 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 示例页面提供了一个可运行的示例。

查尔斯·特塞拉克 API 到IronOCR映射参考

查尔斯·特塞拉克 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.Pages, 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 异常

查尔斯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 路径错误

查尔斯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:基础镜像更新时容器构建失败

查尔斯Tesseract: Dockerfile包括apt-get install -y libleptonica-dev以满足Leptonica本机依赖性。 当基础镜像从 Debian Bullseye 迁移到 Bookworm,或者当 Leptonica 软件包名称在不同发行版之间发生变化时,构建会因 apt 错误而中断。 要解决这个问题,需要知道在新发行版中应该使用哪个软件包名称。

解决方案: 完全删除Leptonica apt-get行。 Linux上的IronOCR只需要任何使用System.Drawing的.NET应用程序所需的标准libgdiplus包:

# 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模板。 无需编写任何 CharlesWw 特定的基础设施代码。

问题 4:迭代器模式在空白页或空格页上断开

查尔斯Tesseract: NullReferenceException

解决方案: IronOCR结果集合永远不会为空。 空白页面返回空集合。 检查文本内容,而不是空引用:

// 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:负载下的螺纹安全违规

查尔斯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

异步 OCR 指南涵盖了ASP.NET Core控制器的异步模式,其中线程阻塞是不可接受的。

问题 6:运行时缺少 ARM64 二进制文件

Charlesw Tesseract:在 AWS Graviton(Linux ARM64)或 Apple Silicon CI 代理上,归档的软件包可能不会提供 ARM64 本地二进制文件。 失败是BadImageFormatException——这是一个在包无法支持的平台上的运行时错误。

解决方案: IronOCR提供经过验证的适用于 Linux 和 macOS 的 ARM64 二进制文件。 无需修改代码即可部署到 ARM64。 Linux 部署指南macOS 部署指南确认了支持的运行时标识符。

查尔斯·特塞拉克 迁移清单

迁移前

审核代码库,找出所有需要更改的模式:

# 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. Pix.LoadFromMemory()调用
  12. page.GetText()调用
  13. 将基于迭代器的单词/行提取替换为result.Pages上的直接集合访问
  14. 用LINQ替换iter.GetConfidence()阈值逻辑
  15. 从Dockerfile和部署脚本中移除libleptonica-dev / leptonica-1.82.0.dll

后迁移

代码更新完成后,请核实以下内容:

  • OCR 在 Windows 系统上运行成功,未出现任何原生 DLL 错误。
  • OCR在Docker Linux容器中成功运行,无需进行libgdiplus
  • 如果部署矩阵中包含 ARM64 平台,则 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 上运行。 添加 ARM64 部署目标(无论是 AWS Graviton、Apple Silicon CI 还是 Raspberry Pi)的团队无需编写新的平台检测代码。 Linux部署指南AWS部署指南证实了已测试的配置。

Tesseract 5 内置预处理功能,准确率更高。从 Tesseract 4.1.1 升级到 Tesseract 5,显著提高了对劣化文档的识别率。 IronOCR在引擎升级的基础上增加了自动预处理功能,在引擎处理每张图像之前应用去斜、去噪、对比度归一化和二值化。 以前需要自定义预处理流程才能达到可接受的准确度阈值的文档,现在无需额外代码即可达到这些阈值。 图像质量校正指南详细记录了需要超出默认设置进行调整的情况的明确预处理选项。

直接结果导航取代迭代器模板代码。 charlesw迭代器模式——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”,或在命令行界面中运行“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 是否需要更改部署基础架构?

IronOCR 比 charlesw/tesseract(.NET Tesseract 封装库)所需的架构变更更少。它无需 SDK 二进制文件路径、许可证文件放置位置或许可证服务器配置。NuGet 包包含完整的 OCR 引擎,许可证密钥是应用程序代码中设置的字符串。

迁移后如何配置 IronOCR 许可?

在应用程序启动代码中,将 IronOcr.License.LicenseKey 赋值为 "YOUR-KEY"。在 Docker 或 Kubernetes 中,将此密钥存储为环境变量,并在启动时读取。使用 License.IsValidLicense 在接受流量之前进行验证。

IronOCR 能否像 charlesw/tesseract 那样处理 PDF 文件?

是的。IronOCR 可以读取原生 PDF 和扫描版 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采用永久统一费率许可模式,不收取任何页数或数量费用。无论您处理1万页还是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 上玩游戏或重温《最后生还者》。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我