En el caso del reconocimiento a nivel de campo, se reconocen fragmentos breves de texto para capturar datos de determinados campos. La calidad del reconocimiento es crucial en este escenario.Este escenario también puede utilizarse como parte de escenarios más complejos en los que es necesario extraer datos significativos de documentos (por ejemplo, para capturar datos de documentos en papel en sistemas de información y bases de datos, o para clasificar e indexar automáticamente documentos en sistemas de gestión documental).En este escenario, el sistema reconoce varias líneas de texto solo en algunos campos, o bien el texto completo de una imagen pequeña. El sistema calcula un nivel de confianza para cada carácter reconocido. Estos niveles de confianza pueden utilizarse después al comprobar los resultados del reconocimiento. Además, el sistema puede almacenar varias variantes de reconocimiento de palabras y caracteres del texto, que luego pueden utilizarse en algoritmos de votación para mejorar la calidad del reconocimiento.El procesamiento de pequeños fragmentos de texto en este escenario difiere en algunos aspectos de los mismos pasos en otros escenarios:
Preprocesamiento de imágenes escaneadas o fotografías
Las imágenes que se van a reconocer pueden incluir marcas y ruido de fondo, ambos capaces de dificultar el reconocimiento. Por esta razón, en esta etapa se eliminan las marcas no deseadas y el ruido de fondo.
Reconocimiento de pequeños fragmentos de texto
Al reconocer pequeños fragmentos de texto, el tipo de datos que se va a reconocer se conoce de antemano. Por lo tanto, la calidad del reconocimiento puede mejorarse mediante el uso de diccionarios externos, expresiones regulares, idiomas de reconocimiento personalizados y alfabetos, así como imponiendo restricciones al número de caracteres de una cadena. Los campos de texto pueden contener texto impreso, escrito a mano en letra de imprenta y manuscrito.
Trabajo con los datos reconocidos
Este escenario requiere la máxima precisión de reconocimiento para reducir al mínimo el trabajo de verificación de datos. El sistema puede calcular un nivel de confianza para cada palabra o carácter reconocido y proporcionar varias variantes de reconocimiento, entre las que varios motores pueden elegir después la mejor opción aplicando algoritmos de votación.
Los ejemplos de código proporcionados en este tema son específicos de Windows.
A continuación se presenta una descripción detallada del método recomendado para usar ABBYY FineReader Engine 12 en este escenario. El método sugerido utiliza la configuración de procesamiento que se considera más adecuada para este escenario.
Paso 1. Cargar ABBYY FineReader Engine
Para comenzar a trabajar con ABBYY FineReader Engine, es necesario crear el objeto Engine. El objeto Engine es el objeto de nivel superior en la jerarquía de objetos de ABBYY FineReader Engine, y proporciona diversas configuraciones globales, algunos métodos de procesamiento y métodos para crear los demás objetos.Para crear el objeto Engine, puede usar la función InitializeEngine. Consulte también otras formas de cargar el objeto Engine (Win).
public class EngineLoader : IDisposable{ public EngineLoader() { // Inicialice estas variables con la ruta completa a FREngine.dll, su Customer Project ID, // y, si corresponde, la ruta al archivo de token de su licencia en línea y la contraseña de la licencia en línea string enginePath = ""; string customerProjectId = ""; string licensePath = ""; string licensePassword = ""; // Cargar la biblioteca FREngine.dll dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH); try { if (dllHandle == IntPtr.Zero) { throw new Exception("No se puede cargar " + enginePath); } IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine"); if (initializeEnginePtr == IntPtr.Zero) { throw new Exception("No se encuentra la función InitializeEngine"); } IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine"); if (deinitializeEnginePtr == IntPtr.Zero) { throw new Exception("No se encuentra la función DeinitializeEngine"); } IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow"); if (dllCanUnloadNowPtr == IntPtr.Zero) { throw new Exception("No se encuentra la función DllCanUnloadNow"); } // Convertir punteros en delegados initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer( initializeEnginePtr, typeof(InitializeEngine)); deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer( deinitializeEnginePtr, typeof(DeinitializeEngine)); dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer( dllCanUnloadNowPtr, typeof(DllCanUnloadNow)); // Llamar a la función InitializeEngine // pasando la ruta al archivo de licencia en línea y la contraseña de la licencia en línea int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, "", "", false, ref engine); Marshal.ThrowExceptionForHR(hresult); } catch (Exception) { // Liberar la biblioteca FREngine.dll engine = null; // Eliminar todos los objetos antes de llamar a FreeLibrary GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); FreeLibrary(dllHandle); dllHandle = IntPtr.Zero; initializeEngine = null; deinitializeEngine = null; dllCanUnloadNow = null; throw; } } // Funciones de Kernel32.dll [DllImport("kernel32.dll")] private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags); private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008; [DllImport("kernel32.dll")] private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); [DllImport("kernel32.dll")] private static extern bool FreeLibrary(IntPtr hModule); // Funciones de FREngine.dll [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)] private delegate int InitializeEngine(string customerProjectId, string licensePath, string licensePassword, string tempFolder, string dataFolder, bool isSharedCPUCoresMode, ref FREngine.IEngine engine); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int DeinitializeEngine(); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int DllCanUnloadNow(); // Variables privadas private FREngine.IEngine engine = null; // Handle de FREngine.dll private IntPtr dllHandle = IntPtr.Zero; private InitializeEngine initializeEngine = null; private DeinitializeEngine deinitializeEngine = null; private DllCanUnloadNow dllCanUnloadNow = null;}
// Inicialice estas variables con la ruta a FREngine.dll, el Customer Project ID de FineReader Engine,// y, si corresponde, la ruta al token de licencia en línea y la contraseña de licencia en líneawchar_t* FreDllPath;wchar_t* CustomerProjectId;wchar_t* LicensePath; // si no utiliza una licencia en línea, asigne cadenas vacías a estas variableswchar_t* LicensePassword;// HANDLE de FREngine.dllstatic HMODULE libraryHandle = 0;// Objeto global de FineReader EngineFREngine::IEnginePtr Engine;void LoadFREngine(){ if( Engine != 0 ) { // Ya cargado return; } // Primer paso: cargar FREngine.dll if( libraryHandle == 0 ) { libraryHandle = LoadLibraryEx( FreDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH ); if( libraryHandle == 0 ) { throw L"Error al cargar ABBYY FineReader Engine"; } } // Segundo paso: obtener el objeto Engine typedef HRESULT ( STDAPICALLTYPE* InitializeEngineFunc )( BSTR, BSTR, BSTR, BSTR, BSTR, VARIANT_BOOL, FREngine::IEngine** ); InitializeEngineFunc pInitializeEngine = ( InitializeEngineFunc )GetProcAddress( libraryHandle, "InitializeEngine" ); if( pInitializeEngine == 0 || pInitializeEngine( CustomerProjectId, LicensePath, LicensePassword, L"", L"", VARIANT_FALSE, &Engine ) != S_OK ) { UnloadFREngine(); throw L"Error al cargar ABBYY FineReader Engine"; }}
Paso 2. Carga de la configuración para el escenario
La configuración más adecuada puede seleccionarse mediante el método LoadPredefinedProfile del objeto Engine. Este método recibe el nombre del perfil como parámetro de entrada. La configuración más adecuada puede seleccionarse mediante el perfil predefinido denominado FieldLevelRecognition. Para obtener más información sobre los perfiles, consulte Trabajo con perfiles.
// Cargar un perfil predefinidoEngine->LoadPredefinedProfile( L"FieldLevelRecognition" );
Si desea cambiar la configuración utilizada para el procesamiento, use los objetos Parameter correspondientes. Consulte la sección Optimización adicional, más abajo, para obtener más información.
Paso 3. Carga y preprocesamiento de las imágenes
ABBYY FineReader Engine proporciona un objeto FRDocument para procesar documentos de varias páginas. Para cargar las imágenes de un documento y preprocesarlas, debe crear el objeto FRDocument y agregarle imágenes. Puede hacer una de las siguientes acciones:
Crear un objeto FRDocument mediante el método CreateFRDocumentFromImage del objeto Engine. Este método crea un objeto FRDocument y carga imágenes desde el archivo especificado.
// Crear el objeto FRDocument a partir de un archivo de imagenFREngine.IFRDocument frDocument = engine.CreateFRDocumentFromImage( "C:\\MyImage.tif", null );
// Abrir un archivo de imagen y crear el objeto FRDocumentFREngine::IFRDocumentPtr frDocument = Engine->CreateFRDocumentFromImage( L"C:\\MyImage.tif", 0 );
Paso 4. Configurar los campos que se van a reconocer
Ahora debe crear bloques que contengan sus campos y, para cada uno, especificar el tipo de bloque y las características conocidas de los datos que contiene.Realice el análisis de la estructura del documento mediante el método Analyze, o agregue manualmente bloques que contengan los campos que necesita reconocer. Consulte Trabajo con Layout y bloques para obtener instrucciones.Para cada campo, ahora puede especificar sus propios parámetros de reconocimiento. Por ejemplo, si un campo contiene texto, use la propiedad ITextBlock::RecognizerParams:
establezca el tipo de texto con ayuda de la propiedad TextTypes del objeto RecognizerParams. Por ejemplo, si el campo contiene dígitos escritos con el formato de un código postal, use el tipo de texto TT_Index.
establezca el idioma mediante el método SetPredefinedTextLanguage. El uso de idiomas predefinidos especiales (solo para Windows) puede resultar útil si conoce el tipo de información contenida en el campo. Por ejemplo, si el campo contiene una dirección de EE. UU., seleccione el idioma predefinido English_US_Address. Esto garantizará un reconocimiento más fiable del texto.
establezca las propiedades SaveCharacterRecognitionVariants y SaveWordRecognitionVariants del objeto RecognizerParams si necesita usar las variantes de reconocimiento para verificar posteriormente el resultado, como se describe más adelante en el paso 6. Tenga en cuenta que esta configuración no está disponible para textos manuscritos o escritos en letra de imprenta.
// Analizar la estructura del documentofrDocument.Analyze( null, null, null );// Supongamos que sabemos que el primer bloque// de la estructura contiene una dirección de EE. UU.FREngine.ITextBlock addressBlock = frDocument.Pages[0].Layout.Blocks[0].GetAsTextBlock();FREngine.IRecognizerParams paramsAddressBlock = addressBlock.RecognizerParams;paramsAddressBlock.SetPredefinedTextLanguage( "English_US_Address" );// Habilitar la recopilación de variantes de reconocimientoparamsAddressBlock.SaveCharacterRecognitionVariants = true;paramsAddressBlock.SaveWordRecognitionVariants = true;// Configurar las propiedades de los demás bloques de la estructura de la misma manera...
// Analizar la estructura del documentofrDocument->Analyze( 0, 0, 0 );// Supongamos que sabemos que el primer bloque// de la estructura contiene una dirección de EE. UU.FREngine::ILayoutBlocksPtr layoutBlocks = frDocument->Pages->Item( 0 )->Layout->Blocks;FREngine::IRecognizerParamsPtr paramsAddressBlock = layoutBlocks->Item( 0 )->GetAsTextBlock()->RecognizerParams;paramsAddressBlock->SetPredefinedTextLanguage( L"English_US_Address" );// Habilitar la recopilación de variantes de reconocimientoparamsAddressBlock->SaveCharacterRecognitionVariants = VARIANT_TRUE;paramsAddressBlock->SaveWordRecognitionVariants = VARIANT_TRUE;// Configurar las propiedades de los demás bloques de la estructura de la misma manera...
Paso 5. Reconocimiento
Como el diseño del documento ya se analizó y usted además lo modificó, no vuelva a llamar a los métodos de análisis. Use el método Recognize, que realiza el reconocimiento y la síntesis de páginas de todo el documento. En este escenario, debe extraer los datos de los campos y no exportar el documento reconocido; por lo tanto, no necesitará la síntesis del documento.
// Reconocer el documento// No es necesario especificar parámetros porque están configurados por el perfil de procesamientofrDocument.Recognize( null, null );
// Reconocer el documento// No es necesario especificar parámetros porque están configurados por el perfil de procesamientofrDocument->Recognize( 0, 0 );
Paso 6. Trabajar con los datos reconocidos
Use el objeto Text para acceder al fragmento de texto reconocido (puede obtener este objeto para un bloque de texto mediante la propiedad ITextBlock::Text). Use la propiedad Paragraphs para obtener la colección de párrafos del fragmento y el método IParagraphs::Item para acceder a cada párrafo. La propiedad IParagraph::Text permite acceder al texto reconocido de un párrafo.Puede usar IParagraph::Words para obtener la colección de palabras de un párrafo. Use el método IWords::Item para acceder a cada palabra de la colección. La propiedad IWord::Text devuelve la línea que contiene la palabra reconocida. Use el método GetRecognitionVariants del objeto Word o el método GetWordRecognitionVariants del objeto Paragraph para obtener las variantes de reconocimiento de una palabra.Puede acceder a los atributos de cada carácter mediante el método GetCharParams del objeto Paragraph. Este método proporciona acceso al objeto CharParams, que contiene los parámetros del carácter reconocido. Puede acceder a las variantes de reconocimiento de un carácter mediante la propiedad ICharParams::CharacterRecognitionVariants.Para obtener información detallada sobre cómo trabajar con texto, consulte Working with Text. Para obtener información sobre cómo usar Engine en algoritmos de votación, consulte Using Voting API.Cuando haya terminado de trabajar con el objeto FRDocument, libere todos los recursos utilizados por este objeto. Use el método IFRDocument::Close.
Paso 7. Descarga de ABBYY FineReader Engine
Después de terminar de trabajar con ABBYY FineReader Engine, debe descargar el objeto Engine. Para ello, use la función exportada DeinitializeEngine.
Puede usar el archivo FREngineDistribution.csv para crear automáticamente una lista de los archivos necesarios para que la aplicación funcione. Para el procesamiento en este escenario, seleccione en la columna 5 (RequiredByModule) los siguientes valores:CoreCore.ResourcesOpeningOpening, ProcessingProcessingProcessing.OCRProcessing.OCR, Processing.ICRProcessing.OCR.NaturalLanguagesProcessing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguagesSi modifica el escenario estándar, cambie los módulos necesarios según corresponda. También debe especificar los idiomas de la interfaz, los idiomas de reconocimiento y cualquier función adicional que use la aplicación (como, por ejemplo, Opening.PDF si necesita abrir archivos PDF, o Processing.OCR.CJK si necesita reconocer texto en idiomas CJK). Consulte Working with the FREngineDistribution.csv File para obtener más información.
Estas son las secciones del archivo de ayuda en las que puede encontrar información adicional sobre la configuración de los parámetros para las distintas etapas de procesamiento:
Reconocimiento
Trabajo con idiomas Uso de idiomas de reconocimiento integrados y personalizados.
Idiomas predefinidos especiales en ABBYY FineReader Engine - Windows Lista de idiomas de reconocimiento que contienen unidades lingüísticas especiales: direcciones, fecha y hora, nombres de personas, etc. Estos idiomas pueden utilizarse para el reconocimiento de campos.
Trabajo con los datos reconocidos
Trabajo con texto Trabajo con el texto reconocido, los párrafos, las palabras y los caracteres.