Pular para o conteúdo principal
No caso do reconhecimento em nível de campo, pequenos fragmentos de texto são reconhecidos para capturar dados de determinados campos. A qualidade do reconhecimento é crucial nesse cenário. Esse cenário também pode ser usado como parte de cenários mais complexos, nos quais dados relevantes precisam ser extraídos de documentos (por exemplo, para capturar dados de documentos em papel em sistemas de informação e bancos de dados ou para classificar e indexar documentos automaticamente em Sistemas de Gerenciamento de Documentos). Nesse cenário, o sistema reconhece várias linhas de texto em apenas alguns campos ou o texto completo em uma imagem pequena. O sistema calcula um nível de confiabilidade para cada caractere reconhecido. Esses níveis de confiabilidade podem então ser usados na verificação dos resultados do reconhecimento. Além disso, o sistema pode armazenar várias variantes de reconhecimento para palavras e caracteres no texto, que depois podem ser usadas em algoritmos de votação para melhorar a qualidade do reconhecimento. O processamento de pequenos fragmentos de texto nesse cenário difere, em alguns aspectos, das mesmas etapas em outros cenários:
  1. Pré-processamento de imagens digitalizadas ou fotos
As imagens a serem reconhecidas podem incluir marcações e ruído de fundo, ambos capazes de prejudicar o reconhecimento. Por esse motivo, quaisquer marcações indesejadas e ruídos de fundo são removidos nesta etapa.
  1. Reconhecimento de pequenos fragmentos de texto
Ao reconhecer pequenos fragmentos de texto, o tipo de dado a ser reconhecido é conhecido antecipadamente. Portanto, a qualidade do reconhecimento pode ser melhorada por meio do uso de dicionários externos, expressões regulares, idiomas de reconhecimento e alfabetos personalizados, além da imposição de restrições ao número de caracteres em uma string. Os campos de texto podem conter texto impresso, escrito à mão em letra de forma e manuscrito.
  1. Trabalho com os dados reconhecidos
Esse cenário exige a máxima precisão de reconhecimento para reduzir ao mínimo o trabalho de verificação de dados. O sistema pode calcular um nível de confiabilidade para cada palavra ou caractere reconhecido e fornecer várias variantes de reconhecimento, entre as quais vários Engines podem então escolher o melhor candidato aplicando algoritmos de votação.

Implementação do cenário

Os exemplos de código fornecidos neste tópico são específicos para Windows.
A seguir, apresentamos uma descrição detalhada do método recomendado para usar o ABBYY FineReader Engine 12 neste cenário. Esse método utiliza as configurações de processamento consideradas mais adequadas para este cenário.
Para começar a trabalhar com o ABBYY FineReader Engine, você precisa criar o objeto Engine. O objeto Engine é o objeto de nível mais alto na hierarquia de objetos do ABBYY FineReader Engine e fornece diversas configurações globais, alguns métodos de processamento e métodos para criar os demais objetos.Para criar o objeto Engine, você pode usar a função InitializeEngine. Consulte 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 Online License e a senha da Online License
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // Carregue a biblioteca FREngine.dll
        dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
           
        try
        {
            if (dllHandle == IntPtr.Zero)
            {
                throw new Exception("Não foi possível carregar " + enginePath);
            }
            IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
            if (initializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Não foi possível encontrar a função InitializeEngine");
            }
            IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
            if (deinitializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Não foi possível encontrar a função DeinitializeEngine");
            }
            IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
            if (dllCanUnloadNowPtr == IntPtr.Zero)
            {
                throw new Exception("Não foi possível encontrar a função DllCanUnloadNow");
            }
            // Converter ponteiros em delegates
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // Chamar a função InitializeEngine
            // passando o caminho para o arquivo da Online License e a senha da Online License
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // Liberar a biblioteca FREngine.dll
            engine = null;
            // Excluindo todos os objetos antes da chamada de FreeLibrary
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            FreeLibrary(dllHandle);
            dllHandle = IntPtr.Zero;
            initializeEngine = null;
            deinitializeEngine = null;
            dllCanUnloadNow = null;
            throw;
        }
    }
    // Funções do 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 do 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 para FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

C++ (COM)

// Inicialize estas variáveis com o caminho para FREngine.dll, o ID do projeto do cliente do FineReader Engine,
// e, se aplicável, o caminho para o token da Online License e a senha da Online License
wchar_t* FreDllPath;
wchar_t* CustomerProjectId;
wchar_t* LicensePath;  // se você não usar uma Online License, atribua strings vazias a estas variáveis
wchar_t* LicensePassword;
// HANDLE para FREngine.dll
static HMODULE libraryHandle = 0;
// Objeto global do FineReader Engine
FREngine::IEnginePtr Engine;
void LoadFREngine()
{
    if( Engine != 0 ) {
    // Já carregado
    return;
    }
    // Primeiro passo: carregar FREngine.dll
    if( libraryHandle == 0 ) {
        libraryHandle = LoadLibraryEx( FreDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
        if( libraryHandle == 0 ) {
            throw L"Erro ao carregar o ABBYY FineReader Engine";
        }
    }
    // Segundo passo: obter o 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"Erro ao carregar o ABBYY FineReader Engine";
    }
}
As configurações mais adequadas podem ser selecionadas usando o método LoadPredefinedProfile do objeto Engine. Esse método recebe o nome do perfil como parâmetro de entrada. As configurações mais adequadas podem ser selecionadas usando o perfil predefinido chamado FieldLevelRecognition. Para saber mais sobre perfis, consulte Working with Profiles.

C#

// Carregar um perfil predefinido
engine.LoadPredefinedProfile("FieldLevelRecognition");

C++ (COM)

// Carregar um perfil predefinido
Engine->LoadPredefinedProfile( L"FieldLevelRecognition" );
Se quiser alterar as configurações usadas no processamento, use os objetos de parâmetro correspondentes. Consulte a seção Otimização adicional abaixo para mais informações.
O ABBYY FineReader Engine fornece um objeto FRDocument para processar documentos com várias páginas. Para carregar as imagens de um documento e pré-processá-las, você deve criar o objeto FRDocument e adicionar as imagens a ele. Você pode fazer um dos seguintes procedimentos:

C#

// Criar o objeto FRDocument a partir de um arquivo de imagem
FREngine.IFRDocument frDocument = engine.CreateFRDocumentFromImage( "C:\\MyImage.tif", null );

C++ (COM)

// Abrir um arquivo de imagem e criar o objeto FRDocument
FREngine::IFRDocumentPtr frDocument = Engine->CreateFRDocumentFromImage( L"C:\\MyImage.tif", 0 );
Agora você precisa criar blocos que contenham seus campos e, para cada um deles, especificar o tipo de bloco e as características conhecidas dos dados contidos nele.Faça a análise de layout do documento usando o método Analyze ou adicione manualmente blocos que contenham os campos que você precisa reconhecer. Consulte Working with Layout and Blocks para obter instruções.Agora, para cada campo, você pode especificar seus próprios parâmetros de reconhecimento. Por exemplo, se um campo contiver texto, use a propriedade ITextBlock::RecognizerParams:
  • defina o tipo de texto com a ajuda da propriedade TextTypes do objeto RecognizerParams. Por exemplo, se o campo contiver dígitos escritos no formato de CEP, use o tipo de texto TT_Index.
  • defina o idioma usando o método SetPredefinedTextLanguage. Usar idiomas predefinidos especiais (somente Windows) pode ser útil se você souber o tipo de informação contida no campo. Por exemplo, se o campo contiver um endereço nos EUA, selecione o idioma predefinido English_US_Address. Isso garantirá um reconhecimento mais confiável do texto.
  • defina as propriedades SaveCharacterRecognitionVariants e SaveWordRecognitionVariants do objeto RecognizerParams se você precisar usar variantes de reconhecimento para verificar melhor o resultado, como descrito abaixo na etapa 6. Observe que essa configuração não está disponível para textos manuscritos ou em letra de forma.
Para mais detalhes sobre o reconhecimento de diferentes tipos de campos, consulte as seções Recognizing Checkmarks, Recognizing Handwritten Texts, Recognizing Barcodes e Recognizing Words with Spaces.

C#

// Analisa o layout do documento
frDocument.Analyze( null, null, null );
// Suponha que sabemos que o primeiro bloco
// no layout contém um endereço nos EUA
FREngine.ITextBlock addressBlock = frDocument.Pages[0].Layout.Blocks[0].GetAsTextBlock();
FREngine.IRecognizerParams paramsAddressBlock = addressBlock.RecognizerParams;
paramsAddressBlock.SetPredefinedTextLanguage( "English_US_Address" );
// Habilita a coleta de variantes de reconhecimento
paramsAddressBlock.SaveCharacterRecognitionVariants = true;
paramsAddressBlock.SaveWordRecognitionVariants = true;
// Configure as propriedades dos outros blocos do layout da mesma forma
...

C++ (COM)

// Analisa o layout do documento
frDocument->Analyze( 0, 0, 0 );
// Suponha que sabemos que o primeiro bloco
// no layout contém um endereço nos EUA
FREngine::ILayoutBlocksPtr layoutBlocks = frDocument->Pages->Item( 0 )->Layout->Blocks;
FREngine::IRecognizerParamsPtr paramsAddressBlock = layoutBlocks->Item( 0 )->GetAsTextBlock()->RecognizerParams;
paramsAddressBlock->SetPredefinedTextLanguage( L"English_US_Address" );
// Habilita a coleta de variantes de reconhecimento
paramsAddressBlock->SaveCharacterRecognitionVariants = VARIANT_TRUE;
paramsAddressBlock->SaveWordRecognitionVariants = VARIANT_TRUE;
// Configure as propriedades dos outros blocos do layout da mesma forma
...
Como o layout do documento já foi analisado e também modificado por você, não chame os métodos de análise novamente. Use o método Recognize, que executa o reconhecimento e a síntese de páginas para todas as páginas do documento. Neste cenário, você precisa extrair os dados dos campos, e não exportar o documento reconhecido, portanto não precisará da síntese do documento.

C#

// Reconhecer o documento
// Não é necessário especificar parâmetros, porque eles são definidos pelo perfil de processamento
frDocument.Recognize( null, null );

C++ (COM)

// Reconhecer o documento
// Não é necessário especificar parâmetros, porque eles são definidos pelo perfil de processamento
frDocument->Recognize( 0, 0 );
Use o objeto Text para acessar o fragmento de texto reconhecido (você pode obter esse objeto para um bloco de texto por meio da propriedade ITextBlock::Text). Use a propriedade Paragraphs para obter a coleção de parágrafos do fragmento e o método IParagraphs::Item para acessar parágrafos individuais. A propriedade IParagraph::Text fornece acesso ao texto reconhecido de um parágrafo.Você pode usar IParagraph::Words para obter a coleção de palavras de um parágrafo. Use o método IWords::Item para acessar palavras individuais nessa coleção. A propriedade IWord::Text retorna a linha que contém a palavra reconhecida. Use o método GetRecognitionVariants do objeto Word ou o método GetWordRecognitionVariants do objeto Paragraph para obter as variantes de reconhecimento de uma palavra.Os atributos de caracteres individuais podem ser acessados por meio do método GetCharParams do objeto Paragraph. Esse método fornece acesso ao objeto CharParams, que contém os parâmetros do caractere reconhecido. As variantes de reconhecimento de um caractere podem ser acessadas por meio da propriedade ICharParams::CharacterRecognitionVariants.Para obter informações detalhadas sobre como trabalhar com texto, consulte Trabalhando com texto. Para obter informações sobre o uso do Engine em algoritmos de votação, consulte Usando a API de votação.Depois de concluir o trabalho com o objeto FRDocument, libere todos os recursos usados por esse objeto. Use o método IFRDocument::Close.
Depois de concluir o trabalho com o ABBYY FineReader Engine, você precisa descarregar o objeto Engine. Para 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;
        // gera uma 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;
    // Identificador de FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

C++ (COM)

void UnloadFREngine()
{
 if( libraryHandle == 0 ) {
  return;
 }
 // Libera o objeto Engine
 Engine = 0;
 // Desinicializa o FineReader Engine
 typedef HRESULT ( STDAPICALLTYPE* DeinitializeEngineFunc )();
 DeinitializeEngineFunc pDeinitializeEngine =
  ( DeinitializeEngineFunc )GetProcAddress( libraryHandle, "DeinitializeEngine" );
 if( pDeinitializeEngine == 0 || pDeinitializeEngine() != S_OK ) {
  throw L"Erro ao descarregar o ABBYY FineReader Engine";
 }
 // Agora é seguro liberar a biblioteca FREngine.dll
 FreeLibrary( libraryHandle );
 libraryHandle = 0;
}

Recursos necessários

Você pode usar o arquivo FREngineDistribution.csv para criar automaticamente uma lista dos arquivos necessários para o funcionamento da sua aplicação. Para processar com este cenário, selecione na coluna 5 (RequiredByModule) os seguintes valores: Core Core.Resources Opening Opening, Processing Processing Processing.OCR Processing.OCR, Processing.ICR Processing.OCR.NaturalLanguages Processing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguages Se você modificar o cenário padrão, ajuste os módulos necessários adequadamente. Você também precisa especificar os idiomas da interface, os idiomas de reconhecimento e todos os recursos adicionais usados pela sua aplicação (como, por exemplo, Opening.PDF, se precisar abrir arquivos PDF, ou Processing.OCR.CJK, se precisar reconhecer textos em idiomas CJK). Consulte Como trabalhar com o arquivo FREngineDistribution.csv para mais detalhes.

Otimização adicional

Estas são as seções do arquivo de ajuda em que você pode encontrar informações adicionais sobre como configurar os parâmetros para as várias etapas de processamento:

Veja também

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