Migración de RapidOCR.NET a IronOCR
Esta guía cubre el camino completo de migración de RapidOCR.NET (RapidOcrNet) a IronOCR para desarrolladores de .NET que necesitan eliminar la gestión de archivos de modelos ONNX de su flujo de trabajo OCR. Abarca la sustitución de paquetes, la traducción de código y los cambios operativos que siguen cuando se eliminan por completo las dependencias de modelos externos.
¿Por qué migrar desde RapidOCR.NET?
RapidOCR.NET funciona —para un conjunto limitado de casos de uso, en entornos controlados, donde alguien ya ha resuelto el problema de la distribución del modelo. Cuando cualquiera de esas condiciones cambia, las restricciones arquitectónicas de la biblioteca se convierten en costes de ingeniería.
Los archivos de modelos ONNX son un artefacto de implementación, no un paquete. RapidOCR.NET requiere cuatro archivos externos: det.onnx, cls.onnx, rec.onnx, y un diccionario de caracteres — antes de que un solo carácter pueda ser reconocido. Estos archivos no se incluyen en el paquete NuGet. Se encuentran en las páginas de lanzamiento de GitHub, requieren descarga manual, requieren una configuración explícita de la ruta en el código y requieren reglas MSBuild personalizadas para copiarlas durante la compilación. Cada nuevo desarrollador, cada canalización de CI, cada entorno de implementación repite esa ceremonia.
Cambiar de idioma implica sustituir el archivo, no la configuración. Para cambiar de OCR en inglés a OCR en chino en RapidOCR.NET es necesario descargar un modelo de reconocimiento diferente y un diccionario de caracteres diferente, y luego reconstruir la instancia del motor. El español, el francés, el alemán, el ruso, el árabe y más de 100 idiomas adicionales no tienen ningún modelo disponible en el catálogo de modelos de RapidOCR. Una aplicación que necesite procesar documentos en una combinación de idiomas no tiene una opción viable dentro de RapidOCR.NET para los idiomas no compatibles.
Las actualizaciones de versión requieren intervención manual. Cuando el proyecto RapidOCR publica pesos de modelo mejorados, los equipos deben descargar los nuevos archivos, sustituirlos en todos los entornos, validar las rutas y volver a implementarlos. No existe ningún paso de restauración del paquete que se encargue de esto automáticamente. En una configuración multientorno con desarrollo, staging y producción, esa propagación es una operación manual cada vez.
La dependencia del Runtime de ONNX agrega complejidad de plataforma. RapidOCR.NET depende de Microsoft.ML.OnnxRuntime, un paquete con binarios nativos específicos de plataforma. Las variantes de CPU y GPU requieren paquetes diferentes. Una imagen de contenedor construida para linux/amd64 requiere diferentes binarios que una construida para linux/arm64. Cada destino de implementación requiere una validación para comprobar que la variante de tiempo de ejecución correcta está presente y es compatible con los archivos de modelo instalados.
La latencia de arranque en frío y la huella de memoria son costes fijos. La carga de los tres modelos ONNX al inicio tarda entre 2 y 5 segundos y ocupa entre 300 y 500 MB de memoria durante todo el proceso. Ese coste se paga independientemente del volumen de OCR, lo que hace que la biblioteca no sea adecuada para funciones sin servidor, contenedores ligeros o servicios de bajo tráfico en los que la penalización de arranque es desproporcionada en relación con el rendimiento.
Sin soporte comercial. RapidOCR.NET es mantenido por un único desarrollador de la comunidad bajo la licencia Apache 2.0. Los incidentes de producción —conflictos de versiones de ONNX Runtime, fallos de inferencia en formatos de imagen poco habituales, aumento de la memoria bajo carga sostenida— se envían a una cola de incidencias de GitHub sin plazo de respuesta garantizado ni SLA.
El problema fundamental
Tres archivos de modelo ONNX Plus más un diccionario de caracteres, todos descargados por separado, todos configurados por ruta:
// RapidOcrNet: 4 external files required before any OCR can execute
var engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = "./models/det.onnx", // ~3 MB — downloaded from GitHub
ClsModelPath = "./models/cls.onnx", // ~1 MB — downloaded from GitHub
RecModelPath = "./models/rec_en.onnx", // ~2-10 MB — language-specific download
KeysPath = "./models/en_keys.txt" // character dictionary — language-specific
});
IronOCR no tiene archivos de modelo, ni configuración de ruta, ni paso de descarga:
// IronOCR: install the NuGet package, write one line
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read("document.jpg").Text;
##IronOCR frente a RapidOCR.NET: comparación de características
IronOCR y RapidOCR.NET se solapan en el OCR básico de imágenes. La brecha se abre ante cada preocupación circundante.
| Característica | RapidOCR.NET | IronOCR |
|---|---|---|
| Instalación de NuGet | Sí (RapidOcrNet) | Sí (IronOcr) |
| Se requieren archivos de modelos externos | Sí (4 archivos, descarga manual) | No |
| Se requiere configuración de ruta | Sí | No |
| Se requieren reglas de copia de MSBuild | Sí | No |
| Funciona inmediatamente después de la instalación de NuGet. | No | Sí |
| Dependencia de ONNX Runtime | Sí (~30–50 MB) | No |
| Idiomas compatibles | ~5 (solo CJK + inglés) | Más de 125 paquetes de idiomas NuGet |
| Cambio de idioma | Intercambio de archivos + reconstrucción del motor | Asignación de propiedades |
| Compatibilidad con idiomas europeos | No | Sí (30+) |
| Compatibilidad con árabe y hebreo | No | Sí |
| Compatibilidad con el alfabeto cirílico (ruso, ucraniano) | No | Sí |
| Entrada nativa de PDF | No | Sí |
| Entrada de PDF protegida con contraseña | No | Sí |
| Salida en PDF con capacidad de búsqueda | No | Sí |
| Entrada TIFF de varias páginas | No | Sí |
| Entrada de flujo y matriz de bytes | Limitado | Sí |
| Preprocesamiento de imágenes integrado | No | Sí (filtros automáticos + manuales) |
| Filtros de corrección de inclinación / eliminación de ruido / contraste | No | Sí |
| Salida estructurada (párrafos, líneas, palabras) | Parcial (solo bloques) | Sí, con coordenadas |
| Puntuaciones de confianza por palabra | Sí (por bloque) | Sí |
| Lectura de BarCodes durante el OCR | No | Sí |
| Exportación hOCR | No | Sí |
| Procesamiento paralelo seguro para subprocesos | Limitado | Sí (una instancia por hilo) |
| Implementación multiplataforma | Requiere binarios de ONNX Runtime para cada plataforma | Sí (Windows, Linux, macOS, Docker) |
| Despliegue de Docker | Se requieren instrucciones de COPIA del modelo del manual | Listo para usar |
| Sobrecarga de arranque en frío | 2–5 segundos (carga del modelo) | Mínimo |
| Apoyo comercial | No | Sí |
| Licencia | Apache 2.0 (gratuito) | Perpetual ($999 Lite, $1,499 Pro, $2,999 Enterprise) |
Inicio rápido: Migración de RapidOCR.NET a IronOCR
Paso 1: Sustituir el paquete NuGet
Eliminar RapidOCR.NET y la dependencia de ONNX Runtime:
dotnet remove package RapidOcrNet
dotnet remove package Microsoft.ML.OnnxRuntime
Instala IronOCR desde NuGet :
Paso 2: Actualizar los espacios de nombres
Sustituya el espacio de nombres RapidOCR.NET por el espacio de nombres IronOCR:
// Before (RapidOCR.NET)
using RapidOcrNet;
// After (IronOCR)
using IronOcr;
Paso 3: Inicializar licencia
Añadir la inicialización de la licencia al inicio de la aplicación, antes de cualquier llamada IronTesseract:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"Puede obtener una clave de prueba gratuita en la página de licencias de IronOCR .
Ejemplos de migración de código
Eliminación de la configuración de la ruta del modelo ONNX
El cambio más mecánico en esta migración es eliminar el bloque de configuración RapidOcrOptions y reemplazarlo con un constructor sin argumentos.
Enfoque de RapidOCR.NET:
using RapidOcrNet;
// Startup validation — written because a missing model crashes at runtime, not at install
private static void EnsureModelsPresent(string modelDir)
{
var required = new[]
{
Path.Combine(modelDir, "det.onnx"),
Path.Combine(modelDir, "cls.onnx"),
Path.Combine(modelDir, "rec_en.onnx"),
Path.Combine(modelDir, "en_keys.txt")
};
var missing = required.Where(f => !File.Exists(f)).ToList();
if (missing.Any())
throw new FileNotFoundException(
$"Missing model files: {string.Join(", ", missing)}\n" +
"Download from: https://github.com/RapidAI/RapidOCR/releases");
}
// Engine factory — called once at startup, held for lifetime of service
public RapidOcrEngine CreateEngine(string modelDir)
{
EnsureModelsPresent(modelDir);
return new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(modelDir, "det.onnx"),
ClsModelPath = Path.Combine(modelDir, "cls.onnx"),
RecModelPath = Path.Combine(modelDir, "rec_en.onnx"),
KeysPath = Path.Combine(modelDir, "en_keys.txt"),
UseGpu = false,
NumThreads = Environment.ProcessorCount
});
}
Enfoque IronOCR:
using IronOcr;
// No model validation, no path configuration, no GPU flags
// IronTesseract is thread-safe; create one per thread or on demand
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
Se puede eliminar todo el método de validación EnsureModelsPresent, el objeto de configuración RapidOcrOptions, y la clase de fábrica del motor. No hay archivos de modelo que validar, ya que IronOCR incluye su motor internamente como parte del paquete NuGet. La guía de configuración de IronTesseract describe en detalle las opciones de inicialización y la ubicación de la clave de licencia.
Consolidación del proceso de detección, clasificación y reconocimiento
RapidOCR.NET ejecuta un proceso ONNX de tres etapas —detección, clasificación de la orientación y, a continuación, reconocimiento— y devuelve una lista plana desordenada de bloques de texto que el usuario debe ordenar y ensamblar.IronOCR expone una sola llamada .Read() respaldada por su motor Tesseract 5 interno, devolviendo una salida estructurada con el orden de lectura ya aplicado.
Enfoque de RapidOCR.NET:
using RapidOcrNet;
public class InvoiceTextExtractor
{
private readonly RapidOcrEngine _engine;
public InvoiceTextExtractor(string modelDir)
{
// Three separate ONNX models run in sequence on every call
_engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(modelDir, "det.onnx"), // Stage 1: detect text regions
ClsModelPath = Path.Combine(modelDir, "cls.onnx"), // Stage 2: classify direction
RecModelPath = Path.Combine(modelDir, "rec_en.onnx"),// Stage 3: recognize characters
KeysPath = Path.Combine(modelDir, "en_keys.txt")
});
}
public string ExtractInvoiceText(string imagePath)
{
var result = _engine.Run(imagePath);
// Blocks are unordered — must sort by vertical position, then horizontal
var orderedBlocks = result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.ThenBy(b => b.BoundingBox.Left)
.ToList();
// Manual assembly — no paragraph or line structure
return string.Join(Environment.NewLine,
orderedBlocks.Select(b => b.Text));
}
}
Enfoque IronOCR:
using IronOcr;
public class InvoiceTextExtractor
{
private readonly IronTesseract _ocr = new IronTesseract();
public string ExtractInvoiceText(string imagePath)
{
// Single call — detection, recognition, reading order all internal
var result = _ocr.Read(imagePath);
return result.Text; // Already in reading order
}
public IEnumerable<string> ExtractInvoiceParagraphs(string imagePath)
{
var result = _ocr.Read(imagePath);
// Structured paragraphs with coordinates — no sorting or assembly needed
foreach (var page in result.Pages)
foreach (var paragraph in page.Paragraphs)
yield return paragraph.Text;
}
}
El proceso de tres etapas es totalmente interno a IronOCR. La lista result.TextBlocks con su cadena manual OrderBy se colapsa a result.Text. Para las llamadas que necesitaban datos de cuadros delimitadores de TextBlocks, las colecciones result.Pages[i].Paragraphs, .Lines, y .Words proporcionan coordenadas equivalentes a través de una API estructurada. La guía práctica de resultados de lectura y la página de características de resultados OCR documentan el modelo de salida estructurado completo.
Sustitución de la carga de modelos personalizados
Las aplicaciones que necesitan cambiar configuraciones OCR en tiempo de ejecución — por ejemplo, enrutar documentos a través de diferentes parámetros de reconocimiento basado en el tipo de documento — deben reconstruir todo el RapidOcrEngine en RapidOCR.NET porque la configuración está ligada al constructor.IronOCR expone la configuración del motor como propiedades que se pueden ajustar por lectura en una sola instancia.
Enfoque de RapidOCR.NET:
using RapidOcrNet;
public class DocumentRouter
{
private readonly string _modelDir;
public DocumentRouter(string modelDir) => _modelDir = modelDir;
// Must create separate engine instances per configuration
// Each engine holds ~300-500 MB of loaded model weights
private RapidOcrEngine BuildEnglishEngine() =>
new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(_modelDir, "det.onnx"),
ClsModelPath = Path.Combine(_modelDir, "cls.onnx"),
RecModelPath = Path.Combine(_modelDir, "en_rec.onnx"),
KeysPath = Path.Combine(_modelDir, "en_keys.txt")
});
private RapidOcrEngine BuildChineseEngine() =>
new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(_modelDir, "det.onnx"),
ClsModelPath = Path.Combine(_modelDir, "cls.onnx"),
RecModelPath = Path.Combine(_modelDir, "ch_rec.onnx"), // separate download
KeysPath = Path.Combine(_modelDir, "ch_keys.txt") // separate download
});
public string ProcessDocument(string imagePath, string language)
{
// Rebuild engine for each language — model reload cost on every switch
using var engine = language == "chinese"
? BuildChineseEngine()
: BuildEnglishEngine();
var result = engine.Run(imagePath);
return string.Join("\n", result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.Select(b => b.Text));
}
}
Enfoque IronOCR:
using IronOcr;
public class DocumentRouter
{
// One instance handles all languages — language is a property, not a constructor param
private readonly IronTesseract _ocr = new IronTesseract();
public string ProcessDocument(string imagePath, string language)
{
// Language switch requires no model reload, no rebuild
_ocr.Language = language switch
{
"chinese" => OcrLanguage.ChineseSimplified,
"japanese" => OcrLanguage.Japanese,
"arabic" => OcrLanguage.Arabic,
"russian" => OcrLanguage.Russian,
_ => OcrLanguage.English
};
return _ocr.Read(imagePath).Text;
}
}
Sin necesidad de reconstruir el motor, sin recargar el modelo, sin descargas separadas por idioma. Los paquetes de idioma para objetivos no ingleses se instalan a través de NuGet — dotnet add package IronOcr.Languages.ChineseSimplified — y el paso de restauración maneja el despliegue automáticamente. La guía práctica multilingüe cubre la instalación de paquetes de idiomas y el índice de idiomas enumera los más de 125 paquetes disponibles.
Migración del procesamiento por lotes
RapidOCR.NET no ofrece garantías de seguridad de hilo en una única instancia RapidOcrEngine. El procesamiento por lotes requiere una cola de un solo subproceso o la instanciación del motor por subproceso, cada una con una huella de modelo de entre 300 y 500 MB.IronOCR es explícitamente seguro para hilos: crea uno IronTesseract por hilo y ejecuta los de manera concurrente sin bloqueos.
Enfoque de RapidOCR.NET:
using RapidOcrNet;
public class BatchOcrProcessor
{
private readonly string _modelDir;
public BatchOcrProcessor(string modelDir) => _modelDir = modelDir;
// Thread-pool processing — each thread needs its own engine copy
// 4 threads × 300-500 MB model footprint = 1.2-2 GB RAM minimum
public Dictionary<string, string> ProcessBatch(IReadOnlyList<string> imagePaths)
{
var results = new System.Collections.Concurrent.ConcurrentDictionary<string, string>();
Parallel.ForEach(imagePaths, new ParallelOptions { MaxDegreeOfParallelism = 4 },
imagePath =>
{
// Each thread must create its own engine — not safe to share
using var engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(_modelDir, "det.onnx"),
ClsModelPath = Path.Combine(_modelDir, "cls.onnx"),
RecModelPath = Path.Combine(_modelDir, "rec_en.onnx"),
KeysPath = Path.Combine(_modelDir, "en_keys.txt")
});
var result = engine.Run(imagePath);
results[imagePath] = string.Join("\n",
result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.Select(b => b.Text));
});
return new Dictionary<string, string>(results);
}
}
Enfoque IronOCR:
using IronOcr;
public class BatchOcrProcessor
{
// Thread-safe: create IronTesseract per thread, no shared state required
public Dictionary<string, string> ProcessBatch(IReadOnlyList<string> imagePaths)
{
var results = new System.Collections.Concurrent.ConcurrentDictionary<string, string>();
Parallel.ForEach(imagePaths, imagePath =>
{
// Lightweight construction — no model loading overhead per thread
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
results[imagePath] = result.Text;
});
return new Dictionary<string, string>(results);
}
}
La instanciación RapidOcrEngine por hilo desaparece. Las instancias de subprocesos de IronOCR son ligeras: no se carga ningún modelo externo durante la construcción. El ejemplo de multithreading muestra patrones de procesamiento concurrente para pipelines de alto rendimiento.
Procesamiento de archivos TIFF multifotograma
RapidOCR.NET solo acepta archivos de imagen individuales. Procesar un TIFF de varias páginas — el formato estándar para documentos recibidos por fax y archivos escaneados — requiere dividirlo en marcos individuales con una biblioteca de imágenes separada, guardar esos marcos en archivos temporales, ejecutar engine.Run() en cada uno y limpiar después.IronOCR maneja TIFF de múltiples marcos de forma nativa a través de OcrInput.LoadImageFrames.
Enfoque de RapidOCR.NET:
using RapidOcrNet;
// Also requires: SixLabors.ImageSharp or System.Drawing for TIFF frame extraction
public class TiffOcrProcessor
{
private readonly RapidOcrEngine _engine;
public TiffOcrProcessor(string modelDir)
{
_engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(modelDir, "det.onnx"),
ClsModelPath = Path.Combine(modelDir, "cls.onnx"),
RecModelPath = Path.Combine(modelDir, "rec_en.onnx"),
KeysPath = Path.Combine(modelDir, "en_keys.txt")
});
}
public string ProcessMultiPageTiff(string tiffPath)
{
var pageTexts = new List<string>();
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
try
{
// External library required to split TIFF frames
var framePaths = SplitTiffIntoFrames(tiffPath, tempDir); // not in RapidOcrNet
foreach (var framePath in framePaths)
{
var result = _engine.Run(framePath);
pageTexts.Add(string.Join("\n",
result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.Select(b => b.Text)));
}
}
finally
{
// Clean up temp frame files
Directory.Delete(tempDir, recursive: true);
}
return string.Join("\n\n", pageTexts);
}
private IEnumerable<string> SplitTiffIntoFrames(string tiffPath, string outputDir)
{
// Requires external library — implementation depends on what is installed
throw new NotImplementedException("Add SixLabors.ImageSharp or similar");
}
}
Enfoque IronOCR:
using IronOcr;
public class TiffOcrProcessor
{
private readonly IronTesseract _ocr = new IronTesseract();
public string ProcessMultiPageTiff(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // All frames loaded — no external library needed
var result = _ocr.Read(input);
return result.Text; // Pages assembled in order automatically
}
public IEnumerable<(int PageNumber, string Text, double Confidence)> ProcessTiffWithPageData(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
var result = _ocr.Read(input);
foreach (var page in result.Pages)
yield return (page.PageNumber, page.Text, page.Confidence);
}
}
Sin bibliotecas de imágenes externas, sin archivos temporales, sin lógica de limpieza. LoadImageFrames lee todos los marcos TIFF en el pipeline OcrInput en una sola llamada. La guía de uso de archivos TIFF y GIF abarca la selección de fotogramas, el filtrado de rangos de páginas y el manejo eficiente de la memoria de documentos grandes con múltiples fotogramas.
Extracción de datos estructurados de formularios escaneados
RapidOCR.NET devuelve bloques de texto con cuadros delimitadores, pero sin una estructura de documento de nivel superior: no distingue entre párrafos, líneas o palabras. Extraer campos individuales de un formulario escaneado requiere escribir una lógica de intersección de coordenadas sobre la lista de bloques sin procesar.IronOCR proporciona un árbol de resultados estructurado hasta el nivel de caracteres, con coordenadas en cada nivel.
Enfoque de RapidOCR.NET:
using RapidOcrNet;
public class FormFieldExtractor
{
private readonly RapidOcrEngine _engine;
public FormFieldExtractor(string modelDir)
{
_engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(modelDir, "det.onnx"),
ClsModelPath = Path.Combine(modelDir, "cls.onnx"),
RecModelPath = Path.Combine(modelDir, "rec_en.onnx"),
KeysPath = Path.Combine(modelDir, "en_keys.txt")
});
}
// Extract text within a defined region by filtering block coordinates manually
public string ExtractFieldByRegion(string imagePath, float regionLeft, float regionTop,
float regionRight, float regionBottom)
{
var result = _engine.Run(imagePath);
// Filter blocks whose bounding box intersects the target region
var blocksInRegion = result.TextBlocks
.Where(b =>
b.BoundingBox.Left < regionRight &&
b.BoundingBox.Right > regionLeft &&
b.BoundingBox.Top < regionBottom &&
b.BoundingBox.Bottom > regionTop)
.OrderBy(b => b.BoundingBox.Top)
.ThenBy(b => b.BoundingBox.Left);
return string.Join(" ", blocksInRegion.Select(b => b.Text));
}
}
Enfoque IronOCR:
using IronOcr;
public class FormFieldExtractor
{
private readonly IronTesseract _ocr = new IronTesseract();
// Use CropRectangle to OCR only the target region — no post-filter needed
public string ExtractFieldByRegion(string imagePath, int x, int y, int width, int height)
{
var region = new CropRectangle(x, y, width, height);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
return _ocr.Read(input).Text;
}
// Extract all fields with their coordinates from a full-page scan
public IEnumerable<(string Text, int X, int Y, double Confidence)> ExtractAllWords(string imagePath)
{
var result = _ocr.Read(imagePath);
foreach (var page in result.Pages)
foreach (var word in page.Words)
yield return (word.Text, word.X, word.Y, word.Confidence);
}
}
CropRectangle confina el OCR a la región exacta de interés, lo cual es más rápido y preciso que ejecutar OCR de página completa y filtrar los resultados posteriormente. Las coordenadas y valores de confianza por palabra están disponibles directamente en result.Pages[i].Words sin ninguna intersección manual de cuadro delimitador. El tutorial sobre OCR basado en regiones y el ejemplo del rectángulo de recorte tratan este patrón en detalle.
Referencia de mapeo de la API de RapidOCR.NET a IronOCR
| RapidOCR.NET | Equivalente a IronOCR |
|---|---|
using RapidOcrNet | using IronOcr |
new RapidOcrEngine(new RapidOcrOptions { ... }) | new IronTesseract() |
RapidOcrOptions.DetModelPath | No es necesario — incluido internamente |
RapidOcrOptions.ClsModelPath | No es necesario — incluido internamente |
RapidOcrOptions.RecModelPath | No es necesario — incluido internamente |
RapidOcrOptions.KeysPath | No es necesario — incluido internamente |
RapidOcrOptions.UseGpu | No aplicable — Optimizado internamente para la CPU |
RapidOcrOptions.NumThreads | Utilice Parallel.ForEach con uno IronTesseract por hilo |
engine.Run(imagePath) | ocr.Read(imagePath) |
engine.Dispose() | using var ocr = new IronTesseract() |
result.TextBlocks | result.Pages[i].Words / .Lines / .Paragraphs |
result.TextBlocks[i].Text | result.Words[i].Text |
result.TextBlocks[i].Confidence | result.Words[i].Confidence |
result.TextBlocks[i].BoundingBox.Top | result.Words[i].Y |
result.TextBlocks[i].BoundingBox.Left | result.Words[i].X |
Ordenación manual OrderBy(b => b.BoundingBox.Top) | No necesario — result.Text está en orden de lectura |
string.Join("\n", result.TextBlocks.Select(b => b.Text)) | result.Text |
| Cambio de archivo de idioma (descargar otro modelo) | ocr.Language = OcrLanguage.French |
| Reconstrucción del motor para el cambio de idioma | No necesario — establecer ocr.Language por llamada |
Conversión de PDF a imagen + bucle engine.Run() | ocr.Read("document.pdf") |
| División manual de fotogramas en TIFF multifotograma | input.LoadImageFrames("document.tiff") |
| Sin capacidad de búsqueda en PDF | result.SaveAsSearchablePdf("output.pdf") |
| Sin capacidad para BarCodes | ocr.Configuration.ReadBarCodes = true |
Problemas comunes de migración y soluciones
Problema 1: El directorio Models sigue existiendo tras la migración
RapidOCR.NET: El directorio models/ en el proyecto contiene det.onnx, cls.onnx, rec_en.onnx, y en_keys.txt, junto con entradas de <Content> de MSBuild que los copian al compilar. Tras cambiar a IronOCR, este directorio y esas entradas permanecen y siguen aumentando el tamaño del resultado de la compilación.
Solución: Elimine el directorio models/, quite el correspondiente <ItemGroup> de .csproj, y elimine cualquier lógica de validación de inicio que verificara archivos faltantes. También elimine la referencia NuGet Microsoft.ML.OnnxRuntime si se instaló por separado. El resultado publicado de una aplicación .NET que utiliza IronOCR no contiene archivos de modelos externos.
<!-- Remove this entire block from .csproj -->
<ItemGroup>
<Content Include="models\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
Tema 2: Patrón de construcción del motor por subproceso
RapidOCR.NET: El código de procesamiento paralelo que creaba un nuevo RapidOcrEngine por hilo para evitar problemas de estado compartido tenía un costo de memoria significativo: cada instancia del motor cargaba 300–500 MB de pesos de modelo ONNX de forma independiente.
Solución: Las instancias IronTesseract de IronOCR son seguras para hilos y livianas. Crear uno por hilo en una Parallel.ForEach sin preocuparse por un costo de carga de modelo por instancia. El enfoque de IronOCR es idéntico al ejemplo de Migración de Procesamiento por Lotes mencionado anteriormente — IronTesseract maneja este escenario con el mismo patrón de construcción por hilo, pero sin el costo de carga de modelo de 300–500 MB que cada instancia RapidOcrEngine llevaba. El ejemplo de multithreading muestra el patrón estándar para los flujos de trabajo de alto rendimiento.
Problema 3: Excepción de idioma no compatible
RapidOCR.NET: El código que procesaba documentos no CJK a través de RapidOCR.NET —o intentaba crear un motor con un modelo de español/francés/alemán inexistente— generaba un error de "archivo no encontrado" en tiempo de ejecución o producía resultados vacíos.
Solución: Instale el paquete NuGet de paquete de idioma adecuado y configúrelo ocr.Language al valor de enumeración de destino OcrLanguage. Sin descarga de modelos, sin reconstrucción del motor, sin rutas de código adicionales para cada idioma:
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.Spanish;
var result = ocr.Read("spanish-document.jpg");
La guía de paquetes de idiomas personalizados abarca la configuración avanzada de idiomas más allá de los más de 125 paquetes estándar.
Problema 4: La lógica de ordenación de bloques de texto falla tras la migración
RapidOCR.NET: Debido a que result.TextBlocks era una lista plana desordenada, las bases de código típicamente contenían cadenas de .OrderBy(b => b.BoundingBox.Top).ThenBy(b => b.BoundingBox.Left) dispersas a lo largo del código de procesamiento de resultados.
Solución: Eliminar por completo esta lógica de ordenación. result.Text en IronOCR ya está ensamblado en orden de lectura natural. Para el código que también consumía coordenadas de cuadros delimitadores de los bloques ordenados, reemplace la referencia al bloque con result.Pages[i].Words[j]:
// Before: manual sort + coordinate extraction
var sorted = result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.ThenBy(b => b.BoundingBox.Left);
foreach (var block in sorted)
Console.WriteLine($"{block.Text} at ({block.BoundingBox.Left}, {block.BoundingBox.Top})");
// After: structured access, already in order
foreach (var page in result.Pages)
foreach (var word in page.Words)
Console.WriteLine($"{word.Text} at ({word.X}, {word.Y})");
Problema 5: El canal de CI/CD falla tras eliminar los archivos de modelo
RapidOCR.NET: Las canalizaciones de construcción que almacenaban en caché o buscaban el directorio models/ como un paso separado — ya sea desde una tienda de artefactos, un bucket compartido de S3 o un repositorio Git LFS — fallarán cuando esos pasos no encuentren nada para restaurar después de la migración.
Solución: Eliminar por completo los pasos de obtención y almacenamiento en caché del archivo de modelo del proceso de integración continua (CI). El motor de IronOCR se restaura como parte del paso estándar dotnet restore. No se requieren etapas adicionales de canalización. Para implementaciones contenedorizadas, elimine cualquier instrucción Docker COPY models/ ./models/ — la guía de implementación Docker de IronOCR documenta el único paquete de sistema requerido (libgdiplus en imágenes de Debian/Ubuntu) y nada más.
Problema 6: Conflictos de versiones de ONNX Runtime tras una migración parcial
RapidOCR.NET: Las aplicaciones que también usan otros paquetes ML basados en ONNX (ML.NET, detección de objetos ONNX, etc.) pueden haber tenido Microsoft.ML.OnnxRuntime fijado a una versión específica para compatibilidad con RapidOCR.NET. La eliminación de RapidOCR.NET puede provocar conflictos de versiones en esos otros paquetes.
Solución: Elimine Microsoft.ML.OnnxRuntime de la lista de paquetes explícitos.IronOCR no tiene dependencia del Runtime de ONNX, por lo que eliminar la referencia a RapidOCR.NET elimina por completo la fijación de versión. Otros paquetes de ML que realmente requieran ONNX Runtime podrán entonces resolver su propia versión compatible a través de la resolución de dependencias estándar de NuGet sin la restricción de RapidOCR.NET.
Lista de verificación para la migración a RapidOCR.NET
Tareas previas a la migración
Revisa el código fuente para detectar todos los usos de RapidOCR.NET antes de realizar cambios:
# Find all files that reference RapidOcrNet
grep -r "RapidOcrNet\|RapidOcrEngine\|RapidOcrOptions" --include="*.cs" .
# Find model path configuration
grep -r "DetModelPath\|ClsModelPath\|RecModelPath\|KeysPath" --include="*.cs" .
# Find MSBuild model copy entries
grep -r "det\.onnx\|cls\.onnx\|rec.*\.onnx\|keys\.txt" --include="*.csproj" .
# Find model validation logic
grep -r "ValidateModel\|models/" --include="*.cs" .
# Find ONNX Runtime references
grep -r "OnnxRuntime\|Microsoft\.ML" --include="*.csproj" .
# Find language-switching patterns (multiple engine instances per language)
grep -r "CreateEnglishEngine\|CreateChineseEngine\|rec_en\|ch_rec\|en_keys\|ch_keys" --include="*.cs" .
Inventar los resultados: anote cada lugar donde se cree un motor, cada lugar donde se configuren rutas de modelos, cada lugar donde se ordenen bloques de texto, y cada lugar donde la conversión de PDF a imagen alimenta a engine.Run().
Tareas de actualización de código
- Elimine la referencia del paquete NuGet
RapidOcrNetde todos los archivos.csproj. - Elimine la referencia del paquete NuGet
Microsoft.ML.OnnxRuntimede todos los archivos.csproj. - Instale el paquete NuGet
IronOcr. - Instala los paquetes NuGet de paquetes de idioma para cualquier idioma distinto del inglés que requiera la aplicación.
- Elimine el directorio
models/del proyecto y repositorio. - Elimine las entradas de MSBuild
<Content Include="models\**\*.*">de todos los archivos.csproj. - Elimine los métodos de validación de modelos de inicio (los métodos de estilo
EnsureModelsPresent). - Reemplace
using RapidOcrNetconusing IronOcren todos los archivos fuente. - Reemplazar new RapidOcrEngine(new RapidOcrOptions
{ ... })withnew IronTesseract`. - Reemplace
engine.Run(imagePath)conocr.Read(imagePath). - Reemplace las cadenas de ensamblaje
result.TextBlocks(.OrderBy().Select(b => b.Text)) conresult.Text. - Reemplace la extracción de campo de filtro de coordenadas con la entrada de región
CropRectangle. - Reemplace la construcción de motor por hilo con la construcción por hilo
IronTesseract. - Reemplace los métodos de fábrica del motor específicos del idioma con las asignaciones
ocr.Language = OcrLanguage.X. - Elimine el código de conversión de PDF a imagen y reemplace con llamadas directas
ocr.Read("file.pdf"). - Elimine el código de división de marcos de TIFF de múltiples marcos y reemplace con
input.LoadImageFrames("file.tiff"). - Añadir
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"al inicio de la aplicación. - Eliminar los pasos de obtención y almacenamiento en caché de archivos de modelo de las definiciones del canal de CI/CD.
- Elimine las instrucciones de
COPYdel modelo ONNX de los Dockerfiles.
Pruebas posteriores a la migración
- Verificar que todas las rutas de OCR de imágenes existentes devuelvan texto con una precisión igual o superior a la de RapidOCR.NET.
- Confirme que el orden de lectura
result.Textcoincide con la secuencia de campo esperada para cada tipo de documento. - Pruebe las lecturas con cambio de idioma para cada valor
OcrLanguageque la aplicación utiliza. - Ejecute el procesador de lotes paralelo y confirme que no haya errores de contención de subprocesos ni problemas de resultados obsoletos.
- Verificar que el procesamiento de TIFF de múltiples fotogramas devuelva el número correcto de páginas con el texto correcto por página.
- Pruebe la extracción de campo a través de
CropRectanglecontra las regiones de coordenadas esperadas. - Confirme que el directorio
models/está ausente de la salida de compilación y los paquetes de implementación. - Ejecuta el proceso de CI de principio a fin y confirma que no quedan pasos de obtención de modelos.
- Construya y ejecute un contenedor Docker y confirme que no hay errores de capa o archivo no encontrado
COPY models/al inicio. - Realice una prueba de medición del tiempo de arranque para verificar que la latencia de arranque en frío ha disminuido.
Principales ventajas de migrar a IronOCR
El despliegue ahora es determinista. dotnet restore y dotnet publish producen un despliegue OCR completo y funcional sin dependencias de archivos externos. La misma restauración de NuGet que instala la versión del paquete instala todo lo que el motor necesita para funcionar. No hay archivos de modelo que versionar por separado, ni pasos de caché de CI que configurar, ni scripts de validación de implementación que mantener. El proceso es tan sencillo como cualquier otra dependencia de paquetes .NET.
La cobertura de idiomas se escala con los requisitos empresariales. Añadir soporte para un nuevo idioma de documento significa ejecutar dotnet add package IronOcr.Languages.X y configurar ocr.Language. No hay comprobación de disponibilidad del modelo upstream, ni descarga del modelo, ni refactorización del motor. Los equipos que comienzan con OCR en inglés y posteriormente necesitan procesar contratos en alemán, facturas en árabe u órdenes de compra en ruso amplían su cobertura sin alterar la arquitectura de la aplicación. Los más de 125 paquetes de idiomas siguen el mismo patrón de instalación.
La salida estructurada elimina el código de ensamblaje de coordenadas. La jerarquía result.Pages, .Paragraphs, .Lines, .Words, y .Characters reemplaza la lista plana TextBlocks y la lógica de clasificación que trabajaba en torno a su falta de estructura. Se ha eliminado el código que extraía el texto en orden de lectura ordenando las coordenadas de los bloques. El código que necesitaba cuadros delimitadores por palabra los obtiene de word.X, word.Y, word.Width, word.Height sin filtrado de intersección. La página de características de los resultados del OCR documenta el modelo de salida completo.
El procesamiento de PDF y TIFF no requiere bibliotecas externas. Los dos formatos de documento más comunes, además de los JPG de una sola imagen —los PDF de varias páginas y los TIFF de varios fotogramas— son gestionados de forma nativa por IronOCR. Cada biblioteca externa que se añadió al árbol de dependencias para soportar engine.Run() con entrada PDF o TIFF puede ser removida. Resultado neto: menos paquetes que actualizar, menos problemas de compatibilidad entre versiones y archivos de proyecto más sencillos. Las guías de uso de entrada en PDF y TIFF cubren ambos formatos en detalle.
Los incidentes de producción cuentan con una vía de asistencia. Las licencias comerciales incluyen soporte por correo electrónico directo con un punto de contacto para problemas que no pueden esperar a una respuesta a través de GitHub. Los equipos con obligaciones de SLA o procesos de procesamiento de documentos críticos para el negocio pueden escalar los incidentes a los ingenieros que mantienen la biblioteca en lugar de esperar una respuesta de la comunidad. El centro de documentación de IronOCR proporciona documentación de referencia junto con esa ruta de soporte.
La Licencia Perpetua $999 es un costo único. No hay precios por página, facturación por transacción, ni renovación anual que reabra la conversación de costos. Los equipos de desarrollo que han calculado el coste de las horas de ingeniería dedicadas a la gestión de modelos, las soluciones alternativas para la conversión de PDF, el mantenimiento de la cadena de integración continua y las escalaciones por idiomas no compatibles, consideran sistemáticamente que la comparación es favorable frente al coste de la licencia.
