Passer au contenu principal
Dans le cas de la reconnaissance au niveau des champs, de courts fragments de texte sont reconnus afin de capturer les données de certains champs. La qualité de la reconnaissance est cruciale dans ce scénario. Ce scénario peut également être utilisé dans le cadre de scénarios plus complexes, dans lesquels des données pertinentes doivent être extraites de documents (par exemple, pour capturer des données de documents papier dans des systèmes d’information et des bases de données, ou pour classer et indexer automatiquement des documents dans des systèmes de gestion documentaire). Dans ce scénario, le système reconnaît soit plusieurs lignes de texte dans certains champs seulement, soit l’intégralité du texte sur une image de petite taille. Le système calcule un indice de confiance pour chaque caractère reconnu. Les indices de confiance peuvent ensuite être utilisés lors de la vérification des résultats de reconnaissance. En outre, le système peut stocker plusieurs variantes de reconnaissance pour les mots et les caractères du texte, qui peuvent ensuite être utilisées dans des algorithmes de vote afin d’améliorer la qualité de la reconnaissance. Le traitement de petits fragments de texte dans ce scénario diffère à certains égards des étapes correspondantes dans d’autres scénarios :
  1. Prétraitement des images numérisées ou des photos
Les images à reconnaître peuvent inclure des marquages et du bruit de fond, qui peuvent tous deux nuire à la reconnaissance. C’est pourquoi tout marquage indésirable et tout bruit de fond sont supprimés à cette étape.
  1. Reconnaissance de petits fragments de texte
Lors de la reconnaissance de petits fragments de texte, le type de données à reconnaître est connu à l’avance. Par conséquent, la qualité de la reconnaissance peut être améliorée grâce à l’utilisation de dictionnaires externes, d’expressions régulières, de langues de reconnaissance et d’alphabets personnalisés, ainsi qu’en imposant des restrictions sur le nombre de caractères dans une chaîne. Les champs de texte peuvent contenir du texte imprimé, manuscrit en lettres détachées et manuscrit cursif.
  1. Travail avec les données reconnues
Ce scénario exige une précision de reconnaissance maximale afin de réduire au minimum le travail de vérification des données. Le système peut calculer un indice de confiance pour chaque mot ou caractère reconnu et fournir plusieurs variantes de reconnaissance, parmi lesquelles plusieurs Engines peuvent ensuite choisir le meilleur candidat en appliquant des algorithmes de vote.

Mise en œuvre du scénario

Les exemples de code fournis dans cette section sont spécifiques à Windows.
Vous trouverez ci-dessous une description détaillée de la méthode recommandée pour utiliser ABBYY FineReader Engine 12 dans ce scénario. Cette méthode repose sur les paramètres de traitement jugés les plus adaptés à ce scénario.
Pour commencer à utiliser ABBYY FineReader Engine, vous devez créer l’objet Engine. L’objet Engine est l’objet de plus haut niveau dans la hiérarchie des objets ABBYY FineReader Engine ; il fournit divers paramètres globaux, certaines méthodes de traitement, ainsi que des méthodes permettant de créer les autres objets.Pour créer l’objet Engine, vous pouvez utiliser la fonction InitializeEngine. Consultez également les autres façons de charger l’objet Engine (Win).

C#

public class EngineLoader : IDisposable
{
    public EngineLoader()
    {
        // Initialisez ces variables avec le chemin complet vers FREngine.dll, votre Customer Project ID,
        // et, le cas échéant, le chemin vers votre fichier de jeton de licence en ligne et le mot de passe de la licence en ligne
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // Chargement de la bibliothèque FREngine.dll
        dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
           
        try
        {
            if (dllHandle == IntPtr.Zero)
            {
                throw new Exception("Impossible de charger " + enginePath);
            }
            IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
            if (initializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Impossible de trouver la fonction InitializeEngine");
            }
            IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
            if (deinitializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Impossible de trouver la fonction DeinitializeEngine");
            }
            IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
            if (dllCanUnloadNowPtr == IntPtr.Zero)
            {
                throw new Exception("Impossible de trouver la fonction DllCanUnloadNow");
            }
            // Conversion des pointeurs en délégués
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // Appel de la fonction InitializeEngine
            // en transmettant le chemin vers le fichier de licence en ligne et le mot de passe de la licence en ligne
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // Libération de la bibliothèque FREngine.dll
            engine = null;
            // Suppression de tous les objets avant l'appel à FreeLibrary
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            FreeLibrary(dllHandle);
            dllHandle = IntPtr.Zero;
            initializeEngine = null;
            deinitializeEngine = null;
            dllCanUnloadNow = null;
            throw;
        }
    }
    // Fonctions 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);
    // Fonctions 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 privées
    private FREngine.IEngine engine = null;
    // Handle vers FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

C++ (COM)

// Initialisez ces variables avec le chemin vers FREngine.dll, votre Customer Project ID FineReader Engine,
// et, le cas échéant, le chemin vers le jeton de licence en ligne et le mot de passe de la licence en ligne
wchar_t* FreDllPath;
wchar_t* CustomerProjectId;
wchar_t* LicensePath;  // si vous n'utilisez pas de licence en ligne, affectez des chaînes vides à ces variables
wchar_t* LicensePassword;
// HANDLE vers FREngine.dll
static HMODULE libraryHandle = 0;
// Objet Engine FineReader global
FREngine::IEnginePtr Engine;
void LoadFREngine()
{
    if( Engine != 0 ) {
    // Déjà chargé
    return;
    }
    // Première étape : charger FREngine.dll
    if( libraryHandle == 0 ) {
        libraryHandle = LoadLibraryEx( FreDllPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH );
        if( libraryHandle == 0 ) {
            throw L"Erreur lors du chargement d'ABBYY FineReader Engine";
        }
    }
    // Deuxième étape : récupérer l'objet 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"Erreur lors du chargement d'ABBYY FineReader Engine";
    }
}
Les paramètres les plus adaptés peuvent être sélectionnés à l’aide de la méthode LoadPredefinedProfile de l’objet Engine. Cette méthode prend le nom du profil en paramètre d’entrée. Vous pouvez sélectionner les paramètres les plus adaptés en utilisant le profil prédéfini FieldLevelRecognition. Pour en savoir plus sur les profils, consultez Working with Profiles.

C#

// Charger un profil prédéfini
engine.LoadPredefinedProfile("FieldLevelRecognition");

C++ (COM)

// Charger un profil prédéfini
Engine->LoadPredefinedProfile( L"FieldLevelRecognition" );
Si vous souhaitez modifier les paramètres utilisés pour le traitement, utilisez les objets Parameter correspondants. Pour plus d’informations, consultez la section Optimisation supplémentaire ci-dessous.
ABBYY FineReader Engine fournit un objet FRDocument pour traiter les documents multipages. Pour charger les images d’un document et les prétraiter, vous devez créer l’objet FRDocument et y ajouter des images. Vous pouvez procéder de l’une des façons suivantes :

C#

// Créer l'objet FRDocument à partir d'un fichier image
FREngine.IFRDocument frDocument = engine.CreateFRDocumentFromImage( "C:\\MyImage.tif", null );

C++ (COM)

// Ouvrir un fichier image et créer l'objet FRDocument
FREngine::IFRDocumentPtr frDocument = Engine->CreateFRDocumentFromImage( L"C:\\MyImage.tif", 0 );
Vous devez maintenant créer des blocs contenant vos champs et, pour chacun d’eux, spécifier le type de bloc ainsi que les caractéristiques connues des données qu’il contient.Effectuez l’analyse de la mise en page du document à l’aide de la méthode Analyze, ou ajoutez manuellement des blocs contenant les champs que vous devez reconnaître. Consultez Working with Layout and Blocks pour savoir comment procéder.Pour chaque champ, vous pouvez désormais définir ses propres paramètres de reconnaissance. Par exemple, si un champ contient du texte, utilisez la propriété ITextBlock::RecognizerParams :
  • définissez le type de texte à l’aide de la propriété TextTypes de l’objet RecognizerParams. Par exemple, si le champ contient des chiffres écrits au format d’un code postal, utilisez le type de texte TT_Index.
  • définissez la langue à l’aide de la méthode SetPredefinedTextLanguage. L’utilisation de langues prédéfinies spéciales (Windows uniquement) peut être utile si vous connaissez le type d’informations contenues dans le champ. Par exemple, si le champ contient une adresse aux États-Unis, sélectionnez la langue prédéfinie English_US_Address. Cela garantit une reconnaissance plus fiable du texte.
  • définissez les propriétés SaveCharacterRecognitionVariants et SaveWordRecognitionVariants de l’objet RecognizerParams si vous devez utiliser les variantes de reconnaissance pour vérifier plus en détail le résultat, comme décrit ci-dessous à l’étape 6. Notez que ce paramètre n’est pas disponible pour les textes manuscrits ou écrits à la main en lettres détachées.
Pour plus de détails sur la reconnaissance de différents types de champs, consultez les sections Reconnaissance des coches, Reconnaissance de textes manuscrits, Recognizing Barcodes et Reconnaissance des mots comportant des espaces.

C#

// Analyser la mise en page du document
frDocument.Analyze( null, null, null );
// Supposons que nous sachions que le premier bloc
// de la mise en page contient une adresse aux États-Unis
FREngine.ITextBlock addressBlock = frDocument.Pages[0].Layout.Blocks[0].GetAsTextBlock();
FREngine.IRecognizerParams paramsAddressBlock = addressBlock.RecognizerParams;
paramsAddressBlock.SetPredefinedTextLanguage( "English_US_Address" );
// Activer la collecte des variantes de reconnaissance
paramsAddressBlock.SaveCharacterRecognitionVariants = true;
paramsAddressBlock.SaveWordRecognitionVariants = true;
// Configurer de la même manière les propriétés des autres blocs de la mise en page
...

C++ (COM)

// Analyser la mise en page du document
frDocument->Analyze( 0, 0, 0 );
// Supposons que nous sachions que le premier bloc
// de la mise en page contient une adresse aux États-Unis
FREngine::ILayoutBlocksPtr layoutBlocks = frDocument->Pages->Item( 0 )->Layout->Blocks;
FREngine::IRecognizerParamsPtr paramsAddressBlock = layoutBlocks->Item( 0 )->GetAsTextBlock()->RecognizerParams;
paramsAddressBlock->SetPredefinedTextLanguage( L"English_US_Address" );
// Activer la collecte des variantes de reconnaissance
paramsAddressBlock->SaveCharacterRecognitionVariants = VARIANT_TRUE;
paramsAddressBlock->SaveWordRecognitionVariants = VARIANT_TRUE;
// Configurer de la même manière les propriétés des autres blocs de la mise en page
...
Comme la mise en page du document a déjà été analysée et modifiée par vos soins, n’appelez pas de nouveau les méthodes d’analyse. Utilisez la méthode Recognize, qui effectue la reconnaissance et la synthèse des pages pour l’ensemble des pages du document. Dans ce scénario, vous devez extraire les données des champs et non exporter le document reconnu ; vous n’aurez donc pas besoin de la synthèse du document.

C#

// Reconnaître le document
// Il n'est pas nécessaire de spécifier des paramètres, car ils sont définis par le profil de traitement
frDocument.Recognize( null, null );

C++ (COM)

// Reconnaître le document
// Il n'est pas nécessaire de spécifier des paramètres, car ils sont définis par le profil de traitement
frDocument->Recognize( 0, 0 );
Utilisez l’objet Text pour accéder au fragment de texte reconnu (vous pouvez obtenir cet objet pour un bloc de texte via la propriété ITextBlock::Text). Utilisez la propriété Paragraphs pour obtenir la collection de paragraphes du fragment, ainsi que la méthode IParagraphs::Item pour accéder aux paragraphes individuels. La propriété IParagraph::Text donne accès au texte reconnu d’un paragraphe.Vous pouvez utiliser IParagraph::Words pour obtenir la collection de mots d’un paragraphe. Utilisez la méthode IWords::Item pour accéder aux mots individuels de la collection. La propriété IWord::Text renvoie la ligne qui contient le mot reconnu. Utilisez la méthode GetRecognitionVariants de l’objet Word ou la méthode GetWordRecognitionVariants de l’objet Paragraph pour obtenir les variantes de reconnaissance d’un mot.Les attributs de chaque caractère sont accessibles via la méthode GetCharParams de l’objet Paragraph. Cette méthode donne accès à l’objet CharParams, qui contient les paramètres du caractère reconnu. Les variantes de reconnaissance d’un caractère sont accessibles via la propriété ICharParams::CharacterRecognitionVariants.Pour des informations détaillées sur l’utilisation du texte, consultez Utilisation du texte. Pour en savoir plus sur l’utilisation de l’Engine dans les algorithmes de vote, consultez Utilisation de l’API Voting.Une fois que vous avez terminé de travailler avec l’objet FRDocument, libérez toutes les ressources utilisées par cet objet. Utilisez la méthode IFRDocument::Close.
Une fois que vous avez fini d’utiliser ABBYY FineReader Engine, vous devez décharger l’objet Engine. Pour cela, utilisez la fonction exportée DeinitializeEngine.

C#

public class EngineLoader : IDisposable
{
    // Décharger FineReader Engine
    public void Dispose()
    {
        if (engine == null)
        {
            // Engine n’a pas été chargé
            return;
        }
        engine = null;
        // Suppression de tous les objets avant l’appel à 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;
        // lever une exception après le nettoyage
        Marshal.ThrowExceptionForHR(hresult);
    }
    // Fonctions 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);
    // Fonctions 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 privées
    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;
}

C++ (COM)

void UnloadFREngine()
{
 if( libraryHandle == 0 ) {
  return;
 }
 // Libérer l’objet Engine
 Engine = 0;
 // Désinitialiser FineReader Engine
 typedef HRESULT ( STDAPICALLTYPE* DeinitializeEngineFunc )();
 DeinitializeEngineFunc pDeinitializeEngine =
  ( DeinitializeEngineFunc )GetProcAddress( libraryHandle, "DeinitializeEngine" );
 if( pDeinitializeEngine == 0 || pDeinitializeEngine() != S_OK ) {
  throw L"Erreur lors du déchargement d’ABBYY FineReader Engine";
 }
 // Il est maintenant possible de libérer la bibliothèque FREngine.dll en toute sécurité
 FreeLibrary( libraryHandle );
 libraryHandle = 0;
}

Ressources requises

Vous pouvez utiliser le fichier FREngineDistribution.csv pour créer automatiquement une liste des fichiers nécessaires au fonctionnement de votre application. Pour le traitement dans ce scénario, sélectionnez dans la colonne 5 (RequiredByModule) les valeurs suivantes : Core Core.Resources Opening Opening, Processing Processing Processing.OCR Processing.OCR, Processing.ICR Processing.OCR.NaturalLanguages Processing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguages Si vous modifiez le scénario standard, adaptez les modules requis en conséquence. Vous devez également spécifier les langues de l’interface, les langues de reconnaissance et toutes les fonctionnalités supplémentaires utilisées par votre application (par exemple, Opening.PDF si vous devez ouvrir des fichiers PDF, ou Processing.OCR.CJK si vous devez reconnaître des textes en langues CJK). Consultez Working with the FREngineDistribution.csv File pour plus de détails.

Optimisation supplémentaire

Voici les sections du fichier d’aide où vous trouverez des informations complémentaires sur la configuration des paramètres des différentes étapes de traitement :

Voir aussi

Implémentation de scénarios d’utilisation de base