从 Dynamsoft OCR 迁移到 IronOCR
本指南为从 Dynamsoft 标签识别器 迁移到IronOCR 的.NET开发人员提供了完整的迁移路径。 它涵盖了NuGet包替换、命名空间更新、许可证初始化以及与一般功能比较不同的场景的实用代码迁移示例——包括模板配置消除、运行时设置 JSON 删除、区域定义迁移和结果解析简化。
为什么要从 Dynamsoft OCR 迁移?
Dynamsoft 标签识别器是一款专用的专业工具。这种精准度在小范围部署中表现出色,但一旦应用范围超出最初的 MRZ 或 VIN 用例,就会产生阻碍。
运行时设置JSON是维护表面。 每个Dynamsoft识别工作流从AppendSettingsFromString开始,加载一个声明参数数组、字符模型和区域引用的JSON文档。 这些 JSON 模板是单独的部署工件,不会编译到您的二进制文件中。 当 Dynamsoft 在 SDK 版本之间更改模板架构时,它们需要版本控制、部署管道管理和手动更新。 IronOCR无需配置文件:实例化.Read(),引擎会自动选择适当的设置。
年度订阅价格叠加。Dynamsoft标签识别器许可价格为每台设备每年 599 美元起。 没有永久的解决方案。 一个五设备处理集群每年的成本超过 2,995 美元——而且该预算仅涵盖 MRZ 和结构化标签识别。 如果添加 Dynamsoft 条形码阅读器进行条形码读取,或添加 Dynamsoft 文档规范化器进行边缘校正,则年度账单将按产品数量乘以相应倍数。 IronOCR的Lite许可证是$999,一次性支付,涵盖通用OCR、结构化标签、条形码、原生PDF、可搜索PDF输出,以及单个包中的125+种语言。
区域定义需要JSON模板。 在Dynamsoft中定义一个识别区域意味着制作一个LabelRecognizerParameterArray中,并在任何图像处理开始之前加载整个文档。 IronOCR使用一个OcrInput.LoadImage。 更改区域只需修改一个数字,无需重新解析 JSON 文档。
结果解析完全是您的责任。 LineResult数组。 您需要的每个结构——字段偏移量、日期转换、校验位验证、名称分隔符处理——都需要在原始输出的基础上编写自定义解析代码。 IronOCR返回一个.Characters,作为带有边界框坐标、置信度得分和字体元数据的类型化集合。
不支持原生 PDF 会产生隐藏的依赖关系。Dynamsoft标签识别器不具备 PDF 输入功能。 任何到达处理管道的 PDF 文件都需要一个外部库将每一页渲染成位图,一个页面迭代循环,以及在第一次调用 Dynamsoft 之前进行结果聚合步骤。 IronOCR直接读取PDF:new IronTesseract().Read("document.pdf")处理每一页面,无需二次依赖、渲染循环或临时图像文件夹。
多产品初始化模块随着范围的扩大而增加。 处理结构化标签、条形码和文档标准化的Dynamsoft应用程序在启动时会进行三个静态InitLicense调用,三个释放链和三个独立的SDK版本依赖。 升级 SDK 意味着需要协调所有产品。 无论应用程序使用哪些功能, IronOCR都只有一个初始化语句和一个软件包版本。
基本问题
Dynamsoft 需要先在运行时加载 JSON 配置文件,然后才能开始识别:
// Dynamsoft: JSON template required before any image processing
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
string settings = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""VIN_Label"",
""ReferenceRegionNameArray"": [""VinRegion""],
""CharacterModelName"": ""VIN""
}],
""ReferenceRegionArray"": [{
""Name"": ""VinRegion"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [5, 40],
""SecondPoint"": [95, 40],
""ThirdPoint"": [95, 60],
""FourthPoint"": [5, 60]
}
}]
}";
recognizer.AppendSettingsFromString(settings); // fails silently if JSON is malformed
var results = recognizer.RecognizeFile(imagePath);
// IronOCR: no JSON, no template files — region is a constructor argument
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var region = new CropRectangle(x: 50, y: 400, width: 900, height: 200);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
var result = new IronTesseract().Read(input);
Console.WriteLine(result.Text);
IronOCR与 Dynamsoft OCR:功能对比
下表列出了两个库之间的全部功能差距。
| 特征 | Dynamsoft 标签识别器 | IronOCR |
|---|---|---|
| 通用文档 OCR | 不支持 | 全面支持 |
| MRZ识别 | 专业化(原始文本输出) | 内置结构化字段 |
| 车辆识别码 (VIN) 识别 | 专业版(需要模板) | 标准OCR,区域定向 |
| 工业标签解读 | 专业版(需要模板) | 是的,通过CropRectangle |
| 运行时设置配置 | 必需的 (JSON通过AppendSettingsFromString) | 不要求 |
| 模板部署工件 | 必需(JSON 文件) | None |
| 原生 PDF 输入 | 不支持 | 是 |
| 受密码保护的PDF | 不支持 | 是 |
| 多页 TIFF 输入 | 手动页面迭代 | 原生(LoadImageFrames) |
| 可搜索的 PDF 输出 | 不支持 | 是的(SaveAsSearchablePdf) |
| 条形码读取 | 独立产品(Dynamsoft 条码阅读器) | 内置的(ReadBarCodes = true) |
| 自动预处理 | 有限的 | 是的(调整桌面倾斜度、降噪、对比度、二值化、锐化、膨胀、腐蚀) |
| 结构化输出(字数、行数、段落) | 原始LineResult文本字符串 | 完全输入坐标和置信度 |
| 语言支持 | 有限公司(拉丁语 MRZ) | 支持 125 多种语言,以NuGet包的形式打包。 |
| 多语言同步 | 不支持 | 是的(OcrLanguage.French + OcrLanguage.German) |
| 置信度评分 | 仅按行收费 | 按字、行、页 |
| hOCR导出 | 不支持 | 是 |
| 许可模式 | 年度订阅费(599美元起/设备/年) | 永久($999一次性,Lite层) |
| 需要多种产品 | 是的(3+ 可获得全面保障) | 没有(一个包裹) |
| .NET Framework支持 | .NET Framework 4.x+ | .NET Framework 4.6.2+,. .NET 5/6/7/8/9 |
| 跨平台部署 | 是 | 是的(Windows、Linux、macOS、Docker、Azure、AWS) |
| NuGet 软件包 | Dynamsoft.LabelRecognizer | IronOcr |
快速入门:Dynamsoft OCR 到IronOCR 的迁移
步骤 1:替换 NuGet 软件包
移除 Dynamsoft 软件包:
dotnet remove package Dynamsoft.LabelRecognizer
从NuGet库安装IronOCR :
步骤 2:更新命名空间
// Before (Dynamsoft)
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;
// After (IronOCR)
using IronOcr;
步骤 3:初始化许可证
在应用程序启动时,用单个IronOCR许可证分配替换每个Dynamsoft静态InitLicense调用:
// Before (Dynamsoft — one call per product)
LabelRecognizer.InitLicense("DYNAMSOFT-LICENSE-KEY");
// After (IronOCR — one line, all features)
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
代码迁移示例
基于模板的识别到零配置引擎
Dynamsoft 的 JSON 模板系统在处理任何图像之前,会向 SDK 提供有关字符模型、区域规范和识别参数的详细说明。 对于大多数现实世界的 OCR 工作负载而言,这种配置会增加设置的复杂性,而不会带来识别方面的好处,因为底层 Tesseract 引擎会自动处理布局检测。
Dynamsoft 方法:
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;
// JSON template required before recognition
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
string invoiceTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""Invoice_Header"",
""ReferenceRegionNameArray"": [""HeaderRegion""],
""CharacterModelName"": ""NumberLetter""
}],
""ReferenceRegionArray"": [{
""Name"": ""HeaderRegion"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [0, 0],
""SecondPoint"": [100, 0],
""ThirdPoint"": [100, 20],
""FourthPoint"": [0, 20]
}
}]
}";
recognizer.AppendSettingsFromString(invoiceTemplate);
var results = recognizer.RecognizeFile("invoice.jpg");
var headerText = new StringBuilder();
foreach (var result in results)
foreach (var line in result.LineResults)
headerText.AppendLine(line.Text);
Console.WriteLine(headerText.ToString());
recognizer.Dispose();
IronOCR方法:
using IronOcr;
// No template file — region specified inline, engine auto-configures
var region = new CropRectangle(x: 0, y: 0, width: 1200, height: 200);
using var input = new OcrInput();
input.LoadImage("invoice.jpg", region);
input.Deskew();
var result = new IronTesseract().Read(input);
Console.WriteLine(result.Text);
Console.WriteLine($"Confidence: {result.Confidence}%");
Dynamsoft 的方法要求在处理任何图像之前,先编写、验证和部署 JSON 模板。 在AppendSettingsFromString中的拼写错误在运行时返回空结果——没有编译时验证。 IronOCR的CropRectangle是一个简单的构造函数:编译时类型检查,无外部文件,无部署工件。 有关所有目标模式,请参阅基于区域的 OCR 指南。
VIN码扫描及区域迁移
车辆识别码提取是 Dynamsoft 标签识别器 的一项专长。 其 VIN 模板模型针对特定的 17 位字母数字格式进行了优化。 迁移到IronOCR会将模板模型替换为预处理流程和区域目标定位,这样无需字符模型配置即可处理相同的 VIN 车牌条件。
Dynamsoft 方法:
using Dynamsoft.LabelRecognizer;
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
// VIN requires a specific character model and region configuration
string vinTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""VIN_Scan"",
""ReferenceRegionNameArray"": [""VIN_Zone""],
""CharacterModelName"": ""VIN""
}],
""ReferenceRegionArray"": [{
""Name"": ""VIN_Zone"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [10, 35],
""SecondPoint"": [90, 35],
""ThirdPoint"": [90, 65],
""FourthPoint"": [10, 65]
}
}]
}";
recognizer.AppendSettingsFromString(vinTemplate);
var results = recognizer.RecognizeFile("vehicle-vin.jpg");
string rawVin = results
.SelectMany(r => r.LineResults)
.Select(l => l.Text)
.FirstOrDefault() ?? string.Empty;
Console.WriteLine($"Raw VIN text: {rawVin}"); // still requires validation
recognizer.Dispose();
IronOCR方法:
using IronOcr;
using System.Text.RegularExpressions;
// Target the VIN plate region directly — no template file
var vinRegion = new CropRectangle(x: 100, y: 350, width: 800, height: 300);
using var input = new OcrInput();
input.LoadImage("vehicle-vin.jpg", vinRegion);
input.Contrast(); // recover faded stamped digits
input.Sharpen(); // clarify character boundaries on embossed plates
var result = new IronTesseract().Read(input);
// VIN: 17 chars, no I/O/Q
var vinMatch = Regex.Match(result.Text, @"\b[A-HJ-NPR-Z0-9]{17}\b");
string vin = vinMatch.Success ? vinMatch.Value : result.Text.Trim();
Console.WriteLine($"VIN: {vin}");
Console.WriteLine($"Confidence: {result.Confidence}%");
SecondPoint规范相同的像素参考框架——通过将Dynamsoft的百分比值乘以您的图像尺寸进行转换。 预处理管道 (Contrast, Sharpen) 替代了Dynamsoft在其VIN模板中烘焙的字符模型优化。 图像质量校正指南涵盖了浮雕和低对比度表面的滤镜选择。
多页 TIFF 批量处理
Dynamsoft 标签识别器可处理单张图像。 多页 TIFF 文档(常见于文档管理系统、医学影像档案和传真流程)需要外部迭代:加载每一帧,将其逐一传递给识别器,然后汇总结果。 IronOCR通过LoadImageFrames原生支持多帧TIFF。
Dynamsoft 方法:
using Dynamsoft.LabelRecognizer;
// Requires an external TIFF library to extract frames
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(genericTemplate);
// External library needed to iterate TIFF frames
var tiffImage = System.Drawing.Image.FromFile("scanned-batch.tiff");
int frameCount = tiffImage.GetFrameCount(
System.Drawing.Imaging.FrameDimension.Page);
var allText = new StringBuilder();
for (int i = 0; i < frameCount; i++)
{
tiffImage.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
string tempPath = $"frame_{i}.jpg";
tiffImage.Save(tempPath, System.Drawing.Imaging.ImageFormat.Jpeg);
var results = recognizer.RecognizeFile(tempPath);
foreach (var r in results)
foreach (var line in r.LineResults)
allText.AppendLine(line.Text);
System.IO.File.Delete(tempPath); // clean up temp files
}
Console.WriteLine(allText.ToString());
recognizer.Dispose();
IronOCR方法:
using IronOcr;
// No frame iteration, no temp files, no external TIFF library
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff"); // loads all frames natively
input.Deskew();
input.DeNoise();
var ocr = new IronTesseract();
var result = ocr.Read(input);
// Results organized per page
foreach (var page in result.Pages)
{
Console.WriteLine($"Frame {page.PageNumber}: {page.Lines.Count} lines");
Console.WriteLine(page.Text);
}
// Save entire batch as a single searchable PDF
result.SaveAsSearchablePdf("batch-searchable.pdf");
Dynamsoft方法需要System.Drawing用于帧提取,每帧在磁盘上创建临时文件,并在每次通过后手动清理。 IronOCR的LoadImageFrames在一次调用中读取所有帧——无需临时文件,无需帧索引跟踪。 在OCR之后,SaveAsSearchablePdf将整个批次归档为可搜索文档,仅需一次方法调用。 多帧 TIFF 指南和可搜索 PDF 输出指南详细介绍了这两种功能。
结构化词级结果解析
Dynamsoft RecognizeFile 返回一个DLRResult数组。 每个Location属性。 提取单词级位置需要将行文本按空格分割,并按比例分割行边界框——这种近似方法在比例字体上会失效。 IronOCR将单词级边界框呈现为每个OcrResult.Word对象上的类型化属性。
Dynamsoft 方法:
using Dynamsoft.LabelRecognizer;
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(settingsJson);
var results = recognizer.RecognizeFile("form-scan.jpg");
foreach (var dlrResult in results)
{
foreach (var lineResult in dlrResult.LineResults)
{
// Line-level data only — word boundaries are not provided
Console.WriteLine($"Text: {lineResult.Text}");
Console.WriteLine($"Confidence: {lineResult.Confidence}");
// Location is a quadrilateral — four corner points
var loc = lineResult.Location;
Console.WriteLine($"Top-left: ({loc.Points[0].X}, {loc.Points[0].Y})");
// To get word positions: split text and divide bounding box manually
var words = lineResult.Text.Split(' ');
int approxWidth = (loc.Points[1].X - loc.Points[0].X) / words.Length;
for (int i = 0; i < words.Length; i++)
{
int wordX = loc.Points[0].X + (i * approxWidth);
Console.WriteLine($" Word '{words[i]}' approx at x={wordX}");
}
}
}
recognizer.Dispose();
IronOCR方法:
using IronOcr;
var result = new IronTesseract().Read("form-scan.jpg");
// Word-level positions are first-class properties — no manual division
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"Paragraph at ({paragraph.X}, {paragraph.Y}): {paragraph.Text}");
foreach (var line in paragraph.Lines)
{
foreach (var word in line.Words)
{
Console.WriteLine(
$" Word: '{word.Text}' " +
$"at ({word.X},{word.Y}) " +
$"size {word.Width}x{word.Height} " +
$"confidence {word.Confidence}%");
}
}
}
}
IronOCR提供了真正的层次结构:页面包含段落,段落包含行,行包含单词,单词包含字符。 每个级别暴露出.Confidence,作为类型化的整数和双精度属性——不需要四边形坐标算术。 结构化结果指南记录了每个可访问的属性,置信度评分指南解释了自动化文档审查流程的置信度阈值。
用于高容量标签扫描的异步并行处理
Dynamsoft标签识别器是线程安全的,但其RecognizeFile调用是同步的。 将其封装在AppendSettingsFromString共享配置状态——在多个线程上加载模板需要仔细的初始化顺序。 IronOCR的Read,线程模型简单明了。
Dynamsoft 方法:
using Dynamsoft.LabelRecognizer;
using System.Threading.Tasks;
// InitLicense must be called once before parallel work begins
LabelRecognizer.InitLicense(licenseKey);
// Each thread needs its own recognizer instance with its own template load
var results = new System.Collections.Concurrent.ConcurrentBag<string>();
await Task.WhenAll(imagePaths.Select(async path =>
{
// Cannot share recognizer instances safely across tasks
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(templateJson); // reload JSON per instance
await Task.Run(() =>
{
var dlrResults = recognizer.RecognizeFile(path);
var text = string.Join("\n",
dlrResults.SelectMany(r => r.LineResults).Select(l => l.Text));
results.Add(text);
});
recognizer.Dispose();
}));
Console.WriteLine($"Processed {results.Count} images");
IronOCR方法:
using IronOcr;
using System.Collections.Concurrent;
using System.Threading.Tasks;
var extractedTexts = new ConcurrentDictionary<string, string>();
// Each IronTesseract instance is independent — no shared state
Parallel.ForEach(imagePaths, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
extractedTexts[imagePath] = result.Text;
});
foreach (var (path, text) in extractedTexts)
Console.WriteLine($"{System.IO.Path.GetFileName(path)}: {text.Length} characters");
IronOCR在并行工作开始前不需要任何初始化序列。 在应用程序启动时的一次IronOcr.License.LicenseKey分配激活所有实例。 每个线程不重新加载模板,每个实例不进行JSON验证。 对于非阻塞服务器端场景,异步OCR指南涵盖基于await的ASP.NET Core和Azure Functions模式。
从扫描标签存档输出可搜索的 PDF 文件
Dynamsoft 没有任何形式的 PDF 输出功能。 通过 Dynamsoft 处理的扫描标签档案仍然是仅图像文件——无法搜索,无法被文档管理系统索引,也不符合 PDF/A 归档标准。 IronOCR通过对OcrResult对象进行一次方法调用,添加可搜索的PDF输出。
Dynamsoft 方法:
using Dynamsoft.LabelRecognizer;
// Process scanned label — extract text into a string
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(labelTemplate);
var results = recognizer.RecognizeFile("scanned-labels.jpg");
var extractedText = new StringBuilder();
foreach (var r in results)
foreach (var line in r.LineResults)
extractedText.AppendLine(line.Text);
// Cannot create a searchable PDF — save text to a sidecar .txt file instead
System.IO.File.WriteAllText("scanned-labels.txt", extractedText.ToString());
// The original image remains unsearchable
Console.WriteLine("No PDF output available in Dynamsoft Label Recognizer.");
recognizer.Dispose();
IronOCR方法:
using IronOcr;
// Read, preprocess, and produce a searchable PDF archive in one pipeline
using var input = new OcrInput();
input.LoadImage("scanned-labels.jpg");
input.Deskew();
input.Contrast();
var ocr = new IronTesseract();
var result = ocr.Read(input);
// Searchable PDF: original image layer preserved, invisible text layer added
result.SaveAsSearchablePdf("scanned-labels-searchable.pdf");
Console.WriteLine($"Searchable PDF created. Confidence: {result.Confidence}%");
Console.WriteLine($"Extracted text preview: {result.Text.Substring(0, 100)}");
可搜索的PDF输出保留了原始扫描图像的全分辨率,并在其上添加了一层不可见的OCR文本层。文档管理系统、搜索索引和PDF查看器现在可以搜索标签内容。 可搜索的 PDF 操作指南和扫描文档处理指南涵盖多页存档和批量转换工作流程。
Dynamsoft OCR API 到IronOCR映射参考
| Dynamsoft 标签识别器 | IronOCR当量 |
|---|---|
LabelRecognizer.InitLicense(key) | IronOcr.License.LicenseKey = key |
new LabelRecognizer() | new IronTesseract() |
recognizer.AppendSettingsFromString(json) | 无需手动配置 — 自动配置 |
recognizer.RecognizeFile(path) | ocr.Read(path) |
recognizer.RecognizeByFile(path, templateName) | ocr.Read(path) |
recognizer.RecognizeBuffer(buffer, width, height, ...) | ocr.Read(input) |
DLRResult[](结果数组) | OcrResult(单一结果对象) |
DLRResult.LineResults | OcrResult.Lines |
DLRLineResult.Text | OcrResult.Line.Text |
DLRLineResult.Confidence | OcrResult.Line.Words[i].Confidence |
DLRLineResult.Location.Points[i] | OcrResult.Line.X, .Y, .Width, .Height |
ReferenceRegionArray(JSON) | new CropRectangle(x, y, w, h) |
LabelRecognizerParameterArray(JSON) | 不要求 |
模板中的CharacterModelName | 不要求 |
recognizer.Dispose() | using var ocr = new IronTesseract() |
| 不支持 PDF 输入 | input.LoadPdf(path) |
| 没有可搜索的 PDF 输出 | result.SaveAsSearchablePdf(path) |
| 不支持多页 TIFF 输入 | input.LoadImageFrames(path) |
| 条形码读取(单独产品) | ocr.Configuration.ReadBarCodes = true |
多个InitLicense调用(每个产品) | 单一IronOcr.License.LicenseKey分配 |
常见迁移问题和解决方案
问题 1:迁移后 AppendSettingsFromString 返回空结果
**Dynamsoft:**识别在DLRResult数组。 不会抛出异常。 从 Dynamsoft 迁移过来的团队有时会在结果解析代码中添加防御性空值检查,以防止这种静默故障。
**解决方案:**完全移除AppendSettingsFromString。 IronOCR无需模板配置。 如果需要特定区域目标,请用ReferenceRegionArray JSON:
// Remove all AppendSettingsFromString calls
// Replace region JSON with a CropRectangle constructor
var region = new CropRectangle(x: 0, y: 400, width: 1200, height: 300);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
var result = new IronTesseract().Read(input);
IronTesseract 设置指南记录了所有可以设置为属性而不是 JSON 字符串的引擎配置选项。
问题 2:应用程序启动时多次调用 InitLicense
**Dynamsoft:**使用标签识别器、条形码阅读器和文档标准化器的应用程序在启动时调用三个独立的InitLicense方法,每个都需要其自己的许可证密钥。 团队存储三个环境变量,独立轮换三个密钥,并调试三个独立的初始化失败。
**解决方案:**移除所有Dynamsoft InitLicense调用。 替换为一条IronOCR线:
// Remove:
// LabelRecognizer.InitLicense(mrzKey);
// BarcodeReader.InitLicense(barcodeKey);
// DocumentNormalizer.InitLicense(docKey);
// Add once, at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
一个环境变量即可激活IronOCR 的所有功能——OCR、条形码、PDF 处理以及 125 多种语言——无需对每个功能进行初始化。
问题 3:LineResult 文本聚合产生乱码输出
Dynamsoft:DLRResult。 将DLRResult对象的顺序是区域检测顺序,而不是读取顺序。
**解决方案:**IronOCR的结果层次结构按阅读顺序组织输出。 使用Pages → Paragraphs → Lines结构以自然文档顺序访问文本:
var result = new IronTesseract().Read(imagePath);
// Reading-order text — no manual aggregation
Console.WriteLine(result.Text);
// Or access paragraph-level groupings
foreach (var paragraph in result.Pages[0].Paragraphs)
Console.WriteLine(paragraph.Text);
问题 4:部署服务器上缺少模板 JSON 文件
**Dynamsoft:**模板 JSON 文件是单独的部署工件。 当模板文件丢失或在新服务器上路径不正确时,AppendSettingsFromString失败——有时默默地,有时伴随运行时异常——而且部署破坏了识别,而无需接触应用程序代码。
解决方法: IronOCR没有模板文件。 替换NuGet包并更新命名空间后,部署工件列表缩小到应用程序二进制文件和一个环境变量。 如有需要,添加启动验证检查:
// Validate license at startup — no template files to check
if (!IronOcr.License.IsValidLicense)
throw new InvalidOperationException("IronOCR license key is invalid or missing.");
var ocr = new IronTesseract();
// Ready to process — no file dependencies
问题五:跨多个产品的处置链管理
**Dynamsoft:**每个Dynamsoft产品实例(LabelRecognizer, BarcodeReader, DocumentNormalizer) 实现IDisposable。 聚合多个产品的服务类带有多层次的Dispose调用会导致本地资源泄漏,表现为负载下的内存增长。
**解决方案:**IronOCR的IDisposable,但处理模型更简单——一个类,一个模式。 在DI容器中注册一个using块来获取短生命周期的实例:
// Short-lived pattern
using var input = new OcrInput();
input.LoadImage(imagePath);
var result = new IronTesseract().Read(input);
// Long-lived singleton (register in Program.cs)
builder.Services.AddSingleton<IronTesseract>();
进度跟踪指南涵盖了长时间运行的批处理作业的生命周期管理,异步 OCR 指南展示了ASP.NET Core中的单例模式。
问题 6:自定义标签格式不支持角色模型
**Dynamsoft:**模板中的CharacterModelName字段引用一个必须存在于Dynamsoft SDK安装目录中的模型文件。 自定义角色模型需要从 Dynamsoft 的门户网站下载额外的模型文件,并将其放置在正确的 SDK 路径中。 模型缺失会导致识别失败,并出现晦涩难懂的运行时错误。
解决方法: IronOCR不使用字符模型文件。 对于自定义或特殊字体,请使用自定义语言培训:
// No character model files needed
// For specialized fonts, use a custom language pack
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English; // or load a custom trained pack
using var input = new OcrInput();
input.LoadImage(specializedFontImage);
input.Binarize(); // helps with specialized font clarity
var result = ocr.Read(input);
自定义字体训练指南涵盖了在不进行任何文件路径配置的情况下,为专有标签字体训练自定义语言包。
Dynamsoft OCR 迁移检查清单
迁移前
审核代码库中所有与 Dynamsoft 相关的引用:
# Find all Dynamsoft using statements
grep -r "using Dynamsoft" --include="*.cs" .
# Find InitLicense calls (one per product)
grep -r "InitLicense" --include="*.cs" .
# Find AppendSettingsFromString calls (template loads)
grep -r "AppendSettingsFromString" --include="*.cs" .
# Find template JSON strings (inline or file references)
grep -r "LabelRecognizerParameterArray\|ReferenceRegionArray\|CharacterModelName" --include="*.cs" .
# Find RecognizeFile and RecognizeByFile calls
grep -r "RecognizeFile\|RecognizeByFile\|RecognizeBuffer" --include="*.cs" .
# Find LineResult result parsing patterns
grep -r "LineResults\|DLRResult\|DLRLineResult" --include="*.cs" .
# Identify any JSON template files in the project
find . -name "*.json" | xargs grep -l "LabelRecognizerParameterArray" 2>/dev/null
调查结果:
- 计算
InitLicense调用点数量(每个使用的Dynamsoft产品一个) - 计算
AppendSettingsFromString调用点数量(每个识别模板一个) - 列出所有将在迁移后删除的 JSON 模板文件
- 识别任何
CropRectangle) - 注意哪些功能由单独的产品涵盖(条形码、文档规范化)
代码迁移
- 移除
Dynamsoft.LabelRecognizerNuGet包(以及任何其他Dynamsoft包) - 安装
IronOcrNuGet包(dotnet add package IronOcr) - 将所有
using IronOcr; - 在应用程序启动时用一个
LabelRecognizer.InitLicense(key)调用 - 移除所有
AppendSettingsFromString(json)调用——无必须的等效品 - 用
ReferenceRegionArrayJSON坐标 - 用
new LabelRecognizer()实例化 - 用
recognizer.RecognizeFile(path) - 用
DLRLineResult结果迭代 - 用
lineResult.Text字符串聚合 - 用
BarcodeReader.InitLicense+BarcodeReader.DecodeFile - 移除多产品
using var ocr = new IronTesseract()替换 - 从项目和部署工件中删除 JSON 模板文件
- 用
input.LoadImageFrames(path)替换TIFF文件的帧迭代循环 - 在需要存档扫描输出的地方添加
result.SaveAsSearchablePdf(outputPath)
后迁移
- 在应用程序启动时验证
true - 确认所有识别结果为之前工作的输入返回非空
result.Text - 在代表性样本上检查
result.Confidence—值高于80%表示识别质量良好 - 通过将
CropRectangle输出与之前的Dynamsoft区域结果对比来测试区域定位精度 - 通过在以前需要Dynamsoft条形码阅读器的输入上运行
ocr.Configuration.ReadBarCodes = true验证条形码阅读 - 验证多页TIFF处理产生每帧一个
OcrResult.Page - 确认可搜索的 PDF 输出在 PDF 查看器中支持文本搜索。
- 使用
Parallel.ForEach运行并行处理测试,并验证没有线程争用 - 测试所有部署目标(Linux、Docker、Azure),以确认单包部署无需 JSON 模板文件即可正常工作
- 确认部署配置中不存在 Dynamsoft 许可证密钥环境变量
迁移到IronOCR的主要优势
一个包消除了多产品协调税。 每种能力——通用OCR、MRZ提取、条形码阅读、原生PDF输入、可搜索PDF输出、预处理和125+种语言——作为一个单一IronOcr NuGet包提供。 版本升级影响一个.csproj文件中的一个包条目。许可证密钥旋转是一个环境变量。 部署工件清单缩减为应用程序二进制文件,不再包含 JSON 模板文件和角色模型目录。
零配置文件依赖。Dynamsoft模板系统要求 JSON 文件在运行时存在且路径正确。IronOCR 除了NuGet包本身之外,没有任何其他运行时文件依赖。 Docker 镜像变得具有确定性:通过 CI 测试的镜像将完全在生产环境中运行。 Docker部署指南展示了一个完整的Dockerfile,只需要一个apt-get install行用于Linux。
结构化输出可减少集成代码。 Dynamsoft返回原始LineResult文本字符串。 结构化数据提取——字段位置、单词边界、每个标记的置信度——需要对您的代码进行后处理和测试。IronOCR的结果层次结构将页面、段落、行、单词和字符作为类型集合呈现,每个级别都有坐标和置信度分数。 从 Dynamsoft 迁移过来的团队通常会删除 30-50% 的结果处理代码,因为IronOCR提供了他们之前手动构建的结构。 OCR 结果功能页面记录了完整的输出模型。
永久授权消除了年度预算的不确定性。Dynamsoft标签识别器没有永久授权选项。 仅标签识别一项,运行五年的处理集群每年就要花费 2995 美元以上,还不包括条形码或文档规范化产品。 IronOCR的$999 Lite许可证是一次性购买,涵盖所有功能无期限。 对于政府、Enterprise和长期生产部署而言,从核心文档处理组件中移除年度续订依赖性,可以降低采购复杂性,并消除项目进行中订阅失效的风险。 IronOCR许可页面列出了所有级别以及每个级别涵盖的内容。
无需平台特定配置即可跨平台使用。IronOCRIronOCRNuGet 的运行时标识符图谱,为 Windows x64、Linux x64、macOS x64 和 macOS ARM 解析正确的运行时二进制文件。 无条件<PackageReference>块,无平台检测代码,无本地二进制路径设置。在Windows、Linux、AWS Lambda和Azure App Service上编译和运行相同的using IronOcr;代码,无需修改。
语言覆盖范围可根据应用需求进行扩展。Dynamsoft标签识别器专为拉丁字符 MRZ 格式而设计。 非拉丁文字——阿拉伯语、中文、日语、韩语、希伯来语——不在其设计范围之内。 IronOCR支持以单独的NuGet包安装125+种语言:dotnet add package IronOcr.Languages.Arabic无需在识别管道中更改代码即可添加阿拉伯语支持。语言索引列出了每个可用的语言包。 对于处理国际身份证件、多语言货运标签或跨境发票的应用程序而言,这种广度意味着一个库就能涵盖不断增长的应用程序遇到的每一种文档类型。
