Saltar al contenido principal
Este escenario está disponible solo para Windows.
En este escenario, ABBYY FineReader Engine se utiliza en un “equipo de digitalización”, que escanea imágenes y las guarda como archivos. Este escenario puede utilizarse como parte de otros escenarios en la etapa preliminar del procesamiento de documentos, es decir, para obtener versiones electrónicas de los documentos para su posterior procesamiento. Algunos ejemplos de uso son la digitalización de documentos con fines de archivo, la obtención de versiones editables de documentos y la extracción de datos específicos de los documentos. Los documentos en papel se escanean y las imágenes se guardan en formato electrónico, lo que permite obtener versiones electrónicas de alta calidad de sus documentos impresos. Los documentos pueden pasar por las siguientes etapas de procesamiento:
  1. Digitalización
Los documentos pueden escanearse mediante una de las dos interfaces de digitalización disponibles que proporcionan los escáneres (TWAIN o WIA), utilizando la propia interfaz de digitalización de ABBYY o sin interfaz de digitalización.
  1. Preprocesamiento de las imágenes escaneadas
Una vez escaneadas, las imágenes pueden preprocesarse. El preprocesamiento incluye la eliminación de motas, la corrección de líneas de texto distorsionadas, la inversión de colores, la eliminación de márgenes negros y la corrección de la orientación o la resolución de la imagen. Las páginas enfrentadas pueden dividirse en dos imágenes independientes. Las imágenes procesadas pueden guardarse en varios formatos de imagen, como JPEG, TIFF o BMP.

Implementación del escenario

A continuación se ofrece una descripción detallada del método recomendado para utilizar ABBYY FineReader Engine 12 en este escenario. En la implementación propuesta, se omite la fase de preparación de imágenes. Consulte Optimización adicional más abajo para obtener consejos sobre la implementación de la preparación de imágenes.
Para empezar a trabajar con ABBYY FineReader Engine, debe crear el objeto Engine. El objeto Engine es el objeto principal en la jerarquía de objetos de ABBYY FineReader Engine y proporciona varias opciones de configuración global, 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).

C#

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 Online License y la contraseña de Online License
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // Cargue la biblioteca FREngine.dll
        dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
           
        try
        {
            if (dllHandle == IntPtr.Zero)
            {
                throw new Exception("Can't load " + enginePath);
            }
            IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
            if (initializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Can't find InitializeEngine function");
            }
            IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
            if (deinitializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Can't find DeinitializeEngine function");
            }
            IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
            if (dllCanUnloadNowPtr == IntPtr.Zero)
            {
                throw new Exception("Can't find DllCanUnloadNow function");
            }
            // Convierta los punteros en delegados
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // Llame a la función InitializeEngine 
            // pasando la ruta al archivo de Online License y la contraseña de Online License
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // Libere la biblioteca FREngine.dll
            engine = null;
            // Elimine 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;
    // Identificador de FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}
ABBYY FineReader Engine ofrece el objeto ScanManager para gestionar las fuentes de digitalización. La propiedad ScanSources de este objeto proporciona acceso a la lista de todos los escáneres disponibles, mientras que el método FindScanSources permite seleccionar los escáneres según el tipo de API que proporcionan y el tipo de interfaz de usuario que se desea utilizar para configurar las opciones de digitalización.Para escanear y guardar los archivos en disco, puede usar cualquiera de estos dos métodos del objeto ScanSource: el método Scan, que no devuelve el control hasta que el escaneo se completa, y el método BeginScan, que inicia la operación de escaneo asíncrono y devuelve el control de inmediato.Puede implementar la interfaz IScanCallback y utilizarla para recibir notificaciones sobre el progreso del escaneo.Los siguientes parámetros son accesibles a través de la API de ABBYY FineReader Engine 12: brillo, color, resolución, tipo de compresión de imagen, ángulo de rotación de imagen, tamaño del área de escaneo, modo de escaneo dúplex, modo de alimentador automático, una pausa entre páginas y otros más. Los parámetros de escaneo se configuran mediante la propiedad ScanSettings del objeto ScanSource. Esta propiedad es necesaria para acceder al objeto ScanSourceSettings, que, a su vez, proporciona acceso a la configuración de escaneo de una fuente.Para escanear las imágenes de forma síncrona:
  1. Cree un objeto ScanManager. Puede especificar si los registros de escaneo se escriben con el parámetro de entrada del método CreateScanManager.
  2. Seleccione el origen de escaneo mediante el método FindScanSources del objeto ScanManager, especificando la API y el tipo de interfaz de usuario que debe admitir el escáner.
  3. Si elige no mostrar ningún cuadro de diálogo para que el usuario configure por sí mismo las opciones de digitalización, ajuste dichas opciones mediante la propiedad ScanSettings del ScanSource seleccionado. Seleccione los valores adecuados de brillo, resolución y de los demás parámetros en las propiedades correspondientes del objeto ScanSourceSettings. Puede comprobar qué ajustes están disponibles para este escáner mediante la propiedad Capabilities del ScanSource.
  4. Especifique el nombre de la carpeta en la que se almacenarán las páginas escaneadas. El nombre de la carpeta debe ser una variable BSTR, por ejemplo, ScanFolder.
  5. Ejecute el método Scan del objeto ScanSource e indique como parámetros el tipo de cuadro de diálogo que se mostrará al usuario (pase la constante SSUIT_None para no mostrar ninguno) y la ruta de ScanFolder a la carpeta con los resultados.
  6. Este método devolverá los nombres de los archivos de imagen como un objeto StringsCollection. Puede obtener los nombres de los archivos de imagen de este objeto StringsCollection y, a continuación, procesar los archivos como archivos de imagen normales.
Para escanear las imágenes de forma asíncrona:
  1. Cree un objeto que implemente la interfaz IScanCallback. En el caso de la operación de escaneo asíncrono, las notificaciones de la interfaz de callback son muy útiles.
  2. Cree un objeto ScanManager. Puede especificar si los registros de digitalización deben escribirse en el parámetro de entrada del método CreateScanManager.
  3. Seleccione el origen de escaneo mediante el método FindScanSources del objeto ScanManager, especificando la API y el tipo de interfaz de usuario que debe admitir el escáner.
  4. Si decide no mostrar ningún cuadro de diálogo para que el usuario configure él mismo las opciones de digitalización, ajuste las opciones de digitalización mediante la propiedad ScanSettings del ScanSource seleccionado. Seleccione los valores adecuados de brillo, resolución y los demás parámetros en las propiedades correspondientes del objeto ScanSourceSettings. Puede comprobar qué ajustes están disponibles para este escáner mediante la propiedad Capabilities del ScanSource.
  5. Especifique el nombre de la carpeta en la que se almacenarán las páginas escaneadas. El nombre de la carpeta debe ser una variable de tipo BSTR, por ejemplo, ScanFolder.
  6. Ejecute el método BeginScan del objeto ScanSource e indique como parámetros el tipo de cuadro de diálogo que se mostrará al usuario (pase la constante SSUIT_None para no mostrar ninguno) y la ruta ScanFolder de la carpeta con los resultados. También debe pasar el puntero al objeto callback que creó.
  7. La ruta del archivo de imagen se devuelve con la notificación OnImageScanned de la interfaz IScanCallback, y la finalización de la operación se indica con la notificación OnScanComplete. Como usted proporciona la implementación de estos métodos, puede elegir qué hacer en cada una de estas situaciones. Por ejemplo, al recibir la ruta de un archivo de imagen, puede trabajar con él como con cualquier otro archivo del disco, cargándolo para procesarlo con FineReader Engine de la forma habitual.
Hasta que se complete el escaneo y se reciba la notificación OnScanComplete, no puede ejecutar BeginScan ni volver a ejecutar Scan, ni siquiera con otro escáner. La ventaja del escaneo asíncrono no es que pueda realizar varias operaciones de escaneo a la vez, sino que puede procesar las imágenes que ya recibió mientras se escanean las nuevas.
A continuación se muestra código de ejemplo para el escenario de escaneo asíncrono:

C#

// Implementar la interfaz IScanCallback
class ScanningCallback :FREngine.IScanCallback
{
  // constructor
  public ScanningCallback() {}
  ...
  // proporcionar la implementación de los métodos de IScanCallback
  public void OnError(string sourceName, string message) { // notificar o gestionar el error aquí }
  public void OnImageScanned(string sourceName, string Path, ref bool cancel) { // insertar aquí cualquier acción que deba realizarse al escanear una imagen }
  public void OnScanComplete() { // insertar aquí una acción que deba ejecutarse al completar el escaneo }
  // variables privadas
  ...
}
// Crear el administrador de escaneo con los registros desactivados
scanManager = engineLoader.Engine.CreateScanManager(false);
// Crear una lista de fuentes de escaneo filtradas por tipo de API y de interfaz de usuario
FREngine.IScanSources sources = scanManager.FindScanSources(UIType, APIType);
// A modo de ejemplo, seleccionar la primera fuente de escaneo de la colección
FREngine.IScanSource selectedSource = sources[0];
// Acceder a la configuración y las funcionalidades de la fuente de escaneo
FREngine.IScanSourceSettings settings = selectedSource.ScanSettings;
FREngine.IScanSourceCapabilities capabilities = selectedSource.Capabilities;
// Establecer las opciones de escaneo en modo dúplex si el escáner lo admite
settings.DuplexMode = capabilities.HasDuplexMode;
// Configurar el escaneo de varias páginas y un retraso de 10 segundos entre páginas
settings.MultipleImagesEnabled = true;
settings.PauseBetweenPagesMode = FREngine.ScanPauseModeEnum.SPM_PresetDelay;
settings.Delay = 10;
// Establecer la ruta a la carpeta con los resultados
string scanFolder = "D:\\SampleImages";
// Crear un objeto de callback
IScanningCallback callback = new ScanningCallback();
// Iniciar el escaneo
selectedSource.BeginScan(SSUIT_None, scanFolder, callback);
Después de terminar de trabajar con ABBYY FineReader Engine, debe liberar el objeto Engine. Para ello, use la función exportada DeinitializeEngine.

C#

public class EngineLoader : IDisposable
{
    // Liberar FineReader Engine
    public void Dispose()
    {
        if (engine == null)
        {
            // Engine no se cargó
            return;
        }
        engine = null;
        // Eliminar todos los objetos antes de llamar a FreeLibrary
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        int hresult = deinitializeEngine();
 
        hresult = dllCanUnloadNow();
        if (hresult == 0)
        {
            FreeLibrary(dllHandle);
        }
        dllHandle = IntPtr.Zero;
        initializeEngine = null;
        deinitializeEngine = null;
        dllCanUnloadNow = null;
        // generar una excepción después de la limpieza
        Marshal.ThrowExceptionForHR(hresult);
    }
    // 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, , , , 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;
    // Identificador de FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

Recursos necesarios

Puede usar el archivo FREngineDistribution.csv para crear automáticamente una lista de los archivos necesarios para que su aplicación funcione. Para el procesamiento con este escenario, seleccione en la columna 5 (RequiredByModule) los siguientes valores: Core Core.Resources Opening Opening, Processing Opening.Scanning Si 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 su aplicación (como, por ejemplo, Processing.OCR.CJK si necesita reconocer textos en idiomas CJK). Consulte Working with the FREngineDistribution.csv File para obtener más información.

Optimización adicional

Estas son las secciones del archivo de ayuda donde puede encontrar información adicional sobre cómo configurar los parámetros de las distintas etapas de procesamiento:
  • Separación de documentos
    • En este escenario, puede que necesite agrupar el flujo de imágenes entrantes en documentos. Por ejemplo, puede que conozca el número de páginas de cada documento, o que necesite asegurarse de que haya páginas separadoras con códigos de barras entre la última página del primer documento y la primera página del siguiente. Consulte el escenario de reconocimiento de códigos de barras.

Consulte también

Implementación de escenarios básicos de uso