> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Field-Level Recognition

> Recognize short text fragments — fields on forms or scanned documents — with ABBYY FineReader Engine, with high-accuracy settings, certainty ratings, and voting for verification.

In the case of field-level recognition, short text fragments are recognized in order to capture data from certain fields. The recognition quality is crucial in this scenario.

This scenario may also be used as part of more complex scenarios where meaningful data are to be extracted from documents (for example, to capture data from paper documents into information systems and databases or to automatically classify and index documents in Document Management Systems).

In this scenario, the system recognizes either several lines of text in only some of the fields or the entire text on a small image. The system computes a certainty rating for each recognized character. The certainty ratings can then be used when checking the recognition results. Additionally, the system may store multiple recognition variants for words and characters in the text, which may then be used in voting algorithms to improve the quality of recognition.

The processing of small text fragments in this scenario is in some ways different from the same steps in other scenarios:

1. Preprocessing of scanned images or photos

   The images to be recognized may include markup and background noise, both of which may hamper recognition. For this reason, any unwanted markup and background noise are removed at this stage.

2. Recognition of small text fragments

   When recognizing small text fragments, the type of data to be recognized is known in advance. Therefore, the quality of recognition may be improved through the use of external dictionaries, regular expressions, custom recognition languages, and alphabets, and by imposing restrictions on the number of characters in a string. Text fields may contain printed, handprinted, and handwritten text.

3. Working with the recognized data

   This scenario requires maximum recognition accuracy in order to keep data verification work to a minimum. The system may compute a certainty rating for each recognized word or character and provide multiple recognition variants from which several Engines may then choose the best candidate by applying voting algorithms.

## Scenario implementation

<Note>
  The code samples provided in this topic are Windows -specific.
</Note>

Below follows a detailed description of the recommended method of using ABBYY FineReader Engine 12 in this scenario. The suggested method uses processing settings deemed most appropriate for this scenario.

<Accordion title="Step 1. Loading ABBYY FineReader Engine">
  To start your work with ABBYY FineReader Engine, you need to create the [Engine](/fine-reader/engine/api-reference/engine-object-iengine-interface) object. The Engine object is the top object in the hierarchy of the ABBYY FineReader Engine objects and provides various global settings, some processing methods, and methods for creating the other objects.

  To create the Engine object, you can use the [InitializeEngine](/fine-reader/engine/api-reference/functions/initializeengine-function) function. See also [other ways to load Engine object](/fine-reader/engine/guided-tour/advanced-techniques/programming-aspects/different-ways-to-load-engine) (Win).

  ### C\#

  ```csharp theme={null}
  public class EngineLoader : IDisposable
  {
      public EngineLoader()
      {
          // Initialize these variables with the full path to FREngine.dll, your Customer Project ID,
          // and, if applicable, the path to your Online License token file and the Online License password
          string enginePath = "";
          string customerProjectId = "";
          string licensePath = "";
          string licensePassword = "";
          // Load the FREngine.dll library
          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");
              }
              // Convert pointers to delegates
              initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                  initializeEnginePtr, typeof(InitializeEngine));
              deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                  deinitializeEnginePtr, typeof(DeinitializeEngine));
              dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                  dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
              // Call the InitializeEngine function 
              // passing the path to the Online License file and the Online License password
              int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                  "", "", false, ref engine);
              Marshal.ThrowExceptionForHR(hresult);
          }
          catch (Exception)
          {
              // Free the FREngine.dll library
              engine = null;
              // Deleting all objects before FreeLibrary call
              GC.Collect();
              GC.WaitForPendingFinalizers();
              GC.Collect();
              FreeLibrary(dllHandle);
              dllHandle = IntPtr.Zero;
              initializeEngine = null;
              deinitializeEngine = null;
              dllCanUnloadNow = null;
              throw;
          }
      }
      // Kernel32.dll functions
      [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);
      // FREngine.dll functions
      [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();
      // private variables
      private FREngine.IEngine engine = null;
      // Handle to FREngine.dll
      private IntPtr dllHandle = IntPtr.Zero;
      private InitializeEngine initializeEngine = null;
      private DeinitializeEngine deinitializeEngine = null;
      private DllCanUnloadNow dllCanUnloadNow = null;
  }
  ```

  ### C++ (COM)

  ```cpp theme={null}
  // Initialize these variables with the path to FREngine.dll, your FineReader Engine customer project ID,
  // and, if applicable, the path to the Online License token and Online License password
  wchar_t* FreDllPath;
  wchar_t* CustomerProjectId;
  wchar_t* LicensePath;  // if you don't use an Online License, assign empty strings to these variables
  wchar_t* LicensePassword;
  // HANDLE to FREngine.dll
  static HMODULE libraryHandle = 0;
  // Global FineReader Engine object
  FREngine::IEnginePtr Engine;
  void LoadFREngine()
  {
      if( Engine != 0 ) {
      // Already loaded
      return;
      }
      // First step: load FREngine.dll
      if( libraryHandle == 0 ) {
          libraryHandle = LoadLibraryEx( FreDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
          if( libraryHandle == 0 ) {
              throw L"Error while loading ABBYY FineReader Engine";
          }
      }
      // Second step: obtain the Engine object
      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 while loading ABBYY FineReader Engine";
      }
  }
  ```
</Accordion>

<Accordion title="Step 2. Loading settings for the scenario">
  The most suitable settings can be selected by using the [LoadPredefinedProfile](/fine-reader/engine/api-reference/engine-object-iengine-interface/supplementary-methods/loadpredefinedprofile-method) method of the [Engine](/fine-reader/engine/api-reference/engine-object-iengine-interface) object. This method receives the profile name as the input parameter. The most suitable settings can be selected by using the predefined profile called FieldLevelRecognition. For more about profiles, see [Working with Profiles](/fine-reader/engine/guided-tour/advanced-techniques/working-with-profiles).

  ### C\#

  ```csharp theme={null}
  // Load a predefined profile
  engine.LoadPredefinedProfile("FieldLevelRecognition");
  ```

  ### C++ (COM)

  ```cpp theme={null}
  // Load a predefined profile
  Engine->LoadPredefinedProfile( L"FieldLevelRecognition" );
  ```

  If you wish to change the settings used for processing, use the corresponding parameter objects. See the [Additional optimization](/fine-reader/engine/guided-tour/basic-usage-scenarios-implementation/field-level-recognition#optimization) section below for more information.
</Accordion>

<Accordion title="Step 3. Loading and preprocessing the images">
  ABBYY FineReader Engine provides a [FRDocument](/fine-reader/engine/api-reference/document-related-objects/frdocument) object for processing multi-page documents. To load the images of a document and preprocess them, you should create the FRDocument object and add images to it. You can do one of the following:

  * Create an FRDocument object using the [CreateFRDocumentFromImage](/fine-reader/engine/api-reference/engine-object-iengine-interface/creation-methods/createfrdocumentfromimage-method) method of the Engine object. This method creates an FRDocument object and loads images from a specified file.
  * Create an FRDocument object with the help of the [CreateFRDocument](/fine-reader/engine/api-reference/engine-object-iengine-interface/creation-methods/createlessobjectgreater-methods) method of the Engine object, then add the images into the created FRDocument object from a file (use the [AddImageFile](/fine-reader/engine/api-reference/document-related-objects/frdocument/addimagefile-method), [AddImageFileWithPassword](/fine-reader/engine/api-reference/document-related-objects/frdocument/addimagefilewithpassword-method), or [AddImageFileWithPasswordCallback](/fine-reader/engine/api-reference/document-related-objects/frdocument/addimagefilewithpasswordcallback-method) method of the FRDocument object).

  ### C\#

  ```csharp theme={null}
  // Create the FRDocument object from an image file
  FREngine.IFRDocument frDocument = engine.CreateFRDocumentFromImage( "C:\\MyImage.tif", null );
  ```

  ### C++ (COM)

  ```cpp theme={null}
  // Open an image file and create the FRDocument object
  FREngine::IFRDocumentPtr frDocument = Engine->CreateFRDocumentFromImage( L"C:\\MyImage.tif", 0 );
  ```
</Accordion>

<Accordion title="Step 4. Setting up the fields to be recognized">
  Now you need to create blocks that contain your fields, and for each specify block type and known characteristics of the data inside.

  Perform layout analysis of the document using the [Analyze](/fine-reader/engine/api-reference/document-related-objects/frdocument/analyze-method) method, or manually add blocks that contain the fields you need to recognize. See [Working with Layout and Blocks](/fine-reader/engine/guided-tour/advanced-techniques/working-with-layout-and-blocks#adding_manually) for instructions.

  For each field, you can now specify its own parameters of recognition. For example, if a field contains some text, use the [ITextBlock::RecognizerParams](/fine-reader/engine/api-reference/layout-related-objects/textblock#recognizerparams) property:

  * set the text type with the help of the TextTypes property of the [RecognizerParams](/fine-reader/engine/api-reference/parameter-objects/preprocessing-analysis-recognition-and-synthesis-parameters/recognizerparams) object. E.g., if the field contains digits written in ZIP-code style, use TT\_Index text type.
  * set the language using the [SetPredefinedTextLanguage](/fine-reader/engine/api-reference/parameter-objects/preprocessing-analysis-recognition-and-synthesis-parameters/recognizerparams/setpredefinedtextlanguage-method) method. Using [special predefined languages](/fine-reader/engine/specifications/special-predefined-languages) (Windows only) can be helpful if you know the type of information contained in the field. E.g., if the field contains an address in the US, select the English\_US\_Address predefined language. This will ensure that the text is recognized more reliably.
  * set the SaveCharacterRecognitionVariants and SaveWordRecognitionVariants properties of the [RecognizerParams](/fine-reader/engine/api-reference/parameter-objects/preprocessing-analysis-recognition-and-synthesis-parameters/recognizerparams) object if you need to use the recognition variants for further verification of the result, as described below in step 6. Note that this setting is not available for handwritten or handprinted texts.

  For further details on recognizing different types of fields, consult the [Recognizing Checkmarks](/fine-reader/engine/guided-tour/advanced-techniques/recognizing-checkmarks), [Recognizing Handwritten Texts](/fine-reader/engine/guided-tour/advanced-techniques/recognizing-handwritten-texts), [Recognizing Barcodes](/fine-reader/engine/guided-tour/advanced-techniques/recognizing-barcodes), and [Recognizing Words with Spaces](/fine-reader/engine/guided-tour/advanced-techniques/recognizing-words-with-spaces) sections.

  ### C\#

  ```csharp theme={null}
  // Analyze the document layout
  frDocument.Analyze( null, null, null );
  // Assume that we know the first block
  // in the layout contains an address in the US
  FREngine.ITextBlock addressBlock = frDocument.Pages[0].Layout.Blocks[0].GetAsTextBlock();
  FREngine.IRecognizerParams paramsAddressBlock = addressBlock.RecognizerParams;
  paramsAddressBlock.SetPredefinedTextLanguage( "English_US_Address" );
  // Enable collecting recognition variants
  paramsAddressBlock.SaveCharacterRecognitionVariants = true;
  paramsAddressBlock.SaveWordRecognitionVariants = true;
  // Set up the properties of other layout blocks in the same way
  ...
  ```

  ### C++ (COM)

  ```cpp theme={null}
  // Analyze the document layout
  frDocument->Analyze( 0, 0, 0 );
  // Assume that we know the first block
  // in the layout contains an address in the US
  FREngine::ILayoutBlocksPtr layoutBlocks = frDocument->Pages->Item( 0 )->Layout->Blocks;
  FREngine::IRecognizerParamsPtr paramsAddressBlock = layoutBlocks->Item( 0 )->GetAsTextBlock()->RecognizerParams;
  paramsAddressBlock->SetPredefinedTextLanguage( L"English_US_Address" );
  // Enable collecting recognition variants
  paramsAddressBlock->SaveCharacterRecognitionVariants = VARIANT_TRUE;
  paramsAddressBlock->SaveWordRecognitionVariants = VARIANT_TRUE;
  // Set up the properties of other layout blocks in the same way
  ...
  ```
</Accordion>

<Accordion title="Step 5. Recognition">
  As the document layout has already been analyzed and additionally modified by you, do not call the analysis methods again. Use the [Recognize](/fine-reader/engine/api-reference/document-related-objects/frdocument/recognize-method) method, which performs recognition and page synthesis for all pages in the document. In this scenario, you need to extract the data from fields and not export the recognized document, therefore you will not need document synthesis.

  ### C\#

  ```csharp theme={null}
  // Recognize the document
  // There is no need to specify parameters because they are set up by the processing profile
  frDocument.Recognize( null, null );
  ```

  ### C++ (COM)

  ```cpp theme={null}
  // Recognize the document
  // There is no need to specify parameters because they are set up by the processing profile
  frDocument->Recognize( 0, 0 );
  ```
</Accordion>

<Accordion title="Step 6. Working with the recognized data">
  Use the [Text](/fine-reader/engine/api-reference/text-related-objects/text) object to access the recognized text fragment (you can get this object for a text block via the [ITextBlock::Text](/fine-reader/engine/api-reference/layout-related-objects/textblock#text) property). Use the Paragraphs property to get the collection of paragraphs in the fragment and the [IParagraphs::Item](/fine-reader/engine/api-reference/text-related-objects/paragraphs) method to access the individual paragraphs. The [IParagraph::Text](/fine-reader/engine/api-reference/text-related-objects/paragraph#text) property provides access to the recognized text of a paragraph.

  You can use the [IParagraph::Words](/fine-reader/engine/api-reference/text-related-objects/paragraph#words) to get the collection of words in a paragraph. Use the [IWords::Item](/fine-reader/engine/api-reference/text-related-objects/words) method to access individual words in the collection. The [IWord::Text](/fine-reader/engine/api-reference/text-related-objects/word) property returns the line that contains the recognized word. Use the [GetRecognitionVariants](/fine-reader/engine/api-reference/text-related-objects/word/getrecognitionvariants-method) method of the Word object or the [GetWordRecognitionVariants](/fine-reader/engine/api-reference/text-related-objects/paragraph/getwordrecognitionvariants-metho) method of the Paragraph object to get the recognition variants for a word.

  The attributes of individual characters can be accessed via the [GetCharParams](/fine-reader/engine/api-reference/text-related-objects/paragraph/getcharparams-method) method of the Paragraph object. This method provides access to the [CharParams](/fine-reader/engine/api-reference/text-related-objects/charparams) object, which contains the parameters of the recognized character. The recognition variants for a character are accessible via the [ICharParams::CharacterRecognitionVariants](/fine-reader/engine/api-reference/text-related-objects/charparams#characterrecognitionvariants) property.

  For detailed information on working with text, see [Working with Text](/fine-reader/engine/guided-tour/advanced-techniques/working-with-text). For information on using the Engine in voting algorithms, see [Using Voting API](/fine-reader/engine/guided-tour/advanced-techniques/using-voting-api).

  After you have finished your work with the FRDocument object, release all the resources that were used by this object. Use the [IFRDocument::Close](/fine-reader/engine/api-reference/document-related-objects/frdocument/close-method) method.
</Accordion>

<Accordion title="Step 7. Unloading ABBYY FineReader Engine">
  After finishing your work with ABBYY FineReader Engine, you need to unload the [Engine](/fine-reader/engine/api-reference/engine-object-iengine-interface) object. To do this, use the [DeinitializeEngine](/fine-reader/engine/api-reference/functions/deinitializeengine-function) exported function.

  ### C\#

  ```csharp theme={null}
  public class EngineLoader : IDisposable
  {
      // Unload FineReader Engine
      public void Dispose()
      {
          if (engine == null)
          {
              // Engine was not loaded
              return;
          }
          engine = null;
          // Deleting all objects before FreeLibrary call
          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;
          // throwing exception after cleaning up
          Marshal.ThrowExceptionForHR(hresult);
      }
      // Kernel32.dll functions
      [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);
      // FREngine.dll functions
      [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();
      // private variables
      private FREngine.IEngine engine = null;
      // Handle to FREngine.dll
      private IntPtr dllHandle = IntPtr.Zero;
      private InitializeEngine initializeEngine = null;
      private DeinitializeEngine deinitializeEngine = null;
      private DllCanUnloadNow dllCanUnloadNow = null;
  }
  ```

  ### C++ (COM)

  ```cpp theme={null}
  void UnloadFREngine()
  {
   if( libraryHandle == 0 ) {
    return;
   }
   // Release Engine object
   Engine = 0;
   // Deinitialize FineReader Engine
   typedef HRESULT ( STDAPICALLTYPE* DeinitializeEngineFunc )();
   DeinitializeEngineFunc pDeinitializeEngine =
    ( DeinitializeEngineFunc )GetProcAddress( libraryHandle, "DeinitializeEngine" );
   if( pDeinitializeEngine == 0 || pDeinitializeEngine() != S_OK ) {
    throw L"Error while unloading ABBYY FineReader Engine";
   }
   // Now it's safe to free the FREngine.dll library
   FreeLibrary( libraryHandle );
   libraryHandle = 0;
  }
  ```
</Accordion>

## Required resources

You can use the [FREngineDistribution.csv](/fine-reader/engine/distribution/distribution-windows/distribution-kit/working-with-the-frenginedistributioncsv-file) file to automatically create a list of files required for your application to function. For processing with this scenario, select in the column 5 (RequiredByModule) the following values:

Core

Core.Resources

Opening

Opening, Processing

Processing

Processing.OCR

Processing.OCR, Processing.ICR

Processing.OCR.NaturalLanguages

Processing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguages

If you modify the standard scenario, change the required modules accordingly. You also need to specify the interface languages, recognition languages and any additional features which your application uses (such as, e.g., Opening.PDF if you need to open PDF files, or Processing.OCR.CJK if you need to recognize texts in [CJK languages](/fine-reader/engine/guided-tour/advanced-techniques/recognizing-cjk-languages#cjk)). See [Working with the FREngineDistribution.csv File](/fine-reader/engine/distribution/distribution-windows/distribution-kit/working-with-the-frenginedistributioncsv-file) for further details.

## Additional optimization

These are the sections of the help file where you can find additional information about setting up the parameters for the various processing stages:

* Recognition
  * [Working with Languages](/fine-reader/engine/guided-tour/advanced-techniques/working-with-languages)<br />Using built-in and custom recognition languages.
  * [Working with Dictionaries](/fine-reader/engine/guided-tour/advanced-techniques/working-with-dictionaries)<br />Using dictionaries to improve recognition quality.
  * [Recognizing Words with Spaces](/fine-reader/engine/guided-tour/advanced-techniques/recognizing-words-with-spaces)<br />Using dictionaries to recognize words with spaces (such as New York, etc.).
  * [Recognizing Handwritten Texts](/fine-reader/engine/guided-tour/advanced-techniques/recognizing-handwritten-texts)<br />Using ICR (Intelligent Character Recognition).
  * [Recognizing Checkmarks](/fine-reader/engine/guided-tour/advanced-techniques/recognizing-checkmarks)<br />Setting up recognition of checkmarks and groups of checkmarks.
  * [Special Predefined Languages in ABBYY FineReader Engine](/fine-reader/engine/specifications/special-predefined-languages) - Windows<br />The list of recognition languages that contain special language units: addresses, date and time, human names, etc. These languages can be used for field recognition.
* Working with the recognized data
  * [Working with Text](/fine-reader/engine/guided-tour/advanced-techniques/working-with-text)<br />Working with the recognized text, paragraphs, words, and characters.
  * [Using Voting API](/fine-reader/engine/guided-tour/advanced-techniques/using-voting-api)<br />Working with words and character recognition alternatives.

## See also

[Basic Usage Scenarios Implementation](/fine-reader/engine/guided-tour/basic-usage-scenarios-implementation)
