从 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
// 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与 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
从NuGet包页面安装IronOCR :
步骤 2:更新命名空间
用IronOCR命名空间替换Asprise命名空间:
// Before (Asprise)
using asprise.ocr;
// After (IronOCR)
using IronOcr;
步骤 3:初始化许可证
在应用程序启动时添加许可密钥分配—在任何OCR调用之前的Startup.Configure中,或在静态构造函数中:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"您可以从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();
}
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.
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();
}
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}%");
}
}
}
无需 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());
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}");
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");
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}");
}
可搜索的 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);
}
});
}
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版本消除了临时文件写入、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" .
// 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";
问题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 });
读取结果指南涵盖完整的对象层次结构,包括带有边界框的字符级数据。
问题 4:Task.Run 包装器导致线程池耗尽
**Asprise OCR:**在Task.Run中包装Asprise的高并发Web应用程序在OCR量激增时会耗尽线程池。 每个排队的Task.Run在OCR操作的整个持续时间内占用一个线程池线程。
**解决方案:**替换 Task.Run(() => { 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;
问题 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);
多语言指南列出了所有有效的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;
});
##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" .
盘点结果:
- 计算导入
asprise.ocr的文件数量—这些都需要更新命名空间 - 列出每个
Read调用 - 识别 XML 输出解析代码——每个代码块都需要对象模型替换
- 注意任何许可层级保护或序列化包装器——这些都是可以移除的。
- 查找本地二进制部署脚本和容器配置
代码迁移
- 从所有项目中移除
asprise-ocr-apiNuGet包 - 在每个执行OCR的项目中安装
IronOcrNuGet包 - 将
using IronOcr在所有文件中 - 在应用程序启动时添加
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY" - 从所有启动和初始化代码中移除
Ocr.SetUp()调用 - 将每个
Ocr.StartEngine/Recognize/new IronTesseract().Read(path).Text - 将
result.Pages对象遍历 - 用
OUTPUT_FORMAT_PDF变通方法 - 用
input.LoadImageFrames(tiffPath)替换多帧TIFF拆分代码 - 用
Task.Run包装器 - 移除
SemaphoreSlim或保护Asprise免受并发使用的序列化保护 - 从
.csproj文件和Dockerfiles中移除本机二进制复制指令 - 从环境配置和CI脚本中移除
LD_LIBRARY_PATH设置 - 用
"eng+fra") - 用
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 多个可用的语言包。
