Migración de Dynamsoft OCR a IronOCR
Esta guía proporciona una ruta de migración completa para desarrolladores .NET que pasan de Reconocedor de etiquetas Dynamsoft a IronOCR . Abarca la sustitución de paquetes NuGet , las actualizaciones de espacios de nombres, la inicialización de licencias y ejemplos prácticos de migración de código para escenarios distintos de las comparaciones de capacidades generales, incluyendo la eliminación de la configuración de plantillas, la eliminación de JSON de la configuración en tiempo de ejecución, la migración de la definición de regiones y la simplificación del análisis de resultados.
¿Por qué migrar desde Dynamsoft OCR?
Dynamsoft Label Recognizer es una herramienta especializada diseñada para un propósito específico. Esta precisión funciona bien para implementaciones limitadas, pero genera problemas en cuanto el alcance de la aplicación se extiende más allá del caso de uso original de MRZ o VIN.
La configuración de tiempo de ejecución JSON es una superficie de mantenimiento. Cada flujo de trabajo de reconocimiento de Dynamsoft comienza con AppendSettingsFromString, cargando un documento JSON que declara arreglos de parámetros, modelos de caracteres y referencias de regiones. Esas plantillas JSON son artefactos de despliegue independientes, no están compiladas en el binario. Requieren control de versiones, gestión de la canalización de despliegue y actualizaciones manuales cuando Dynamsoft cambia los esquemas de las plantillas entre las diferentes versiones del SDK.IronOCR no requiere archivos de configuración: instancie IronTesseract, llame a .Read(), y el motor selecciona automáticamente la configuración adecuada.
Precios de suscripción anual para compuestos. Licencias de Reconocedor de etiquetas Dynamsoft a partir de $599 por dispositivo al año. No existe una opción perpetua. Un clúster de procesamiento de cinco dispositivos cuesta más de 2995 dólares al año, y ese presupuesto solo cubre el reconocimiento de etiquetas estructuradas y de la zona de resonancia magnética (MRZ). Si se añade Dynamsoft Barcode Reader para códigos de barras o Dynamsoft Document Normalizer para la corrección de bordes, la factura anual se multiplica por la cantidad de productos. La licencia Lite de IronOCR es $999 de una sola vez y cubre OCR general, etiquetas estructuradas, códigos de barras, PDF nativo, salida de PDF buscable y más de 125 idiomas desde un solo paquete.
La definición de región requiere plantillas JSON. Definir una región de reconocimiento en Dynamsoft significa crear un bloque JSON de ReferenceRegionArray, referenciarlo en un LabelRecognizerParameterArray, y cargar el documento completo antes de que comience cualquier procesamiento de imágenes.IronOCR utiliza un único constructor CropRectangle(x, y, width, height) pasado directamente a OcrInput.LoadImage. Cambiar una región es una edición numérica, no un análisis de un documento JSON.
El análisis de resultados es completamente su responsabilidad. RecognizeFile y RecognizeByFile devuelven arreglos de LineResult que contienen cadenas de texto sin procesar. Cada estructura que necesite (desplazamientos de campo, conversiones de fecha, validación de dígitos de control, manejo de separadores de nombres) requiere código de análisis personalizado sobre esa salida sin procesar.IronOCR devuelve un OcrResult con .Pages, .Lines, .Words, y .Characters como colecciones tipadas con coordenadas de cuadro delimitador, puntuaciones de confianza y metadatos de fuente ya poblados.
La falta de compatibilidad nativa con PDF crea una dependencia oculta. Reconocedor de etiquetas Dynamsoft no tiene capacidad de entrada de PDF. Cualquier archivo PDF que llegue a su canalización de procesamiento requiere una biblioteca externa para convertir cada página en un mapa de bits, un bucle de iteración de páginas y un paso de agregación de resultados antes de la primera llamada a Dynamsoft.IronOCR lee PDFs nativamente: new IronTesseract().Read("document.pdf") procesa cada página sin una dependencia secundaria, un bucle de renderizado o una carpeta de imágenes temporales.
Los bloques de inicialización de múltiples productos crecen con el alcance. Una aplicación de Dynamsoft que maneja etiquetas estructuradas, códigos de barras y normalización de documentos lleva tres llamadas estáticas InitLicense en el inicio, tres cadenas de disposición y tres dependencias de versión de SDK independientes. Actualizar el SDK implica coordinar todos los productos.IronOCR tiene una línea de inicialización y una versión de paquete, independientemente de las funcionalidades que utilice la aplicación.
El problema fundamental
Dynamsoft requiere que se cargue un archivo de configuración JSON en tiempo de ejecución antes de que pueda comenzar el reconocimiento:
// 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);
// 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);
' Dynamsoft: JSON template required before any image processing
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
Dim settings As String = "{
""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
Dim 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: 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);
Imports IronOcr
' IronOCR: no JSON, no template files — region is a constructor argument
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim region As New CropRectangle(x:=50, y:=400, width:=900, height:=200)
Using input As New OcrInput()
input.LoadImage(imagePath, region)
Dim result = New IronTesseract().Read(input)
Console.WriteLine(result.Text)
End Using
IronOCR vs Dynamsoft OCR: Comparación de características
La tabla que aparece a continuación detalla la diferencia total de funcionalidades entre las dos bibliotecas.
| Característica | Reconocedor de etiquetas Dynamsoft | IronOCR |
|---|---|---|
| OCR de documentos generales | No soportado | Soporte completo |
| Reconocimiento de MRZ | Especializado (salida de texto sin formato) | Integrado con campos estructurados |
| reconocimiento del VIN | Especializado (se requiere plantilla) | OCR estándar con segmentación por región |
| Lectura de etiquetas industriales | Especializado (se requiere plantilla) | Sí, a través de CropRectangle |
| Configuración de los ajustes de tiempo de ejecución | Obligatorio (JSON a través de AppendSettingsFromString) |
No es necesario |
| Artefactos de despliegue de plantillas | Archivos JSON obligatorios | None |
| Entrada nativa de PDF | No soportado | Sí |
| PDF protegido con contraseña | No soportado | Sí |
| Entrada TIFF de varias páginas | Repetición manual de páginas | Nativo (LoadImageFrames) |
| Salida en PDF con capacidad de búsqueda | No soportado | Sí (SaveAsSearchablePdf) |
| Lectura de códigos de barras | Producto independiente (lector de códigos de barras Dynamsoft) | Integrado (ReadBarCodes = true) |
| Preprocesamiento automático | Limitado | Sí (Desinclinar, Reducir ruido, Contraste, Binarizar, Enfocar, Dilatar, Erosionar) |
| Salida estructurada (palabras, líneas, párrafos) | Cadenas de texto sin procesar LineResult |
Completamente escrito con coordenadas y confianza |
| Soporte de idiomas | Limitado (Zona de Reparación de Mercancías Latina) | Más de 125 idiomas, agrupados como paquetes NuGet. |
| Multilingüe simultáneo | No soportado | Sí (OcrLanguage.French + OcrLanguage.German) |
| Puntuaciones de confianza | Solo por línea | Por palabra, línea, página |
| Exportación hOCR | No soportado | Sí |
| Modelo de licencia | Suscripción anual (599 $ o más por dispositivo al año) | Perpetua ($999 de una sola vez, nivel Lite) |
| Se requieren varios productos | Sí (3+ para cobertura total) | No (un paquete) |
| Compatibilidad con .NET Framework | .NET Framework 4.x+ | .NET Framework 4.6.2+, .NET 5/6/7/8/9 |
| Implementación multiplataforma | Sí | Sí (Windows, Linux, macOS, Docker, Azure, AWS) |
| Paquete NuGet | Dynamsoft.LabelRecognizer |
IronOcr |
Inicio rápido: Migración de Dynamsoft OCR a IronOCR
Paso 1: Sustituir el paquete NuGet
Elimine el paquete Dynamsoft:
dotnet remove package Dynamsoft.LabelRecognizer
dotnet remove package Dynamsoft.LabelRecognizer
Instala IronOCR desde la galería NuGet :
dotnet add package IronOcr
Paso 2: Actualizar los espacios de nombres
// Before (Dynamsoft)
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;
// After (IronOCR)
using IronOcr;
// Before (Dynamsoft)
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;
// After (IronOCR)
using IronOcr;
Imports IronOcr
Paso 3: Inicializar licencia
Reemplace cada llamada estática de Dynamsoft InitLicense con una sola asignación de licencia de IronOCR al inicio de la aplicación:
// Before (Dynamsoft — one call per product)
LabelRecognizer.InitLicense("DYNAMSOFT-LICENSE-KEY");
// After (IronOCR — one line, all features)
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Before (Dynamsoft — one call per product)
LabelRecognizer.InitLicense("DYNAMSOFT-LICENSE-KEY");
// After (IronOCR — one line, all features)
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
' Before (Dynamsoft — one call per product)
LabelRecognizer.InitLicense("DYNAMSOFT-LICENSE-KEY")
' After (IronOCR — one line, all features)
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Ejemplos de migración de código
Reconocimiento basado en plantillas para un motor de configuración cero
El sistema de plantillas JSON de Dynamsoft proporciona al SDK instrucciones detalladas sobre los modelos de caracteres, las especificaciones de región y los parámetros de reconocimiento antes de que se procese cualquier imagen. Para la mayoría de las cargas de trabajo de OCR del mundo real, esa configuración añade complejidad a la configuración sin beneficios de reconocimiento, porque el motor Tesseract subyacente gestiona la detección del diseño automáticamente.
Enfoque de 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();
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();
Imports Dynamsoft.LabelRecognizer
Imports Dynamsoft.Core
Imports System.Text
' JSON template required before recognition
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
Dim invoiceTemplate As String = "{
""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)
Dim results = recognizer.RecognizeFile("invoice.jpg")
Dim headerText As New StringBuilder()
For Each result In results
For Each line In result.LineResults
headerText.AppendLine(line.Text)
Next
Next
Console.WriteLine(headerText.ToString())
recognizer.Dispose()
Enfoque 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}%");
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}%");
Imports IronOcr
' No template file — region specified inline, engine auto-configures
Dim region As New CropRectangle(x:=0, y:=0, width:=1200, height:=200)
Using input As New OcrInput()
input.LoadImage("invoice.jpg", region)
input.Deskew()
Dim result = New IronTesseract().Read(input)
Console.WriteLine(result.Text)
Console.WriteLine($"Confidence: {result.Confidence}%")
End Using
El método de Dynamsoft requiere la creación, validación e implementación de una plantilla JSON antes de procesar cualquier imagen. Un error tipográfico en AppendSettingsFromString devuelve resultados vacíos en tiempo de ejecución — no hay validación en tiempo de compilación. El CropRectangle de IronOCR es un constructor simple: verificación de tipo en tiempo de compilación, sin archivos externos, sin artefactos de implementación. Consulte la guía de OCR basada en regiones para conocer todos los patrones de segmentación.
Escaneo del código VIN con migración de región
La extracción del número de identificación del vehículo es una especialidad de Dynamsoft Label Recognizer. Su modelo de plantilla VIN está optimizado para el formato alfanumérico específico de 17 caracteres. La migración a IronOCR reemplaza el modelo de plantilla con una canalización de preprocesamiento y una segmentación de regiones, que maneja las mismas condiciones de la placa VIN sin necesidad de configurar un modelo de caracteres.
Enfoque de 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();
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();
Imports Dynamsoft.LabelRecognizer
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
' VIN requires a specific character model and region configuration
Dim vinTemplate As String = "{
""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)
Dim results = recognizer.RecognizeFile("vehicle-vin.jpg")
Dim rawVin As String = results _
.SelectMany(Function(r) r.LineResults) _
.Select(Function(l) l.Text) _
.FirstOrDefault() OrElse String.Empty
Console.WriteLine($"Raw VIN text: {rawVin}") ' still requires validation
recognizer.Dispose()
Enfoque 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}%");
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}%");
Imports IronOcr
Imports System.Text.RegularExpressions
' Target the VIN plate region directly — no template file
Dim vinRegion As New CropRectangle(x:=100, y:=350, width:=800, height:=300)
Using input As New OcrInput()
input.LoadImage("vehicle-vin.jpg", vinRegion)
input.Contrast() ' recover faded stamped digits
input.Sharpen() ' clarify character boundaries on embossed plates
Dim result = New IronTesseract().Read(input)
' VIN: 17 chars, no I/O/Q
Dim vinMatch = Regex.Match(result.Text, "\b[A-HJ-NPR-Z0-9]{17}\b")
Dim vin As String = If(vinMatch.Success, vinMatch.Value, result.Text.Trim())
Console.WriteLine($"VIN: {vin}")
Console.WriteLine($"Confidence: {result.Confidence}%")
End Using
Las coordenadas CropRectangle usan el mismo marco de referencia de píxeles que la especificación basada en porcentaje de Dynamsoft de SecondPoint — convierta multiplicando los valores de porcentaje de Dynamsoft por las dimensiones de su imagen. La tubería de preprocesamiento (Contrast, Sharpen) reemplaza la optimización del modelo de caracteres que Dynamsoft integra en su plantilla VIN. La guía de corrección de la calidad de imagen abarca la selección de filtros para superficies con relieve y de bajo contraste.
Procesamiento por lotes de archivos TIFF de varias páginas
Dynamsoft Label Recognizer procesa imágenes individuales. Los documentos TIFF de varias páginas, habituales en sistemas de gestión documental, archivos de imágenes médicas y sistemas de fax, requieren una iteración externa: cargar cada fotograma, pasarlo individualmente por el reconocedor y agregar los resultados.IronOCR maneja archivos TIFF de múltiples cuadros nativamente a través de LoadImageFrames.
Enfoque de 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();
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();
Imports Dynamsoft.LabelRecognizer
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Text
' Requires an external TIFF library to extract frames
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
recognizer.AppendSettingsFromString(genericTemplate)
' External library needed to iterate TIFF frames
Dim tiffImage As Image = Image.FromFile("scanned-batch.tiff")
Dim frameCount As Integer = tiffImage.GetFrameCount(FrameDimension.Page)
Dim allText As New StringBuilder()
For i As Integer = 0 To frameCount - 1
tiffImage.SelectActiveFrame(FrameDimension.Page, i)
Dim tempPath As String = $"frame_{i}.jpg"
tiffImage.Save(tempPath, Imaging.ImageFormat.Jpeg)
Dim results = recognizer.RecognizeFile(tempPath)
For Each r In results
For Each line In r.LineResults
allText.AppendLine(line.Text)
Next
Next
File.Delete(tempPath) ' clean up temp files
Next
Console.WriteLine(allText.ToString())
recognizer.Dispose()
Enfoque 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");
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");
Imports IronOcr
' No frame iteration, no temp files, no external TIFF library
Using input As New OcrInput()
input.LoadImageFrames("scanned-batch.tiff") ' loads all frames natively
input.Deskew()
input.DeNoise()
Dim ocr As New IronTesseract()
Dim result = ocr.Read(input)
' Results organized per page
For Each page In result.Pages
Console.WriteLine($"Frame {page.PageNumber}: {page.Lines.Count} lines")
Console.WriteLine(page.Text)
Next
' Save entire batch as a single searchable PDF
result.SaveAsSearchablePdf("batch-searchable.pdf")
End Using
El enfoque de Dynamsoft requiere System.Drawing para la extracción de cuadros, un archivo temporal en disco por cuadro y limpieza manual después de cada pasada. El LoadImageFrames de IronOCR lee todos los cuadros en una sola llamada — sin archivos temporales, sin seguimiento de índices de cuadros. Después del OCR, SaveAsSearchablePdf archiva el lote completo como un documento buscable en una llamada de método. La guía de formato TIFF multifotograma y la guía de salida PDF con función de búsqueda cubren ambas capacidades en detalle.
Análisis estructurado de resultados a nivel de palabra
Dynamsoft RecognizeFile devuelve un arreglo DLRResult. Cada DLRResult contiene una colección LineResults de objetos DLRLineResult con una propiedad Text y una propiedad Location que mantiene el cuadrilátero delimitador. La extracción de posiciones a nivel de palabra requiere dividir el texto de la línea por espacios en blanco y dividir proporcionalmente el cuadro delimitador de la línea, una aproximación que falla en fuentes proporcionales.IronOCR muestra cuadros delimitadores a nivel de palabra como propiedades tipadas en cada objeto OcrResult.Word.
Enfoque de 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();
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();
Imports Dynamsoft.LabelRecognizer
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
recognizer.AppendSettingsFromString(settingsJson)
Dim results = recognizer.RecognizeFile("form-scan.jpg")
For Each dlrResult In results
For Each 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
Dim 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
Dim words = lineResult.Text.Split(" "c)
Dim approxWidth As Integer = (loc.Points(1).X - loc.Points(0).X) \ words.Length
For i As Integer = 0 To words.Length - 1
Dim wordX As Integer = loc.Points(0).X + (i * approxWidth)
Console.WriteLine($" Word '{words(i)}' approx at x={wordX}")
Next
Next
Next
recognizer.Dispose()
Enfoque 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}%");
}
}
}
}
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}%");
}
}
}
}
Imports IronOcr
Dim result = New IronTesseract().Read("form-scan.jpg")
' Word-level positions are first-class properties — no manual division
For Each page In result.Pages
For Each paragraph In page.Paragraphs
Console.WriteLine($"Paragraph at ({paragraph.X}, {paragraph.Y}): {paragraph.Text}")
For Each line In paragraph.Lines
For Each word In line.Words
Console.WriteLine(
$" Word: '{word.Text}' " &
$"at ({word.X},{word.Y}) " &
$"size {word.Width}x{word.Height} " &
$"confidence {word.Confidence}%")
Next
Next
Next
Next
IronOCR proporciona una jerarquía real: las páginas contienen párrafos, los párrafos contienen líneas, las líneas contienen palabras y las palabras contienen caracteres. Cada nivel expone .X, .Y, .Width, .Height, y .Confidence como propiedades tipadas de enteros y dobles — no se requiere aritmética de coordenadas de cuadrilátero. La guía de resultados estructurados documenta todas las propiedades accesibles, y la guía de puntuación de confianza explica los umbrales de confianza para los procesos automatizados de revisión de documentos.
Procesamiento paralelo asíncrono para el escaneo de etiquetas de alto volumen
El reconocedor de etiquetas de Dynamsoft es seguro para hilos, pero su llamada RecognizeFile es sincrónica. Encapsularlo en Task.Run produce procesamiento en paralelo, pero cada llamada comparte el estado de configuración a través de AppendSettingsFromString — cargar plantillas en múltiples hilos requiere una secuencia de inicialización cuidadosa. Las instancias IronTesseract de IronOCR son independientes: cree una por tarea, llame a Read, y el modelo de hilos es sencillo.
Enfoque de 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");
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");
Imports Dynamsoft.LabelRecognizer
Imports System.Threading.Tasks
Imports System.Collections.Concurrent
' InitLicense must be called once before parallel work begins
LabelRecognizer.InitLicense(licenseKey)
' Each thread needs its own recognizer instance with its own template load
Dim results As New ConcurrentBag(Of String)()
Await Task.WhenAll(imagePaths.Select(Async Function(path)
' Cannot share recognizer instances safely across tasks
Dim recognizer As New LabelRecognizer()
recognizer.AppendSettingsFromString(templateJson) ' reload JSON per instance
Await Task.Run(Sub()
Dim dlrResults = recognizer.RecognizeFile(path)
Dim text = String.Join(vbLf, dlrResults.SelectMany(Function(r) r.LineResults).Select(Function(l) l.Text))
results.Add(text)
End Sub)
recognizer.Dispose()
End Function))
Console.WriteLine($"Processed {results.Count} images")
Enfoque 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");
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");
Imports IronOcr
Imports System.Collections.Concurrent
Imports System.Threading.Tasks
Dim extractedTexts As New ConcurrentDictionary(Of String, String)()
' Each IronTesseract instance is independent — no shared state
Parallel.ForEach(imagePaths, Sub(imagePath)
Dim ocr As New IronTesseract()
Dim result = ocr.Read(imagePath)
extractedTexts(imagePath) = result.Text
End Sub)
For Each kvp In extractedTexts
Dim path = kvp.Key
Dim text = kvp.Value
Console.WriteLine($"{System.IO.Path.GetFileName(path)}: {text.Length} characters")
Next
IronOCR no requiere ninguna secuencia de inicialización antes de que comience el trabajo en paralelo. Una asignación IronOcr.License.LicenseKey en el inicio de la aplicación activa todas las instancias. No se requiere recargar la plantilla por hilo ni validación JSON por instancia. Para escenarios no bloqueantes del lado del servidor, la guía de OCR asíncrono cubre patrones basados en await para ASP.NET Core y Azure Functions.
Salida PDF con capacidad de búsqueda a partir de archivos de etiquetas escaneadas
Dynamsoft no tiene capacidad de generar archivos PDF de ningún tipo. Los archivos de etiquetas escaneadas procesados a través de Dynamsoft permanecen como archivos de solo imagen: no se pueden buscar, no son indexables por los sistemas de gestión de documentos y no cumplen con los estándares de archivo PDF/A.IronOCR agrega salida de PDF buscable como una sola llamada de método en el objeto OcrResult.
Enfoque de 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();
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();
Imports Dynamsoft.LabelRecognizer
Imports System.IO
Imports System.Text
' Process scanned label — extract text into a string
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer = New LabelRecognizer()
recognizer.AppendSettingsFromString(labelTemplate)
Dim results = recognizer.RecognizeFile("scanned-labels.jpg")
Dim extractedText = New StringBuilder()
For Each r In results
For Each line In r.LineResults
extractedText.AppendLine(line.Text)
Next
Next
' Cannot create a searchable PDF — save text to a sidecar .txt file instead
File.WriteAllText("scanned-labels.txt", extractedText.ToString())
' The original image remains unsearchable
Console.WriteLine("No PDF output available in Dynamsoft Label Recognizer.")
recognizer.Dispose()
Enfoque 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)}");
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)}");
Imports IronOcr
' Read, preprocess, and produce a searchable PDF archive in one pipeline
Using input As New OcrInput()
input.LoadImage("scanned-labels.jpg")
input.Deskew()
input.Contrast()
Dim ocr As New IronTesseract()
Dim 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)}")
End Using
El archivo PDF con capacidad de búsqueda conserva la imagen escaneada original a resolución completa y añade una capa de texto OCR invisible. Los sistemas de gestión documental, los índices de búsqueda y los visores de PDF ahora pueden buscar en el contenido de las etiquetas. El manual en formato PDF con función de búsqueda y la guía de procesamiento de documentos escaneados abarcan archivos de varias páginas y flujos de trabajo de conversión por lotes.
Referencia de mapeo de la API OCR de Dynamsoft a IronOCR
| Reconocedor de etiquetas Dynamsoft | Equivalente a IronOCR |
|---|---|
LabelRecognizer.InitLicense(key) |
IronOcr.License.LicenseKey = key |
new LabelRecognizer() |
new IronTesseract() |
recognizer.AppendSettingsFromString(json) |
No es necesario: se configura automáticamente. |
recognizer.RecognizeFile(path) |
ocr.Read(path) |
recognizer.RecognizeByFile(path, templateName) |
ocr.Read(path) |
recognizer.RecognizeBuffer(buffer, width, height, ...) |
input.LoadImage(imageBytes) y luego ocr.Read(input) |
DLRResult[] (arreglo de resultados) |
OcrResult (objeto de resultado único) |
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) |
No es necesario |
CharacterModelName en plantilla |
No es necesario |
recognizer.Dispose() |
using var ocr = new IronTesseract() |
| No admite entrada de archivos PDF. | input.LoadPdf(path) |
| No se genera un archivo PDF con capacidad de búsqueda. | result.SaveAsSearchablePdf(path) |
| No se admite entrada TIFF de varias páginas. | input.LoadImageFrames(path) |
| Lectura de códigos de barras (producto aparte) | ocr.Configuration.ReadBarCodes = true |
Múltiples llamadas InitLicense (por producto) |
Asignación simple IronOcr.License.LicenseKey |
Problemas comunes de migración y soluciones
Problema 1: AppendSettingsFromString devuelve resultados vacíos después de la migración.
Dynamsoft: El reconocimiento devuelve en silencio arreglos DLRResult vacíos cuando AppendSettingsFromString recibe una cadena JSON malformada. No se produce ninguna excepción. Los equipos que migran desde Dynamsoft a veces añaden comprobaciones de nulidad defensivas en todo su código de análisis de resultados para protegerse contra este fallo silencioso.
Solución: Retire AppendSettingsFromString completamente.IronOCR no requiere configuración de plantilla. Si se necesita un enfoque específico de región, reemplace el JSON ReferenceRegionArray con un CropRectangle:
// 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);
// 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);
Imports System
' Remove all AppendSettingsFromString calls
' Replace region JSON with a CropRectangle constructor
Dim region As New CropRectangle(x:=0, y:=400, width:=1200, height:=300)
Using input As New OcrInput()
input.LoadImage(imagePath, region)
Dim result = New IronTesseract().Read(input)
End Using
La guía de configuración de IronTesseract documenta todas las opciones de configuración del motor que se pueden establecer como propiedades en lugar de cadenas JSON.
Problema 2: Múltiples llamadas a InitLicense al iniciar la aplicación
Dynamsoft: Una aplicación que usa reconocedor de etiquetas, lector de códigos de barras y normalizador de documentos llama a tres métodos InitLicense separados en el inicio, cada uno requiriendo su propia clave de licencia. Los equipos almacenan tres variables de entorno, rotan tres claves de forma independiente y depuran tres fallos de inicialización distintos.
Solución: Retire todas las llamadas InitLicense de Dynamsoft. Reemplazar con una línea de IronOCR:
// Remove:
// LabelRecognizer.InitLicense(mrzKey);
// BarcodeReader.InitLicense(barcodeKey);
// DocumentNormalizer.InitLicense(docKey);
// Add once, at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// Remove:
// LabelRecognizer.InitLicense(mrzKey);
// BarcodeReader.InitLicense(barcodeKey);
// DocumentNormalizer.InitLicense(docKey);
// Add once, at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
' Remove:
' LabelRecognizer.InitLicense(mrzKey)
' BarcodeReader.InitLicense(barcodeKey)
' DocumentNormalizer.InitLicense(docKey)
' Add once, at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
Una única variable de entorno activa todas las funciones de IronOCR(OCR, códigos de barras, procesamiento de PDF y más de 125 idiomas) sin necesidad de inicialización para cada función.
Problema 3: La agregación de texto de LineResult produce una salida ilegible.
Dynamsoft: RecognizeFile devuelve una DLRResult por región de etiqueta detectada. Las aplicaciones que concatenan lineResult.Text en todos los resultados con separadores \n producen salidas que mezclan líneas de diferentes zonas de etiqueta en la página — porque el orden de los objetos DLRResult es el orden de detección de región, no el orden de lectura.
Solución: La jerarquía de resultados de IronOCR organiza la salida en orden de lectura. Use la estructura Pages → Paragraphs → Lines para acceder al texto en el orden natural del documento:
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);
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);
Imports IronOcr
Dim result = New IronTesseract().Read(imagePath)
' Reading-order text — no manual aggregation
Console.WriteLine(result.Text)
' Or access paragraph-level groupings
For Each paragraph In result.Pages(0).Paragraphs
Console.WriteLine(paragraph.Text)
Next
Problema 4: Faltan archivos JSON de plantilla en el servidor de implementación.
Dynamsoft: Los archivos JSON de plantilla son artefactos de implementación independientes. Cuando falta un archivo de plantilla o tiene una ruta incorrecta en un nuevo servidor, AppendSettingsFromString falla — a veces de manera silenciosa, a veces con una excepción de tiempo de ejecución — y la implementación rompe el reconocimiento sin tocar el código de la aplicación.
Solución:IronOCR no tiene archivos de plantilla. Tras reemplazar el paquete NuGet y actualizar los espacios de nombres, la lista de artefactos de implementación se reduce a los binarios de la aplicación y una variable de entorno. Si es necesario, agregue una comprobación de validación de inicio:
// 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
// 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
Imports IronOcr
' Validate license at startup — no template files to check
If Not IronOcr.License.IsValidLicense Then
Throw New InvalidOperationException("IronOCR license key is invalid or missing.")
End If
Dim ocr As New IronTesseract()
' Ready to process — no file dependencies
Número 5: Gestión de la cadena de eliminación en múltiples productos
Dynamsoft: Cada instancia de producto de Dynamsoft (LabelRecognizer, BarcodeReader, DocumentNormalizer) implementa IDisposable. Las clases de servicio que agregan múltiples productos llevan implementaciones de Dispose de múltiples niveles, y la falta de una llamada Dispose en cualquier instancia de producto causa fugas de recursos nativos que se manifiestan como crecimiento de memoria bajo carga.
Solución: Tanto el IronTesseract como el OcrInput de IronOCR implementan IDisposable, pero el modelo de disposición es más simple — una clase, un patrón. Registre una instancia IronTesseract única en el contenedor DI como singleton, o use bloques using para instancias de corta duración:
// 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>();
// 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>();
Imports IronOcr
' Short-lived pattern
Using input As New OcrInput()
input.LoadImage(imagePath)
Dim result = (New IronTesseract()).Read(input)
End Using
' Long-lived singleton (register in Program.vb)
builder.Services.AddSingleton(Of IronTesseract)()
La guía de seguimiento del progreso abarca la gestión del ciclo de vida de los trabajos por lotes de larga duración, y la guía de OCR asíncrono muestra los patrones singleton en ASP.NET Core.
Problema 6: El modelo de caracteres no está disponible para el formato de etiqueta personalizado.
Dynamsoft: El campo CharacterModelName en una plantilla referencia un archivo de modelo que debe existir en el directorio de instalación del SDK de Dynamsoft. Los modelos de personajes personalizados requieren la descarga de archivos de modelo adicionales desde el portal de Dynamsoft y su colocación en la ruta SDK correcta. La ausencia de un modelo provoca un fallo en el reconocimiento y un error de ejecución críptico.
Solución:IronOCR no utiliza archivos de modelos de personajes. Para fuentes personalizadas o especializadas, utilice la formación de idiomas personalizada:
// 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);
// 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);
Imports IronTesseract
' No character model files needed
' For specialized fonts, use a custom language pack
Dim ocr As New IronTesseract()
ocr.Language = OcrLanguage.English ' or load a custom trained pack
Using input As New OcrInput()
input.LoadImage(specializedFontImage)
input.Binarize() ' helps with specialized font clarity
Dim result = ocr.Read(input)
End Using
La guía de capacitación sobre fuentes personalizadas abarca la capacitación en un paquete de idioma personalizado para fuentes de etiquetas propietarias sin necesidad de configurar la ruta del archivo.
Lista de verificación para la migración de OCR de Dynamsoft
Pre-Migración
Revisa el código fuente en busca de todas las referencias a 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
# 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
Resultados del inventario:
- Cuente los sitios de llamada
InitLicense(uno por producto de Dynamsoft en uso) - Cuente los sitios de llamada
AppendSettingsFromString(uno por plantilla de reconocimiento) - Enumerar todos los archivos de plantilla JSON que se eliminarán después de la migración.
- Identifique cualquier definición
ReferenceRegionArray(convertir aCropRectangle) - Tenga en cuenta qué funciones están cubiertas por productos separados (códigos de barras, normalización de documentos).
Migración de código
- Elimine el paquete NuGet
Dynamsoft.LabelRecognizer(y cualquier otro paquete de Dynamsoft) - Instale el paquete NuGet
IronOcr(dotnet add package IronOcr) - Reemplace todos los
using Dynamsoft.LabelRecognizer;yusing Dynamsoft.Core;conusing IronOcr; - Reemplace todas las llamadas
LabelRecognizer.InitLicense(key)con una solaIronOcr.License.LicenseKey = keyen el inicio de la aplicación - Elimine todas las llamadas
AppendSettingsFromString(json)— no se requiere equivalente - Reemplace las coordenadas JSON
ReferenceRegionArraycon constructoresnew CropRectangle(x, y, width, height) - Reemplace la instanciación
new LabelRecognizer()connew IronTesseract() - Reemplace
recognizer.RecognizeFile(path)conocr.Read(path) - Reemplace la iteración de resultados
DLRLineResultcon la jerarquía.Words - Reemplace la agregación manual de cadenas
lineResult.Textconresult.Texto enumeración de página estructurada - Reemplace
BarcodeReader.InitLicense+BarcodeReader.DecodeFileconocr.Configuration.ReadBarCodes = true - Elimine las cadenas
Disposede múltiples productos y reemplácelas conusing var ocr = new IronTesseract() - Eliminar los archivos de plantilla JSON de los artefactos del proyecto y de la implementación.
- Reemplace los bucles de iteración de cuadros sobre archivos TIFF con
input.LoadImageFrames(path) - Agregue
result.SaveAsSearchablePdf(outputPath)donde sea necesario archivar salidas escaneadas
Posmigración
- Verifique que
IronOcr.License.IsValidLicensedevuelvatrueal inicio de la aplicación - Confirme que todos los resultados de reconocimiento devuelvan
result.Textno vacíos para las entradas que funcionaban anteriormente - Verifique
result.Confidenceen muestras representativas — valores por encima del 80% indican buena calidad de reconocimiento - Pruebe la precisión de la orientación a regiones comparando las salidas
CropRectanglecon los resultados de región anteriores de Dynamsoft - Valide la lectura de códigos de barras ejecutando
ocr.Configuration.ReadBarCodes = trueen entradas que anteriormente requerían el lector de códigos de barras de Dynamsoft - Verifique que el procesamiento de archivos TIFF de múltiples páginas produzca un
OcrResult.Pagepor cuadro - Confirme que la salida PDF con capacidad de búsqueda permite realizar búsquedas de texto en un visor de PDF.
- Ejecute pruebas de procesamiento en paralelo con
Parallel.ForEachy verifique que no haya contención de hilos - Pruebe todos los destinos de implementación (Linux, Docker, Azure) para confirmar que la implementación de un solo paquete funciona sin archivos de plantilla JSON.
- Confirme que no queden variables de entorno de clave de licencia de Dynamsoft en la configuración de implementación.
Principales ventajas de migrar a IronOCR
Un paquete elimina el impuesto de coordinación de múltiples productos. Cada capacidad — OCR general, extracción de MRZ, lectura de códigos de barras, entrada de PDF nativo, salida de PDF buscable, preprocesamiento y más de 125 idiomas — se envía como un solo paquete NuGet IronOcr. Las actualizaciones de versión afectan una entrada de paquete en un archivo .csproj. La rotación de la clave de licencia es una variable de entorno. El inventario de artefactos de despliegue se reduce a binarios de la aplicación, sin archivos de plantilla JSON ni directorios de modelos de caracteres.
Sin dependencias de archivos de configuración. El sistema de plantillas Dynamsoft requiere que los archivos JSON estén presentes y correctamente ubicados en la ruta de ejecución.IronOCR no tiene dependencias de archivos en tiempo de ejecución más allá del propio paquete NuGet . Las imágenes de Docker se vuelven deterministas: lo que pasa la integración continua es exactamente lo que se ejecuta en producción. La guía de despliegue en Docker muestra un archivo Docker completo que requiere solo una línea apt-get install para Linux.
La salida estructurada reduce el código de integración. Dynamsoft devuelve cadenas de texto sin procesar LineResult. La extracción de datos estructurados (posiciones de campo, límites de palabras, nivel de confianza por token) requiere un procesamiento posterior que su código posee y prueba. La jerarquía de resultados de IronOCR expone páginas, párrafos, líneas, palabras y caracteres como colecciones escritas con coordenadas y puntuaciones de confianza en cada nivel. Los equipos que migran desde Dynamsoft suelen eliminar entre el 30 % y el 50 % de su código de procesamiento de resultados porque IronOCR les proporciona la estructura que estaban creando manualmente. La página de resultados del OCR documenta el modelo de salida completo.
Las licencias perpetuas eliminan la incertidumbre del presupuesto anual. Reconocedor de etiquetas Dynamsoft no ofrece la opción de licencia perpetua. Un clúster de procesamiento que funcione durante cinco años cuesta más de 2995 dólares al año solo para el reconocimiento de etiquetas, antes de añadir productos de normalización de códigos de barras o documentos. La licencia Lite de $999 de IronOCR es una compra única que cubre todas las características indefinidamente. Para implementaciones gubernamentales, Enterprise y de larga duración, eliminar la dependencia de la renovación anual de un componente central de procesamiento de documentos reduce la complejidad de las adquisiciones y elimina el riesgo de una interrupción de la suscripción a mitad del proyecto. La página de licencias de IronOCR enumera todos los niveles y lo que cubre cada uno.
Multiplataforma sin configuración específica de plataforma.IronOCR resuelve el binario de tiempo de ejecución correcto para Windows x64, Linux x64, macOS x64 y macOS ARM a través del gráfico de identificadores de tiempo de ejecución de NuGet. Sin bloques <PackageReference> condicionales, sin código de detección de plataforma, sin configuración de ruta de binarios nativos. El mismo código using IronOcr; compila y se ejecuta en Windows, Linux, AWS Lambda, y Azure App Service sin modificaciones.
La cobertura lingüística se adapta a las necesidades de la aplicación. Reconocedor de etiquetas Dynamsoft está diseñado para formatos MRZ con caracteres latinos. Los alfabetos no latinos —árabe, chino, japonés, coreano, hebreo— quedan fuera de su ámbito de diseño.IronOCR admite más de 125 idiomas instalados como paquetes NuGet individuales: dotnet add package IronOcr.Languages.Arabic añade soporte para árabe sin cambio de código en la tubería de reconocimiento. El índice de idiomas lista cada paquete de idioma disponible. Para las aplicaciones que procesan documentos de identidad internacionales, etiquetas de envío multilingües o facturas transfronterizas, esta amplitud significa que una sola biblioteca cubre todos los tipos de documentos con los que se encuentra una aplicación en constante evolución.
Preguntas Frecuentes
¿Por qué debería migrar de Dynamsoft OCR SDK a IronOCR?
Los impulsores comunes incluyen la eliminación de la complejidad de la interoperabilidad COM, la sustitución de la gestión de licencias basada en archivos, la evitación de la facturación por página, la habilitación de la implementación de Docker/contenedores y la adopción de un flujo de trabajo nativo de NuGet que se integre con las herramientas .NET estándar.
¿Cuáles son los principales cambios de código al migrar de Dynamsoft OCR SDK a IronOCR?
Sustituya las secuencias de inicialización de Dynamsoft OCR por la instanciación de IronTesseract, elimine la gestión del ciclo de vida COM (patrones explícitos Create/Load/Close) y actualice los nombres de las propiedades de los resultados. El resultado es un número significativamente menor de líneas repetitivas.
¿Cómo instalo IronOCR para comenzar la migración?
Ejecute 'Install-Package IronOcr' en la consola del gestor de paquetes o 'dotnet add package IronOcr' en la CLI. Los paquetes de idiomas son paquetes independientes: 'dotnet add package IronOcr.Languages.French' para el francés, por ejemplo.
¿IronOCR iguala la precisión de OCR de Dynamsoft OCR SDK para documentos comerciales estándar?
IronOCR consigue una gran precisión para contenido empresarial estándar, como facturas, contratos, recibos y formularios mecanografiados. Los filtros de preprocesamiento de imágenes (eliminación de distorsiones, eliminación de ruido, mejora del contraste) mejoran aún más el reconocimiento en entradas degradadas.
¿Cómo maneja IronOCR los datos de idioma que Dynamsoft OCR SDK instala por separado?
Los datos de idiomas en IronOCR se distribuyen como paquetes NuGet. dotnet add package IronOcr.Languages.German' instala la compatibilidad con el alemán. No es necesario colocar manualmente los archivos ni las rutas de los directorios.
¿La migración de Dynamsoft OCR SDK a IronOCR requiere cambios en la infraestructura de implementación?
IronOCR requiere menos cambios de infraestructura que Dynamsoft OCR SDK. No hay rutas binarias del SDK, ubicaciones de archivos de licencia ni configuraciones del servidor de licencias. El paquete NuGet contiene el motor OCR completo, y la clave de licencia es una cadena establecida en el código de la aplicación.
¿Cómo configuro las licencias de IronOCR después de la migración?
Asigne IronOcr.License.LicenseKey = "YOUR-KEY" en el código de inicio de la aplicación. En Docker o Kubernetes, almacene la clave como una variable de entorno y léala en el inicio. Utilice License.IsValidLicense para validar antes de aceptar tráfico.
¿Puede IronOCR procesar archivos PDF de la misma manera que lo hace Dynamsoft OCR?
Sí, IronOCR lee PDF nativos y escaneados. Instancie IronTesseract, llame a ocr.Read(input) donde input es una ruta PDF u OcrPdfInput, e itere las páginas OcrResult. No es necesario un proceso de renderizado de PDF independiente.
¿Cómo gestiona IronOCR los hilos en el procesamiento de grandes volúmenes?
IronTesseract puede instanciarse de forma segura por subproceso. Gire una instancia por hilo en un Parallel.ForEach o Task pool, ejecute OCR concurrentemente, y disponga de cada instancia cuando termine. No se requiere estado global o bloqueo.
¿Qué formatos de salida admite IronOCR tras la extracción de texto?
IronOCR devuelve resultados estructurados que incluyen texto, coordenadas de palabras, puntuaciones de confianza y estructura de páginas. Las opciones de exportación incluyen texto sin formato, PDF con opción de búsqueda y objetos de resultados estructurados para su procesamiento posterior.
¿Es el precio de IronOCR más predecible que el de Dynamsoft OCR SDK para escalar cargas de trabajo?
IronOCR utiliza licencias perpetuas de tarifa plana sin cargos por página o volumen. Tanto si procesa 10.000 como 10 millones de páginas, el coste de la licencia permanece constante. Las opciones de licencias por volumen y por equipo se encuentran en la página de precios de IronOCR.
¿Qué sucede con mis pruebas existentes después de migrar de Dynamsoft OCR SDK a IronOCR?
Las pruebas que validan el contenido de texto extraído deben seguir superándose tras la migración. Las pruebas que validan patrones de llamada a API o el ciclo de vida de objetos COM deberán actualizarse para reflejar el modelo de inicialización y resultados más sencillo de IronOCR.

