Pular para o conteúdo principal
Este cenário está disponível apenas para Windows.
Neste cenário, o ABBYY FineReader Engine é usado em um “computador de digitalização”, que digitaliza imagens e as salva como arquivos. Este cenário pode ser usado como parte de outros cenários na etapa preliminar do processamento de documentos, ou seja, para obter versões eletrônicas de documentos para processamento subsequente. Exemplos de uso incluem digitalizar documentos para fins de arquivamento, obter versões editáveis de documentos e extrair dados específicos de documentos. Documentos em papel são digitalizados, e as imagens são salvas em formato eletrônico, resultando em versões eletrônicas de alta qualidade dos documentos impressos. Os documentos podem passar pelas seguintes etapas de processamento:
  1. Digitalização
Os documentos podem ser digitalizados por meio de uma das duas interfaces de digitalização disponibilizadas pelos scanners (TWAIN ou WIA), usando a interface de digitalização da própria ABBYY ou sem interface de digitalização.
  1. Pré-processamento de imagens digitalizadas
Depois de digitalizadas, as imagens podem ser pré-processadas. O pré-processamento inclui remoção de ruído, correção de linhas de texto distorcidas, inversão de cores, remoção de margens pretas e correção da orientação ou da resolução da imagem. Páginas duplas podem ser divididas em duas imagens separadas. As imagens processadas podem ser salvas em vários formatos de imagem, como JPEG, TIFF e BMP.

Implementação do cenário

A seguir, apresentamos uma descrição detalhada do método recomendado para usar o ABBYY FineReader Engine 12 neste cenário. Na implementação proposta para este cenário, a etapa de preparação da imagem é omitida. Consulte Otimização adicional abaixo para obter dicas sobre como implementar a preparação da imagem.
Para começar a usar o ABBYY FineReader Engine, você precisa criar o objeto Engine. O objeto Engine é o objeto de nível superior na hierarquia de objetos do ABBYY FineReader Engine e fornece várias configurações globais, alguns métodos de processamento e métodos para criar os outros objetos.Para criar o objeto Engine, você pode usar a função InitializeEngine. Veja também outras formas de carregar o objeto Engine (Win).

C#

public class EngineLoader : IDisposable
{
    public EngineLoader()
    {
        // Inicialize estas variáveis com o caminho completo para FREngine.dll, seu ID do projeto do cliente,
        // e, se aplicável, o caminho para o arquivo de token da Licença Online e a senha da Licença Online
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // Carrega a 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");
            }
            // Converte ponteiros em delegates
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // Chama a função InitializeEngine 
            // passando o caminho para o arquivo da Licença Online e a senha da Licença Online
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // Libera a biblioteca FREngine.dll
            engine = null;
            // Exclua todos os objetos antes da chamada a FreeLibrary
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            FreeLibrary(dllHandle);
            dllHandle = IntPtr.Zero;
            initializeEngine = null;
            deinitializeEngine = null;
            dllCanUnloadNow = null;
            throw;
        }
    }
    // Funções 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);
    // Funções 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();
    // variáveis privadas
    private FREngine.IEngine engine = null;
    // Handle da FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}
O ABBYY FineReader Engine oferece o objeto ScanManager para gerenciar as fontes de digitalização. A propriedade ScanSources desse objeto fornece acesso à lista de todos os scanners disponíveis, enquanto o método FindScanSources permite selecionar os scanners pelo tipo de API que eles fornecem e pelo tipo de interface do usuário que você deseja usar para definir as opções de digitalização.Para digitalizar e salvar os arquivos em disco, você pode usar um destes dois métodos do objeto ScanSource: o método Scan, que não retorna até que a digitalização seja concluída, e o método BeginScan, que inicia a operação de digitalização assíncrona e retorna imediatamente.Você pode implementar a interface IScanCallback e usá-la para receber notificações sobre o progresso da digitalização.Os seguintes parâmetros são acessíveis por meio da API do ABBYY FineReader Engine 12: brilho, cor, resolução, tipo de compressão de imagem, ângulo de rotação da imagem, tamanho da área de digitalização, modo de digitalização duplex, modo de alimentador automático, pausa entre páginas e outros. Os parâmetros de digitalização são definidos por meio da propriedade ScanSettings do objeto ScanSource. Essa propriedade é necessária para acessar o objeto ScanSourceSettings, que, por sua vez, fornece acesso às configurações de digitalização de uma fonte.Para digitalizar as imagens de forma síncrona:
  1. Crie um objeto ScanManager. Você pode especificar se os logs de digitalização devem ser gravados por meio do parâmetro de entrada do método CreateScanManager.
  2. Selecione a origem de digitalização com o método FindScanSources do objeto ScanManager, especificando a API e o tipo de interface do usuário que devem ser suportados pelo scanner.
  3. Se você optar por não exibir nenhuma caixa de diálogo para que o usuário defina as opções de digitalização, ajuste essas opções usando a propriedade ScanSettings da ScanSource selecionada. Selecione os valores apropriados de brilho, resolução e outros parâmetros nas propriedades correspondentes do objeto ScanSourceSettings. Você pode verificar quais configurações estão disponíveis para esse scanner usando a propriedade Capabilities da ScanSource.
  4. Especifique o nome da pasta em que as páginas digitalizadas serão armazenadas. O nome da pasta deve ser uma variável do tipo BSTR, por exemplo, ScanFolder.
  5. Execute o método Scan do objeto ScanSource, informando como parâmetro o tipo de caixa de diálogo a ser exibida ao usuário (passe a constante SSUIT_None para não exibir nenhuma caixa) e o caminho de ScanFolder para a pasta com os resultados.
  6. Os nomes dos arquivos de imagem serão retornados por este método como um objeto StringsCollection. É possível obter os nomes dos arquivos de imagem desse objeto StringsCollection e, em seguida, processar os arquivos como arquivos de imagem comuns.
Para digitalizar as imagens de forma assíncrona:
  1. Crie um objeto que implemente a interface IScanCallback. No caso de uma operação de digitalização assíncrona, as notificações da interface de callback são muito úteis.
  2. Crie um objeto ScanManager. É possível especificar se os logs de digitalização devem ser gravados por meio do parâmetro de entrada do método CreateScanManager.
  3. Selecione a origem de digitalização usando o método FindScanSources do objeto ScanManager, especificando a API e o tipo de UI que o scanner deve suportar.
  4. Se você optar por não exibir uma caixa de diálogo para que o próprio usuário configure as opções de digitalização, ajuste essas opções usando a propriedade ScanSettings do ScanSource escolhido. Selecione os valores apropriados de brilho, resolução e dos outros parâmetros nas propriedades correspondentes do objeto ScanSourceSettings. Você pode verificar quais configurações estão disponíveis para esse scanner usando a propriedade Capabilities do ScanSource.
  5. Especifique o nome da pasta em que as páginas digitalizadas serão armazenadas. O nome da pasta deve ser uma variável do tipo BSTR, por exemplo, ScanFolder.
  6. Execute o método BeginScan do objeto ScanSource, fornecendo como parâmetro o tipo de caixa de diálogo a ser exibida ao usuário (passe a constante SSUIT_None para não exibir nenhuma caixa) e o caminho de ScanFolder até a pasta com os resultados. Você também precisa passar o ponteiro para o objeto de callback que criou.
  7. O caminho para o arquivo de imagem é retornado pela notificação OnImageScanned da interface IScanCallback, e a conclusão da operação é sinalizada pela notificação OnScanComplete. Como você está implementando esses métodos, pode escolher o que fazer em cada uma dessas situações. Por exemplo, ao receber o caminho para um arquivo de imagem, você pode trabalhar com ele como com qualquer outro arquivo em disco, carregando-o para processamento com o FineReader Engine da forma usual.
Até que a digitalização seja concluída e a notificação OnScanComplete seja recebida, você não poderá executar BeginScan ou Scan novamente, nem mesmo para outro scanner. A vantagem da digitalização assíncrona não é poder realizar várias operações de digitalização ao mesmo tempo, mas sim processar as imagens que você já recebeu enquanto as novas imagens estão sendo digitalizadas.
Veja a seguir um exemplo de código para o cenário de digitalização assíncrona:

C#

// Implementar a interface IScanCallback
class ScanningCallback :FREngine.IScanCallback
{
  // construtor
  public ScanningCallback() {}
  ...
  // fornecer a implementação dos métodos IScanCallback
  public void OnError(string sourceName, string message) { // reportar ou tratar o erro aqui }
  public void OnImageScanned(string sourceName, string Path, ref bool cancel) { // inserir aqui qualquer ação necessária ao digitalizar uma imagem }
  public void OnScanComplete() { // inserir aqui uma ação a ser executada após a conclusão da digitalização }
  // variáveis privadas
  ...
}
// Criar o gerenciador de digitalização com os logs desativados
scanManager = engineLoader.Engine.CreateScanManager(false);
// Criar uma lista de fontes de digitalização filtradas por tipo de API e UI
FREngine.IScanSources sources = scanManager.FindScanSources(UIType, APIType);
// Apenas como exemplo, escolher a primeira fonte de digitalização da coleção
FREngine.IScanSource selectedSource = sources[0];
// Acessar as configurações e capacidades da fonte de digitalização
FREngine.IScanSourceSettings settings = selectedSource.ScanSettings;
FREngine.IScanSourceCapabilities capabilities = selectedSource.Capabilities;
// Definir as opções de digitalização para o modo duplex, se o scanner suportar
settings.DuplexMode = capabilities.HasDuplexMode;
// Definir opções para digitalização de múltiplas páginas e atraso de 10 segundos entre páginas
settings.MultipleImagesEnabled = true;
settings.PauseBetweenPagesMode = FREngine.ScanPauseModeEnum.SPM_PresetDelay;
settings.Delay = 10;
// Definir o caminho para a pasta com os resultados
string scanFolder = "D:\\SampleImages";
// Criar um objeto de callback
IScanningCallback callback = new ScanningCallback();
// Iniciar a digitalização
selectedSource.BeginScan(SSUIT_None, scanFolder, callback);
Depois de concluir o trabalho com o ABBYY FineReader Engine, você precisa descarregar o objeto Engine. Para fazer isso, use a função exportada DeinitializeEngine.

C#

public class EngineLoader : IDisposable
{
    // Descarrega o FineReader Engine
    public void Dispose()
    {
        if (engine == null)
        {
            // O Engine não foi carregado
            return;
        }
        engine = null;
        // Exclui todos os objetos antes da chamada 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;
        // lança exceção após a limpeza
        Marshal.ThrowExceptionForHR(hresult);
    }
    // Funções 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);
    // Funções 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();
    // variáveis privadas
    private FREngine.IEngine engine = null;
    // Handle para FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

Recursos necessários

Você pode usar o arquivo FREngineDistribution.csv para criar automaticamente uma lista dos arquivos necessários para que seu aplicativo funcione. Para o processamento com este cenário, selecione na coluna 5 (RequiredByModule) os seguintes valores: Core Core.Resources Opening Opening, Processing Opening.Scanning Se você modificar o cenário padrão, ajuste os módulos necessários conforme apropriado. Você também precisa especificar os idiomas da interface, os idiomas de reconhecimento e todos os recursos adicionais usados pelo seu aplicativo (como, por exemplo, Processing.OCR.CJK, se precisar reconhecer textos em idiomas CJK). Consulte Working with the FREngineDistribution.csv File para mais informações.

Otimização adicional

Estas são as seções do arquivo de ajuda em que você pode encontrar informações adicionais sobre a configuração dos parâmetros para os vários estágios de processamento:
  • Separação de documentos
    • Nesse cenário, pode ser necessário agrupar o fluxo de imagens de entrada em documentos. Por exemplo, você pode saber o número de páginas de cada documento ou garantir que haja páginas separadoras com códigos de barras entre a última página do primeiro documento e a primeira página do documento seguinte. Consulte o cenário de reconhecimento de código de barras.

Veja também

Implementação de cenários básicos de uso