跳至页脚内容
视频

从 Asprise OCR 迁移到 IronOCR

本指南将引导.NET开发人员完成用IronOCR替换Asprise OCR的每一步。 它涵盖了机械包交换、命名空间更改以及占生产.NET应用程序中 Asprise 使用量大多数的四种代码迁移模式。 目标受众是已经决定迁移并且需要具体行动计划的开发人员。

为什么要从Asprise OCR迁移?

Asprise OCR 最初是作为一款 Java 产品设计的。其.NET版本只是对源自 Java 的原生引擎的封装,而这种原生引擎的本质决定了该库在.NET中的方方面面——从部署到 API 设计再到许可限制。

JRE和本机二进制依赖。Asprise OCRfor .NET要求在每个运行应用程序的机器上都存在平台特定的本机二进制文件(libaocr.dylib)。 每个二进制文件都必须与目标平台和处理器架构完全匹配。 使用32位DLL构建的64位Docker容器在运行时抛出DllNotFoundException。 这两个错误都不会在构建时显现出来。每个新的部署目标——无论是新服务器、新容器镜像还是 CI 代理——都需要手动加载二进制文件。

来自Java传承的字符串常量API。 Asprise为识别类型和输出格式公开了整数常量:Ocr.OUTPUT_FORMAT_XML。 这些常量直接映射到 Java SDK 的基于整数的 API。 .NET开发人员无法获得有关有效常量值的 IntelliSense 指导,无法获得有关参数组合的编译时安全性,也无法获得强类型的结果对象。 提取结构化输出需要手动解析 XML 字符串。

Asprise不提供原生异步 API,只能通过变通方法实现异步功能。 将同步Asprise调用包装在Task.Run中以避免阻塞ASP.NET线程会导致线程池压力,没有解决禁止在LITE和STANDARD层上并发执行的许可证限制。 现代.NET应用程序中的异步模式(后台服务、最小 API 端点、Azure Functions)在 Asprise 中没有完全对应的功能。

多帧 TIFF 处理需要手动分割。Asprise处理的是单个图像文件。 处理多页 TIFF 文件需要使用外部代码将帧分割成单独的文件,然后循环处理每个文件。帧元数据或页码不会传递到输出文件中。

线程限制会阻碍生产环境部署。LITELite(约 299 美元)和 STANDARD 版(约 699 美元)许可证在合同中规定,程序只能在单个线程和单个进程中执行。 ASP.NET Core使用线程池处理所有 HTTP 请求。 在这些层级上,每个调用 Asprise 的 Web API 端点都会从第一个并发请求开始构成许可违规。升级到Enterprise可以解除此限制,但需要联系销售部门,价格尚未公布——根据部署范围的不同,预计费用在 2,000 美元到 5,000 美元以上不等。

输出格式处理需要字符串解析。 当指定OUTPUT_FORMAT_XML时,Asprise返回一个原始XML字符串。 该应用程序负责反序列化该字符串,验证其结构,并提取单词及其坐标。 每个单词的置信度得分都嵌入在 XML 属性中。 没有对象模型,只有字符串操作。

基本问题

Asprise 需要 JRE 相邻的本地二进制配置,才能执行第一个 OCR 调用。 IronOCR除了一个NuGet包之外,不需要任何其他东西:

// Asprise: native binary must exist in PATH or application directory
// aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp();                              // Static init — touches native binary
Ocr ocr = new Ocr();
ocr.StartEngine("eng", Ocr.SPEED_FAST);  // Allocates native engine memory
string text = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT);
ocr.StopEngine();                         // Must call or native memory leaks
// Asprise: native binary must exist in PATH or application directory
// aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp();                              // Static init — touches native binary
Ocr ocr = new Ocr();
ocr.StartEngine("eng", Ocr.SPEED_FAST);  // Allocates native engine memory
string text = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT);
ocr.StopEngine();                         // Must call or native memory leaks
' Asprise: native binary must exist in PATH or application directory
' aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp()                              ' Static init — touches native binary
Dim ocr As New Ocr()
ocr.StartEngine("eng", Ocr.SPEED_FAST)   ' Allocates native engine memory
Dim text As String = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
ocr.StopEngine()                         ' Must call or native memory leaks
$vbLabelText   $csharpLabel
// IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read(imagePath).Text;
// IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read(imagePath).Text;
' IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text As String = New IronTesseract().Read(imagePath).Text
$vbLabelText   $csharpLabel

IronOCR与 Asprise OCR:功能对比

下表列出了开发人员在评估此迁移时最关心的功能。

特征 Asprise OCR IronOCR
主要平台 Java(传统版) .NET原生
NuGet安装 封装器 + 平台原生 DLL 单个包(IronOcr
运行时需要本地二进制文件。 是的(每个平台一个 DLL 文件)
.NET API 风格 整数常量,字符串返回值 强类型类和枚举
IDisposable / using模式 未实施 是(OcrInput
异步OCR 没有原生支持 是(ReadAsync
多线程 —Lite/标准版 许可证禁止 允许
多线程——所有层级 仅限Enterprise 所有级别
ASP.NET Core Web API 支持 Enterprise要求 任何级别
Azure Functions / AWS Lambda Enterprise要求 任何级别
原生 PDF 输入
多帧 TIFF 输入 否(手动分割帧) 是(LoadImageFrames
字节数组和流输入 有限的
内置图像预处理 是的(9+ 个过滤器)
可搜索的 PDF 输出 是(SaveAsSearchablePdf
结构化结果对象模型 否(仅限 XML 字符串) 是的(页数、段落数、字数、字符数)
逐词置信度得分 否(XML属性解析) 是(result.Confidence
单词像素坐标 XML属性解析 强类型属性
语言数量 20岁以上 125+
强类型语言选择 否(字符串代码) 是(OcrLanguage枚举)
条形码读取 是的(单独识别类型) 是的(配置标志)
hOCR导出
跨平台部署 每个平台的手动二进制文件 NuGet可处理所有平台
Docker / Linux / macOS 手动LD_LIBRARY_PATH配置 开箱即用
.NET兼容性 有限(Java桥接) .NET Framework 4.6.2+,. .NET 5–9
服务器使用入门价格 Enterprise(约 2,000 美元以上) $999(Lite,全部功能)
许可证类型 Enterprise按层级划分,请联系销售部门。 永久(一次性购买)

快速入门:Asprise OCR 到IronOCR 的迁移

步骤 1:替换 NuGet 软件包

移除 Asprise OCR:

dotnet remove package asprise-ocr-api
dotnet remove package asprise-ocr-api
SHELL

NuGet包页面安装IronOCR :

dotnet add package IronOcr

步骤 2:更新命名空间

用IronOCR命名空间替换Asprise命名空间:

// Before (Asprise)
using asprise.ocr;

// After (IronOCR)
using IronOcr;
// Before (Asprise)
using asprise.ocr;

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

步骤 3:初始化许可证

在应用程序启动时添加许可密钥分配—在任何OCR调用之前的Startup.Configure中,或在静态构造函数中:

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

您可以从IronOCR许可页面获取免费试用密钥。 在开发和评估过程中, IronOCR无需密钥即可运行,并在输出结果上添加试用水印。

代码迁移示例

JRE路径配置和引擎初始化移除

在 Linux 或 macOS 上运行的 Asprise 应用程序通常包含启动代码,该代码会在开始任何 OCR 工作之前设置 JRE 路径或验证本机二进制文件是否存在。 IronOCR中没有类似的基础设施。

Asprise OCR 方法:

// AppStartup.cs — native binary validation before accepting any requests
public static void InitializeOcr()
{
    // Validate native library is reachable before first use
    string nativePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
        ? Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll")
        : RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
            ? "/usr/lib/libaocr.so"
            : "/usr/local/lib/libaocr.dylib";

    if (!File.Exists(nativePath))
        throw new FileNotFoundException(
            $"Asprise native binary not found: {nativePath}. " +
            "Deploy the correct platform binary before starting.");

    // Static global init — must run before any Ocr instance is created
    Ocr.SetUp();
}
// AppStartup.cs — native binary validation before accepting any requests
public static void InitializeOcr()
{
    // Validate native library is reachable before first use
    string nativePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
        ? Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll")
        : RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
            ? "/usr/lib/libaocr.so"
            : "/usr/local/lib/libaocr.dylib";

    if (!File.Exists(nativePath))
        throw new FileNotFoundException(
            $"Asprise native binary not found: {nativePath}. " +
            "Deploy the correct platform binary before starting.");

    // Static global init — must run before any Ocr instance is created
    Ocr.SetUp();
}
Imports System
Imports System.IO
Imports System.Runtime.InteropServices

' AppStartup.vb — native binary validation before accepting any requests
Public Module AppStartup
    Public Sub InitializeOcr()
        ' Validate native library is reachable before first use
        Dim nativePath As String = If(RuntimeInformation.IsOSPlatform(OSPlatform.Windows),
                                      Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll"),
                                      If(RuntimeInformation.IsOSPlatform(OSPlatform.Linux),
                                         "/usr/lib/libaocr.so",
                                         "/usr/local/lib/libaocr.dylib"))

        If Not File.Exists(nativePath) Then
            Throw New FileNotFoundException($"Asprise native binary not found: {nativePath}. " &
                                            "Deploy the correct platform binary before starting.")
        End If

        ' Static global init — must run before any Ocr instance is created
        Ocr.SetUp()
    End Sub
End Module
$vbLabelText   $csharpLabel

IronOCR方法:

// Program.cs — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// That is it. 否 binary validation, no path configuration, no SetUp() call.
// NuGet resolved the correct native runtime during package restore.
// Program.cs — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// That is it. 否 binary validation, no path configuration, no SetUp() call.
// NuGet resolved the correct native runtime during package restore.
' Program.vb — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

' That is it. 否 binary validation, no path configuration, no SetUp() call.
' NuGet resolved the correct native runtime during package restore.
$vbLabelText   $csharpLabel

Asprise模式通常跨多个文件用15-30行代码组成—一个启动验证器、一个平台切换、一个包含部署消息的异常和SetUp()调用。 IronOCR用一个单独的任务取代了所有这些操作。 IronTesseract 设置指南涵盖了需要自定义 tessdata 路径或离线操作的环境的部署配置选项。

使用结构化结果对象替换 XML 输出格式

当指定OUTPUT_FORMAT_XML时,Asprise以原始XML字符串的形式生成结构化输出。 从该字符串中提取文本、坐标和置信度需要 XML 解析代码。 IronOCR返回一个类型化的对象图。

Asprise OCR 方法:

// Asprise: structured output is an XML string — must parse manually
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    string xmlOutput = ocr.Recognize(
        imagePath,
        Ocr.RECOGNIZE_TYPE_TEXT,
        Ocr.OUTPUT_FORMAT_XML);   // Returns raw XML, not an object

    // Parse the XML manually to extract words and coordinates
    var doc = System.Xml.Linq.XDocument.Parse(xmlOutput);
    var words = doc.Descendants("word")
        .Select(w => new
        {
            Text       = (string)w.Attribute("text"),
            Confidence = (float)w.Attribute("confidence"),
            X          = (int)w.Attribute("x"),
            Y          = (int)w.Attribute("y"),
        })
        .ToList();

    foreach (var word in words)
        Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}");
}
finally
{
    ocr.StopEngine();
}
// Asprise: structured output is an XML string — must parse manually
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    string xmlOutput = ocr.Recognize(
        imagePath,
        Ocr.RECOGNIZE_TYPE_TEXT,
        Ocr.OUTPUT_FORMAT_XML);   // Returns raw XML, not an object

    // Parse the XML manually to extract words and coordinates
    var doc = System.Xml.Linq.XDocument.Parse(xmlOutput);
    var words = doc.Descendants("word")
        .Select(w => new
        {
            Text       = (string)w.Attribute("text"),
            Confidence = (float)w.Attribute("confidence"),
            X          = (int)w.Attribute("x"),
            Y          = (int)w.Attribute("y"),
        })
        .ToList();

    foreach (var word in words)
        Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}");
}
finally
{
    ocr.StopEngine();
}
Imports System.Xml.Linq

' Asprise: structured output is an XML string — must parse manually
Ocr.SetUp()
Dim ocr As New Ocr()
Try
    ocr.StartEngine("eng", Ocr.SPEED_FAST)
    Dim xmlOutput As String = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_XML) ' Returns raw XML, not an object

    ' Parse the XML manually to extract words and coordinates
    Dim doc As XDocument = XDocument.Parse(xmlOutput)
    Dim words = doc.Descendants("word") _
        .Select(Function(w) New With {
            .Text = CStr(w.Attribute("text")),
            .Confidence = CSng(w.Attribute("confidence")),
            .X = CInt(w.Attribute("x")),
            .Y = CInt(w.Attribute("y"))
        }) _
        .ToList()

    For Each word In words
        Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}")
Next
Finally
    ocr.StopEngine()
End Try
$vbLabelText   $csharpLabel

IronOCR方法:

// IronOCR: structured result is a typed object — no XML parsing
var result = new IronTesseract().Read(imagePath);

foreach (var page in result.Pages)
{
    foreach (var paragraph in page.Paragraphs)
    {
        foreach (var word in paragraph.Words)
        {
            Console.WriteLine(
                $"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%");
        }
    }
}
// IronOCR: structured result is a typed object — no XML parsing
var result = new IronTesseract().Read(imagePath);

foreach (var page in result.Pages)
{
    foreach (var paragraph in page.Paragraphs)
    {
        foreach (var word in paragraph.Words)
        {
            Console.WriteLine(
                $"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%");
        }
    }
}
Imports IronOcr

' IronOCR: structured result is a typed object — no XML parsing
Dim result = New IronTesseract().Read(imagePath)

For Each page In result.Pages
    For Each paragraph In page.Paragraphs
        For Each word In paragraph.Words
            Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%")
        Next
    Next
Next
$vbLabelText   $csharpLabel

无需 XML 反序列化,无需属性转换,无需模式假设。 OcrResult对象模型公开页面、段落、行、单词和字符及其类型化属性。 读取结果指南涵盖了完整的层次结构和坐标系统,包括如何按置信度阈值进行筛选以实现自动化工作流程。

多帧 TIFF 处理

Asprise 接受单个图像文件。 在 Asprise 能够处理多帧 TIFF 文件(文档扫描工作流程中很常见)之前,必须将其分割成单独的帧文件。 IronOCR通过LoadImageFrames直接接受多个帧的TIFF。

Asprise OCR 方法:

// Asprise: no multi-frame TIFF support — split frames externally first
// Using an external imaging library (e.g., System.Drawing or Magick.NET)
var frameFiles = new List<string>();
using (var tiff = System.Drawing.Image.FromFile("scanned-batch.tiff"))
{
    int frameCount = tiff.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
    for (int i = 0; i < frameCount; i++)
    {
        tiff.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
        string framePath = $"frame_{i}.png";
        tiff.Save(framePath);
        frameFiles.Add(framePath);
    }
}

// Now process each frame individually — sequential on LITE/STANDARD
var allText = new System.Text.StringBuilder();
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    foreach (var framePath in frameFiles)
    {
        string pageText = ocr.Recognize(
            framePath,
            Ocr.RECOGNIZE_TYPE_TEXT,
            Ocr.OUTPUT_FORMAT_PLAINTEXT);
        allText.AppendLine(pageText);
    }
}
finally
{
    ocr.StopEngine();
    // Clean up temporary frame files
    foreach (var f in frameFiles)
        File.Delete(f);
}
Console.WriteLine(allText.ToString());
// Asprise: no multi-frame TIFF support — split frames externally first
// Using an external imaging library (e.g., System.Drawing or Magick.NET)
var frameFiles = new List<string>();
using (var tiff = System.Drawing.Image.FromFile("scanned-batch.tiff"))
{
    int frameCount = tiff.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
    for (int i = 0; i < frameCount; i++)
    {
        tiff.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
        string framePath = $"frame_{i}.png";
        tiff.Save(framePath);
        frameFiles.Add(framePath);
    }
}

// Now process each frame individually — sequential on LITE/STANDARD
var allText = new System.Text.StringBuilder();
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    foreach (var framePath in frameFiles)
    {
        string pageText = ocr.Recognize(
            framePath,
            Ocr.RECOGNIZE_TYPE_TEXT,
            Ocr.OUTPUT_FORMAT_PLAINTEXT);
        allText.AppendLine(pageText);
    }
}
finally
{
    ocr.StopEngine();
    // Clean up temporary frame files
    foreach (var f in frameFiles)
        File.Delete(f);
}
Console.WriteLine(allText.ToString());
Imports System.Drawing
Imports System.Text
Imports System.IO

' Asprise: no multi-frame TIFF support — split frames externally first
' Using an external imaging library (e.g., System.Drawing or Magick.NET)
Dim frameFiles As New List(Of String)()
Using tiff As Image = Image.FromFile("scanned-batch.tiff")
    Dim frameCount As Integer = tiff.GetFrameCount(Imaging.FrameDimension.Page)
    For i As Integer = 0 To frameCount - 1
        tiff.SelectActiveFrame(Imaging.FrameDimension.Page, i)
        Dim framePath As String = $"frame_{i}.png"
        tiff.Save(framePath)
        frameFiles.Add(framePath)
    Next
End Using

' Now process each frame individually — sequential on LITE/STANDARD
Dim allText As New StringBuilder()
Ocr.SetUp()
Dim ocr As New Ocr()
Try
    ocr.StartEngine("eng", Ocr.SPEED_FAST)
    For Each framePath As String In frameFiles
        Dim pageText As String = ocr.Recognize(framePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
        allText.AppendLine(pageText)
    Next
Finally
    ocr.StopEngine()
    ' Clean up temporary frame files
    For Each f As String In frameFiles
        File.Delete(f)
    Next
End Try
Console.WriteLine(allText.ToString())
$vbLabelText   $csharpLabel

IronOCR方法:

// IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff");  // All frames, one call

var result = new IronTesseract().Read(input);

// Access each page independently with its page number
foreach (var page in result.Pages)
    Console.WriteLine($"Page {page.PageNumber}: {page.Text}");
// IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff");  // All frames, one call

var result = new IronTesseract().Read(input);

// Access each page independently with its page number
foreach (var page in result.Pages)
    Console.WriteLine($"Page {page.PageNumber}: {page.Text}");
Imports IronOcr

' IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
Using input As New OcrInput()
    input.LoadImageFrames("scanned-batch.tiff") ' All frames, one call

    Dim result = New IronTesseract().Read(input)

    ' Access each page independently with its page number
    For Each page In result.Pages
        Console.WriteLine($"Page {page.PageNumber}: {page.Text}")
    Next
End Using
$vbLabelText   $csharpLabel

Asprise 方法需要外部成像依赖、临时文件管理、手动清理和逐帧顺序处理。 IronOCR一次即可处理所有帧。 TIFF 和 GIF 输入指南涵盖了大型 TIFF 文件的帧范围选择,其中只需要特定页面。

生成可搜索的 PDF 文件

Asprise 在任何许可级别下均不具备可搜索的 PDF 输出功能。 从扫描文档创建带有嵌入式 OCR 文本的 PDF 需要外部 PDF 库、单独的 OCR 处理以获取文本位置以及手动叠加构建。 IronOCR直接从识别结果生成可搜索的 PDF 文件。

Asprise OCR 方法:

// Asprise: no searchable PDF output — external PDF library required
// Step 1: OCR the document to get text
Ocr.SetUp();
Ocr ocr = new Ocr();
string recognizedText;
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    recognizedText = ocr.Recognize(
        "scanned-contract.jpg",
        Ocr.RECOGNIZE_TYPE_TEXT,
        Ocr.OUTPUT_FORMAT_PLAINTEXT);   // Only plain text — no position data
}
finally
{
    ocr.StopEngine();
}

// Step 2: Use an external PDF library to embed text over the image
// (iTextSharp, PdfSharp, or similar — adds another dependency and license)
// Text positioning requires coordinate data Asprise cannot provide in plain text mode
// ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone");
// Asprise: no searchable PDF output — external PDF library required
// Step 1: OCR the document to get text
Ocr.SetUp();
Ocr ocr = new Ocr();
string recognizedText;
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    recognizedText = ocr.Recognize(
        "scanned-contract.jpg",
        Ocr.RECOGNIZE_TYPE_TEXT,
        Ocr.OUTPUT_FORMAT_PLAINTEXT);   // Only plain text — no position data
}
finally
{
    ocr.StopEngine();
}

// Step 2: Use an external PDF library to embed text over the image
// (iTextSharp, PdfSharp, or similar — adds another dependency and license)
// Text positioning requires coordinate data Asprise cannot provide in plain text mode
// ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone");
' Asprise: no searchable PDF output — external PDF library required
' Step 1: OCR the document to get text
Ocr.SetUp()
Dim ocr As New Ocr()
Dim recognizedText As String
Try
    ocr.StartEngine("eng", Ocr.SPEED_FAST)
    recognizedText = ocr.Recognize( _
        "scanned-contract.jpg", _
        Ocr.RECOGNIZE_TYPE_TEXT, _
        Ocr.OUTPUT_FORMAT_PLAINTEXT)   ' Only plain text — no position data
Finally
    ocr.StopEngine()
End Try

' Step 2: Use an external PDF library to embed text over the image
' (iTextSharp, PdfSharp, or similar — adds another dependency and license)
' Text positioning requires coordinate data Asprise cannot provide in plain text mode
' ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone")
$vbLabelText   $csharpLabel

IronOCR方法:

// IronOCR: searchable PDF in two lines — no external PDF library
var result = new IronTesseract().Read("scanned-contract.jpg");
result.SaveAsSearchablePdf("searchable-contract.pdf");

// Batch: convert a folder of scanned images to searchable PDFs
foreach (var imagePath in Directory.GetFiles("scans", "*.jpg"))
{
    var batchResult = new IronTesseract().Read(imagePath);
    string outputPath = Path.ChangeExtension(imagePath, ".searchable.pdf");
    batchResult.SaveAsSearchablePdf(outputPath);
    Console.WriteLine($"Converted: {outputPath}");
}
// IronOCR: searchable PDF in two lines — no external PDF library
var result = new IronTesseract().Read("scanned-contract.jpg");
result.SaveAsSearchablePdf("searchable-contract.pdf");

// Batch: convert a folder of scanned images to searchable PDFs
foreach (var imagePath in Directory.GetFiles("scans", "*.jpg"))
{
    var batchResult = new IronTesseract().Read(imagePath);
    string outputPath = Path.ChangeExtension(imagePath, ".searchable.pdf");
    batchResult.SaveAsSearchablePdf(outputPath);
    Console.WriteLine($"Converted: {outputPath}");
}
Imports System.IO
Imports IronOcr

' IronOCR: searchable PDF in two lines — no external PDF library
Dim result = New IronTesseract().Read("scanned-contract.jpg")
result.SaveAsSearchablePdf("searchable-contract.pdf")

' Batch: convert a folder of scanned images to searchable PDFs
For Each imagePath In Directory.GetFiles("scans", "*.jpg")
    Dim batchResult = New IronTesseract().Read(imagePath)
    Dim outputPath As String = Path.ChangeExtension(imagePath, ".searchable.pdf")
    batchResult.SaveAsSearchablePdf(outputPath)
    Console.WriteLine($"Converted: {outputPath}")
Next
$vbLabelText   $csharpLabel

可搜索的 PDF 文件包含原始图像作为视觉层,并在正确的坐标上叠加了不可见的 OCR 文本——这是归档和合规工作流程的标准格式。 请参阅可搜索的 PDF 操作指南可搜索的 PDF 示例,了解包括 PDF/A 输出在内的各种选项,以便进行长期存档。

Web应用程序中的异步OCR

Asprise没有异步API。 开发者通过将同步调用包装在Task.Run中将其集成到异步.NET应用程序中,这会消耗线程池线程并无法消除阻塞。 IronOCR提供原生异步路径。

Asprise OCR 方法:

// Asprise: no async API — must offload to Task.Run
// This blocks a thread pool thread during the entire OCR operation
// On LITE/STANDARD, concurrent Task.Run calls = license violation
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
    string tempPath = Path.GetTempFileName();
    await using (var fs = new FileStream(tempPath, FileMode.Create))
        await fileStream.CopyToAsync(fs);

    // Task.Run wraps synchronous Asprise — occupies a thread pool thread
    // Two concurrent requests still violate LITE/STANDARD license
    return await Task.Run(() =>
    {
        Ocr ocr = new Ocr();
        try
        {
            ocr.StartEngine("eng", Ocr.SPEED_FAST);
            return ocr.Recognize(
                tempPath,
                Ocr.RECOGNIZE_TYPE_TEXT,
                Ocr.OUTPUT_FORMAT_PLAINTEXT);
        }
        finally
        {
            ocr.StopEngine();
            File.Delete(tempPath);
        }
    });
}
// Asprise: no async API — must offload to Task.Run
// This blocks a thread pool thread during the entire OCR operation
// On LITE/STANDARD, concurrent Task.Run calls = license violation
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
    string tempPath = Path.GetTempFileName();
    await using (var fs = new FileStream(tempPath, FileMode.Create))
        await fileStream.CopyToAsync(fs);

    // Task.Run wraps synchronous Asprise — occupies a thread pool thread
    // Two concurrent requests still violate LITE/STANDARD license
    return await Task.Run(() =>
    {
        Ocr ocr = new Ocr();
        try
        {
            ocr.StartEngine("eng", Ocr.SPEED_FAST);
            return ocr.Recognize(
                tempPath,
                Ocr.RECOGNIZE_TYPE_TEXT,
                Ocr.OUTPUT_FORMAT_PLAINTEXT);
        }
        finally
        {
            ocr.StopEngine();
            File.Delete(tempPath);
        }
    });
}
Imports System.IO
Imports System.Threading.Tasks

' Asprise: no async API — must offload to Task.Run
' This blocks a thread pool thread during the entire OCR operation
' On LITE/STANDARD, concurrent Task.Run calls = license violation
Public Async Function ProcessUploadAsync(fileStream As Stream, fileName As String) As Task(Of String)
    Dim tempPath As String = Path.GetTempFileName()
    Await Using fs As New FileStream(tempPath, FileMode.Create)
        Await fileStream.CopyToAsync(fs)
    End Using

    ' Task.Run wraps synchronous Asprise — occupies a thread pool thread
    ' Two concurrent requests still violate LITE/STANDARD license
    Return Await Task.Run(Function()
                              Dim ocr As New Ocr()
                              Try
                                  ocr.StartEngine("eng", Ocr.SPEED_FAST)
                                  Return ocr.Recognize(tempPath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
                              Finally
                                  ocr.StopEngine()
                                  File.Delete(tempPath)
                              End Try
                          End Function)
End Function
$vbLabelText   $csharpLabel

IronOCR方法:

// IronOCR: native async, concurrent requests permitted on all tiers
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
    using var input = new OcrInput();
    input.LoadImage(fileStream);       // Stream input directly — no temp file

    var ocr = new IronTesseract();
    var result = await ocr.ReadAsync(input);
    return result.Text;
}
// IronOCR: native async, concurrent requests permitted on all tiers
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
    using var input = new OcrInput();
    input.LoadImage(fileStream);       // Stream input directly — no temp file

    var ocr = new IronTesseract();
    var result = await ocr.ReadAsync(input);
    return result.Text;
}
Imports System.IO
Imports System.Threading.Tasks

' IronOCR: native async, concurrent requests permitted on all tiers
Public Async Function ProcessUploadAsync(fileStream As Stream, fileName As String) As Task(Of String)
    Using input As New OcrInput()
        input.LoadImage(fileStream) ' Stream input directly — no temp file

        Dim ocr As New IronTesseract()
        Dim result = Await ocr.ReadAsync(input)
        Return result.Text
    End Using
End Function
$vbLabelText   $csharpLabel

IronOCR版本消除了临时文件写入、Task.Run包装器和线程阻塞行为。 每个并发请求都会创建自己的IronTesseract实例——该类是无状态的,每个实例都是独立的。 异步OCR指南涵盖ReadAsync模式和取消令牌支持,用于托管服务中的长时间批处理操作。

Asprise OCRAPI 到IronOCR映射参考

Asprise OCR IronOCR当量
asprise.ocr命名空间 IronOcr命名空间
Ocr.SetUp() 不要求
new Ocr() new IronTesseract()
ocr.StartEngine("eng", Ocr.SPEED_FAST) 不要求
ocr.StartEngine("eng+fra", speed) ocr.Language = OcrLanguage.English + OcrLanguage.French
ocr.Recognize(path, type, format) ocr.Read(input)
Ocr.RECOGNIZE_TYPE_TEXT 默认行为
Ocr.RECOGNIZE_TYPE_BARCODE ocr.Configuration.ReadBarCodes = true
Ocr.RECOGNIZE_TYPE_ALL ocr.Configuration.ReadBarCodes = true
Ocr.OUTPUT_FORMAT_PLAINTEXT result.Text
Ocr.OUTPUT_FORMAT_XML result.Pages / result.Pages[n].Words
Ocr.OUTPUT_FORMAT_PDF result.SaveAsSearchablePdf(path)
Ocr.SPEED_FASTEST ocr.Configuration.TesseractEngineMode调优
Ocr.SPEED_FAST 默认配置
Ocr.SPEED_SLOW 更高精度的配置设置
ocr.StopEngine() 不需要—IDisposable
result.StartsWith("ERROR:")检查 标准.NET异常处理(try/catch
平台原生 DLL (aocr_x64.dll) NuGet运行时包(自动)
流输入的手动临时文件 input.LoadImage(stream)直接
用于多帧 TIFF 的外部库 input.LoadImageFrames(path)
用于可搜索 PDF 的外部库 result.SaveAsSearchablePdf(path)

常见迁移问题和解决方案

问题 1:移除本机二进制文件后出现 DllNotFoundException 异常

Asprise OCR:移除Asprise NuGet包但保留本机二进制引用(在项目文件复制规则、Docker COPY指令或部署脚本中)可能会导致DllNotFoundException从指向不存在的二进制文件的过期配置中重新出现。

解决方案:在部署工件中搜索对LD_LIBRARY_PATH设置的任何引用并删除它们。 IronOCR没有相应的配置要求。 在 Dockerfile 中:

# Remove: COPY aocr_x64.dll /app/
# Remove: ENV LD_LIBRARY_PATH=/app
# IronOCR: nothing to add — NuGet handles native runtime packaging
RUN dotnet restore
RUN dotnet publish -c Release -o /app/publish

对于跨平台部署, Docker 部署指南涵盖了IronOCR在 Linux 容器上的基本镜像要求。

问题2:缺少Ocr.SetUp()移除导致启动中断

Asprise OCR:Ocr.SetUp()执行全局本机初始化。 某些代码库在静态构造函数或Startup.Configure中调用它。 迁移后,移除Asprise命名空间解决了编译错误,但如果SetUp()包含在抑制异常的try/catch中,代码可能会在未初始化任何内容的情况下静默编译和运行。

解决方案:grep找出所有的SetUp()调用并删除整个初始化块。 将相应的启动钩子替换为IronOCR许可证密钥分配:

grep -rn "Ocr.SetUp\|StartEngine\|StopEngine" --include="*.cs" .
grep -rn "Ocr.SetUp\|StartEngine\|StopEngine" --include="*.cs" .
SHELL
// Remove all occurrences of the engine lifecycle pattern:
// Ocr.SetUp();
// ocr.StartEngine(...);
// ocr.StopEngine();

// Replace application startup initialization with:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Remove all occurrences of the engine lifecycle pattern:
// Ocr.SetUp();
// ocr.StartEngine(...);
// ocr.StopEngine();

// Replace application startup initialization with:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
$vbLabelText   $csharpLabel

问题3:XML输出解析代码没有直接替代品

Asprise OCR:使用OUTPUT_FORMAT_XML字符串的代码在IronOCR中没有等效的XML结构。 Asprise 生成的 XML 模式与IronOCR的对象模型并不直接对应。

解决方案:将XML解析代码替换为直接属性访问OcrResult。 映射关系如下:

// Asprise XML parsing (remove)
var words = XDocument.Parse(xmlOutput)
    .Descendants("word")
    .Select(w => new { Text = (string)w.Attribute("text"), X = (int)w.Attribute("x") });

//IronOCRobject model (replace with)
var result = new IronTesseract().Read(imagePath);
var words = result.Pages
    .SelectMany(p => p.Paragraphs)
    .SelectMany(para => para.Words)
    .Select(w => new { w.Text, w.X });
// Asprise XML parsing (remove)
var words = XDocument.Parse(xmlOutput)
    .Descendants("word")
    .Select(w => new { Text = (string)w.Attribute("text"), X = (int)w.Attribute("x") });

//IronOCRobject model (replace with)
var result = new IronTesseract().Read(imagePath);
var words = result.Pages
    .SelectMany(p => p.Paragraphs)
    .SelectMany(para => para.Words)
    .Select(w => new { w.Text, w.X });
Imports System.Xml.Linq
Imports IronOcr

' Asprise XML parsing (remove)
Dim words = XDocument.Parse(xmlOutput) _
    .Descendants("word") _
    .Select(Function(w) New With {Key .Text = CType(w.Attribute("text"), String), Key .X = CType(w.Attribute("x"), Integer)})

' IronOCR object model (replace with)
Dim result = New IronTesseract().Read(imagePath)
Dim words = result.Pages _
    .SelectMany(Function(p) p.Paragraphs) _
    .SelectMany(Function(para) para.Words) _
    .Select(Function(w) New With {w.Text, w.X})
$vbLabelText   $csharpLabel

读取结果指南涵盖完整的对象层次结构,包括带有边界框的字符级数据。

问题 4:Task.Run 包装器导致线程池耗尽

Asprise OCR:Task.Run中包装Asprise的高并发Web应用程序在OCR量激增时会耗尽线程池。 每个排队的Task.Run在OCR操作的整个持续时间内占用一个线程池线程。

解决方案:替换 Task.Run(() =&gt; { asprise... })使用原生IronOCR异步调用进行模式匹配。 每个IronTesseract`实例都是独立的—每个请求创建一个:

// Remove: await Task.Run(() => { ocr.Recognize(...) });

// Replace with:
using var input = new OcrInput();
input.LoadImage(stream);
var result = await new IronTesseract().ReadAsync(input);
return result.Text;
// Remove: await Task.Run(() => { ocr.Recognize(...) });

// Replace with:
using var input = new OcrInput();
input.LoadImage(stream);
var result = await new IronTesseract().ReadAsync(input);
return result.Text;
Imports IronTesseract

Using input As New OcrInput()
    input.LoadImage(stream)
    Dim result = Await (New IronTesseract()).ReadAsync(input)
    Return result.Text
End Using
$vbLabelText   $csharpLabel

问题 5:基于字符串的语言代码验证

Asprise OCR:语言代码作为字符串传递("eng+fra")。 在运行时验证这些字符串的应用程序—检查硬编码列表,从配置中读取—需要在字符串格式更改为OcrLanguage枚举时进行更新。

解决方案:OcrLanguage枚举值替换字符串语言参数。 以配置驱动的语言选择与Enum.Parse完美映射:

// Asprise string-based (remove)
string language = config["OcrLanguage"];  // e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST);

//IronOCRenum-based (replace with)
// For single language from config:
var ocr = new IronTesseract();
ocr.Language = Enum.Parse<OcrLanguage>(config["OcrLanguage"]);  // e.g. "English"
var result = ocr.Read(input);
// Asprise string-based (remove)
string language = config["OcrLanguage"];  // e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST);

//IronOCRenum-based (replace with)
// For single language from config:
var ocr = new IronTesseract();
ocr.Language = Enum.Parse<OcrLanguage>(config["OcrLanguage"]);  // e.g. "English"
var result = ocr.Read(input);
' Asprise string-based (remove)
Dim language As String = config("OcrLanguage")  ' e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST)

' IronOCRenum-based (replace with)
' For single language from config:
Dim ocr As New IronTesseract()
ocr.Language = [Enum].Parse(Of OcrLanguage)(config("OcrLanguage"))  ' e.g. "English"
Dim result = ocr.Read(input)
$vbLabelText   $csharpLabel

多语言指南列出了所有有效的OcrLanguage枚举值及其对应的NuGet语言包包。

问题 6:不再需要许可证等级检查逻辑

Asprise OCR:部分生产代码库包含运行时检查,用于检测 Asprise 许可证级别,并在低于企业版(Enterprise)级别运行时对 OCR 工作进行序列化。这些保护措施可以防止违反许可证规定,但会增加复杂性并降低吞吐量。

解决方案:移除所有层级检测和序列化保护。 IronOCR对任何层数都没有螺纹限制。 SemaphoreSlim或用于序列化Asprise调用的单线程调度模式在迁移后无用:

// Remove: SemaphoreSlim _ocrLock = new SemaphoreSlim(1, 1);
// Remove: await _ocrLock.WaitAsync(); ... _ocrLock.Release();

// IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, path =>
{
    var text = new IronTesseract().Read(path).Text;
    results[path] = text;
});
// Remove: SemaphoreSlim _ocrLock = new SemaphoreSlim(1, 1);
// Remove: await _ocrLock.WaitAsync(); ... _ocrLock.Release();

// IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, path =>
{
    var text = new IronTesseract().Read(path).Text;
    results[path] = text;
});
Imports System.Threading.Tasks

' IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, Sub(path)
    Dim text = (New IronTesseract()).Read(path).Text
    results(path) = text
End Sub)
$vbLabelText   $csharpLabel

Asprise OCR迁移检查清单

迁移前

在编写任何替换代码之前,请先审核代码库中所有 Asprise 的使用情况:

# Find all files importing asprise namespace
grep -rn "using asprise" --include="*.cs" .

# Find all engine lifecycle calls
grep -rn "SetUp\|StartEngine\|StopEngine" --include="*.cs" .

# Find all integer constant references
grep -rn "RECOGNIZE_TYPE\|OUTPUT_FORMAT\|SPEED_FAST\|SPEED_SLOW" --include="*.cs" .

# Find native binary references in project files and deployment scripts
grep -rn "aocr\|libaocr" --include="*.csproj" --include="Dockerfile" --include="*.yml" .

# Find XML output parsing code
grep -rn "OUTPUT_FORMAT_XML\|XDocument.Parse\|Descendants.*word" --include="*.cs" .

# Find Task.Run wrappers around OCR calls
grep -rn "Task.Run.*ocr\|Task.Run.*Recognize" --include="*.cs" .
# Find all files importing asprise namespace
grep -rn "using asprise" --include="*.cs" .

# Find all engine lifecycle calls
grep -rn "SetUp\|StartEngine\|StopEngine" --include="*.cs" .

# Find all integer constant references
grep -rn "RECOGNIZE_TYPE\|OUTPUT_FORMAT\|SPEED_FAST\|SPEED_SLOW" --include="*.cs" .

# Find native binary references in project files and deployment scripts
grep -rn "aocr\|libaocr" --include="*.csproj" --include="Dockerfile" --include="*.yml" .

# Find XML output parsing code
grep -rn "OUTPUT_FORMAT_XML\|XDocument.Parse\|Descendants.*word" --include="*.cs" .

# Find Task.Run wrappers around OCR calls
grep -rn "Task.Run.*ocr\|Task.Run.*Recognize" --include="*.cs" .
SHELL

盘点结果:

  • 计算导入asprise.ocr的文件数量—这些都需要更新命名空间
  • 列出每个Read调用
  • 识别 XML 输出解析代码——每个代码块都需要对象模型替换
  • 注意任何许可层级保护或序列化包装器——这些都是可以移除的。
  • 查找本地二进制部署脚本和容器配置

代码迁移

  1. 从所有项目中移除asprise-ocr-api NuGet包
  2. 在每个执行OCR的项目中安装IronOcr NuGet包
  3. using IronOcr在所有文件中
  4. 在应用程序启动时添加IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
  5. 从所有启动和初始化代码中移除Ocr.SetUp()调用
  6. 将每个Ocr.StartEngine / Recognize / new IronTesseract().Read(path).Text
  7. result.Pages对象遍历
  8. OUTPUT_FORMAT_PDF变通方法
  9. input.LoadImageFrames(tiffPath)替换多帧TIFF拆分代码
  10. Task.Run包装器
  11. 移除SemaphoreSlim或保护Asprise免受并发使用的序列化保护
  12. .csproj文件和Dockerfiles中移除本机二进制复制指令
  13. 从环境配置和CI脚本中移除LD_LIBRARY_PATH设置
  14. "eng+fra"
  15. result.StartsWith("ERROR:")检查

后迁移

  • 验证dotnet build完成时没有关于缺少本机库的警告
  • 确认在所有目标环境(Windows,Linux,Docker)中启动时没有发生BadImageFormatException
  • 对一张代表性图像运行 OCR,并确认文本输出与迁移前的基线一致。
  • 测试多帧 TIFF 处理,并验证所有页面均返回正确的页码。 生成可搜索的 PDF 文件,并验证 PDF 查看器中的文本是否可选中和可搜索。
  • 向任何调用 OCR 的 API 端点发送并发 HTTP 请求,并确认所有请求均已完成且无错误。
  • 验证异步端点在并发负载下返回结果时不会发生死锁
  • 确认结构化数据提取(词坐标和置信度)在已知文档上产生正确的输出
  • 检查应用程序的内存使用情况以确认没有本机内存泄漏(以前由漏掉的StopEngine()调用引起)
  • 在 Linux 或 Docker 容器下运行应用程序,以确认无需二进制配置即可实现跨平台部署。

迁移到IronOCR的主要优势

部署简化为单个NuGet引用。迁移后,所有部署目标(开发工作站、测试服务器、Linux 容器、CI 代理)都使用相同的命令安装相同的软件包。 没有平台检测逻辑,没有特定于架构的二进制文件源,也没有运行时路径配置。 一个以前需要手动本机二进制COPY指令的Docker镜像现在仅需dotnet restore即可。 Linux 部署指南Azure 部署指南在适用情况下会包含特定于环境的注意事项。

所有许可证层解锁服务器级部署。 $999 Lite许可证支持ASP.NET Core Web APIs、Windows Services、Azure Functions、AWS Lambda和任何其他多线程.NET工作负载。 Asprise 的企业级螺纹识别功能收费 2,000 美元至 5,000 美元以上,而IronOCR 的每个级别都包含此功能。 从 Asprise Enterprise迁移到IronOCR Lite 的团队降低了 OCR 许可成本,同时获得了Enterprise没有提供的功能——原生 PDF、结构化输出、可搜索的 PDF 生成和 125 种语言。

结构化OCR结果替换XML字符串解析。 OcrResult对象模型公开完整的文档层次结构:页面、段落、行、单词和字符,每个都有像素精度的边界框坐标和置信分数。 以前使用 XDocument 或正则表达式解析 Asprise XML 字符串的代码现在变成了直接属性访问。 OCR 结果功能页面涵盖坐标系统以及如何按置信度筛选结果以实现自动质量控制。

内置预处理去除外部成像依赖。 通过DeepCleanBackgroundNoise——消除了Asprise集成所需的外部成像库。消除该依赖关系消除了许可问题,缩小了构建足迹,并将预处理配置直接放置在与OCR配置相邻在同一代码文件中。预处理功能页面图像质量校正指南涵盖了何时应用每个滤镜以及每个滤镜在低质量扫描上的可测量的精度提升。

本机异步和真正的并行性提高吞吐量。 async/await模式中而不阻塞线程池。 使用Parallel.ForEach的并行批处理或PLINQ随着可用核心,线性扩展。 Asprise Lite/STANDARD 强制按顺序运行的文档批次(100 个文档,每个文档 2 秒,耗时超过 3 分钟)在配备IronOCR的 8 核机器上大约 25 秒即可运行。 多线程示例展示了并行吞吐量模式,并展示了如何使用ConcurrentBag进行线程安全的结果收集。

125+种语言,无二进制分发。 语言包作为NuGet包安装——dotnet add package IronOcr.Languages.Japanese——并像任何其他依赖项一样随应用程序一起部署。 无需手动填充 tessdata 文件夹,无需查找语言二进制文件,也无需在目标机器上进行路径配置。语言索引列出了所有 125 多个可用的语言包。

请注意Asprise OCR、PDFSharp、Tesseract和iText是他们各自所有者的注册商标。 本网站未与Asprise、Google、empira Software GmbH或iText Group关联、未授权或赞助。所有产品名称、徽标和品牌均为其各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。

常见问题解答

我为什么要从 Asprise OCR SDK 迁移到 IronOCR?

常见的驱动因素包括消除 COM 互操作的复杂性、取代基于文件的许可证管理、避免按页计费、启用 Docker/容器部署以及采用与标准 .NET 工具集成的 NuGet 原生工作流程。

从 Asprise OCR SDK 迁移到 IronOCR 时,主要的代码变更有哪些?

将 Asprise OCR 初始化序列替换为 IronTesseract 实例化,移除 COM 生命周期管理(显式的创建/加载/关闭模式),并更新结果属性名称。这样可以显著减少样板代码行数。

我该如何安装 IronOCR 以开始迁移?

在软件包管理器控制台中运行“Install-Package IronOcr”,或在命令行界面中运行“dotnet add package IronOcr”。语言包是单独的软件包:例如,法语语言包需要运行“dotnet add package IronOcr.Languages.French”。

IronOCR 在标准商业文档的 OCR 准确率方面是否能与 Asprise OCR SDK 相媲美?

IronOCR 对标准商业内容(包括发票、合同、收据和打印表格)的识别准确率很高。图像预处理滤镜(例如去倾斜、去噪、对比度增强)可进一步提高对质量较差输入文件的识别率。

IronOCR 如何处理 Asprise OCR SDK 单独安装的语言数据?

IronOCR 中的语言数据以 NuGet 包的形式分发。“dotnet add package IronOcr.Languages.German”命令用于安装德语支持。无需手动放置文件或指定目录路径。

从 Asprise OCR SDK 迁移到 IronOCR 是否需要更改部署基础架构?

IronOCR 比 Asprise OCR SDK 需要的底层架构变更更少。它无需修改 SDK 二进制文件路径、许可证文件位置或配置许可证服务器。NuGet 包包含完整的 OCR 引擎,许可证密钥是应用程序代码中设置的字符串。

迁移后如何配置 IronOCR 许可?

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

IronOCR 能否像 Asprise OCR 那样处理 PDF 文件?

是的。IronOCR 可以读取原生 PDF 和扫描版 PDF。实例化 IronTesseract,调用 ocr.Read(input) 方法(其中 input 可以是 PDF 路径或 OcrPdfInput),然后遍历 OcrResult 页面。无需单独的 PDF 渲染流程。

IronOCR 如何处理大批量处理中的线程问题?

IronTesseract 可以安全地按线程实例化。在 Parallel.ForEach 或 Task 池中为每个线程启动一个实例,并发运行 OCR,并在完成后释放每个实例。无需全局状态或锁定。

IronOCR在提取文本后支持哪些输出格式?

IronOCR 返回结构化结果,包括文本、词坐标、置信度评分和页面结构。导出选项包括纯文本、可搜索 PDF 和用于下游处理的结构化结果对象。

对于可扩展的工作负载而言,IronOCR 的定价是否比 Asprise OCR SDK 更具可预测性?

IronOCR采用永久统一费率许可模式,不收取任何页数或数量费用。无论您处理1万页还是1000万页,许可费用都保持不变。批量许可和团队许可选项请参见IronOCR定价页面。

从 Asprise OCR SDK 迁移到 IronOCR 后,我现有的测试会发生什么变化?

迁移后,对提取的文本内容进行断言的测试应该继续通过。验证 API 调用模式或 COM 对象生命周期的测试需要更新,以反映 IronOCR 更简化的初始化和结果模型。

Kannaopat Udonpant
软件工程师
在成为软件工程师之前,Kannapat 在日本北海道大学完成了环境资源博士学位。在攻读学位期间,Kannapat 还成为了车辆机器人实验室的成员,隶属于生物生产工程系。2022 年,他利用自己的 C# 技能加入 Iron Software 的工程团队,专注于 IronPDF。Kannapat 珍视他的工作,因为他可以直接从编写大多数 IronPDF 代码的开发者那里学习。除了同行学习外,Kannapat 还喜欢在 Iron Software 工作的社交方面。不撰写代码或文档时,Kannapat 通常可以在他的 PS5 上玩游戏或重温《最后生还者》。

钢铁支援团队

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