Passer au contenu principal
Ce scénario est disponible uniquement sous Windows.
Dans ce scénario, ABBYY FineReader Engine est utilisé sur un « poste de numérisation », qui numérise les images et les enregistre sous forme de fichiers. Ce scénario peut être utilisé dans le cadre d’autres scénarios à l’étape préliminaire du traitement des documents, c’est-à-dire pour obtenir des versions électroniques de documents en vue d’un traitement ultérieur. Parmi les exemples d’utilisation figurent la numérisation de documents à des fins d’archivage, l’obtention de versions modifiables de documents et l’extraction de données spécifiques à partir de documents. Les documents papier sont numérisés et les images sont enregistrées dans un format électronique, ce qui permet d’obtenir des versions électroniques de haute qualité de vos documents imprimés. Les documents peuvent passer par les étapes de traitement suivantes :
  1. Numérisation
Les documents peuvent être numérisés via l’une des deux interfaces de numérisation proposées par les scanners (TWAIN ou WIA), à l’aide de l’interface de numérisation d’ABBYY, ou sans interface de numérisation.
  1. Prétraitement des images numérisées
Une fois numérisées, les images peuvent être prétraitées. Le prétraitement comprend la suppression des points parasites, la correction des lignes de texte déformées, l’inversion des couleurs, la suppression des marges noires et la correction de l’orientation ou de la résolution de l’image. Les doubles pages peuvent être divisées en deux images distinctes. Les images traitées peuvent être enregistrées dans différents formats d’image tels que JPEG, TIFF ou BMP.

Mise en œuvre du scénario

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. Dans l’implémentation proposée, la phase de préparation des images n’est pas incluse. Veuillez consulter Optimisation supplémentaire ci-dessous pour obtenir des conseils sur la mise en œuvre de la préparation des images.
Pour commencer à utiliser ABBYY FineReader Engine, vous devez créer l’objet Engine. L’objet Engine est l’objet racine de la hiérarchie des objets d’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. Voir aussi d’autres méthodes pour 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 ainsi que le mot de passe de la licence en ligne
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // Charger la bibliothèque 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");
            }
            // Convertir les 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));
            // Appeler la fonction InitializeEngine 
            // en lui transmettant le chemin du 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érer la bibliothèque FREngine.dll
            engine = null;
            // Supprimer 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 de FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}
ABBYY FineReader Engine propose un objet ScanManager pour gérer les sources de numérisation. La propriété ScanSources de cet objet donne accès à la liste de tous les scanners disponibles, tandis que la méthode FindScanSources permet de sélectionner les scanners selon le type d’API qu’ils exposent et le type d’interface utilisateur à utiliser pour configurer les options de numérisation.Pour numériser et enregistrer les fichiers sur le disque, vous pouvez utiliser l’une des deux méthodes de l’objet ScanSource : la méthode Scan, qui ne rend pas la main tant que la numérisation n’est pas terminée, et la méthode BeginScan, qui démarre l’opération de numérisation asynchrone et rend la main immédiatement.Vous pouvez implémenter l’interface IScanCallback et l’utiliser pour recevoir des notifications sur la progression de la numérisation.Les paramètres suivants sont accessibles via l’API ABBYY FineReader Engine 12 : luminosité, couleur, résolution, type de compression d’image, angle de rotation de l’image, taille de la zone de numérisation, mode de numérisation recto-verso, mode d’alimentation automatique, pause entre les pages, et bien d’autres. Les paramètres de numérisation sont définis à l’aide de la propriété ScanSettings de l’objet ScanSource. Cette propriété est nécessaire pour accéder à l’objet ScanSourceSettings, qui donne à son tour accès aux paramètres de numérisation d’une source.Pour analyser les images de façon synchrone :
  1. Créez un objet ScanManager. Vous pouvez préciser si les journaux de numérisation doivent être enregistrés via le paramètre d’entrée de la méthode CreateScanManager.
  2. Sélectionnez la source de numérisation à l’aide de la méthode FindScanSources de l’objet ScanManager, en indiquant le type d’API et d’interface utilisateur pris en charge par le scanner.
  3. Si vous choisissez de ne pas afficher de boîte de dialogue afin que l’utilisateur définisse lui-même les options de numérisation, réglez ces options à l’aide de la propriété ScanSettings du ScanSource sélectionné. Sélectionnez les valeurs appropriées pour la luminosité, la résolution et les autres paramètres dans les propriétés correspondantes de l’objet ScanSourceSettings. Vous pouvez vérifier quels paramètres sont disponibles pour ce scanner à l’aide de la propriété Capabilities du ScanSource.
  4. Indiquez le nom du dossier dans lequel les pages numérisées seront stockées. Le nom du dossier doit être une variable BSTR, par exemple ScanFolder.
  5. Exécutez la méthode Scan de l’objet ScanSource, en indiquant en paramètre le type de boîte de dialogue à afficher à l’utilisateur (passez la constante SSUIT_None pour n’afficher aucune boîte de dialogue), ainsi que le chemin ScanFolder vers le dossier contenant les résultats.
  6. Les noms des fichiers image seront renvoyés par cette méthode sous la forme d’un objet StringsCollection. Vous pouvez récupérer les noms des fichiers image à partir de cet objet StringsCollection, puis traiter ces fichiers comme des fichiers image ordinaires.
Pour analyser les images de façon asynchrone :
  1. Créez un objet qui implémente l’interface IScanCallback. Dans le cadre d’une opération de numérisation asynchrone, les notifications envoyées via cette interface de rappel sont très utiles.
  2. Créez un objet ScanManager. Vous pouvez indiquer si les journaux de numérisation doivent être consignés via le paramètre d’entrée de la méthode CreateScanManager.
  3. Sélectionnez la source de numérisation à l’aide de la méthode FindScanSources de l’objet ScanManager, en précisant le type d’API et d’interface utilisateur pris en charge par le scanner.
  4. Si vous choisissez de ne pas afficher de boîte de dialogue afin que l’utilisateur puisse définir lui-même les options de numérisation, configurez ces options à l’aide de la propriété ScanSettings du ScanSource sélectionné. Sélectionnez les valeurs appropriées pour la luminosité, la résolution et les autres paramètres dans les propriétés correspondantes de l’objet ScanSourceSettings. Vous pouvez vérifier quels paramètres sont pris en charge par ce scanner à l’aide de la propriété Capabilities du ScanSource.
  5. Indiquez le nom du dossier dans lequel les pages numérisées seront enregistrées. Le nom du dossier doit être une variable BSTR, par exemple ScanFolder.
  6. Exécutez la méthode BeginScan de l’objet ScanSource, en indiquant comme paramètre le type de boîte de dialogue à afficher à l’utilisateur (passez la constante SSUIT_None pour ne pas afficher de boîte de dialogue), ainsi que le chemin ScanFolder vers le dossier contenant les résultats. Vous devez également passer le pointeur vers l’objet de rappel que vous avez créé.
  7. Le chemin d’accès au fichier image est renvoyé avec la notification OnImageScanned de l’interface IScanCallback, et la fin de l’opération est signalée par la notification OnScanComplete. Comme vous implémentez ces méthodes, vous pouvez choisir ce qu’il convient de faire dans chacune de ces situations. Par exemple, lorsque vous recevez le chemin d’accès à un fichier image, vous pouvez le traiter comme n’importe quel autre fichier du disque en le chargeant pour le traiter avec FineReader Engine de la manière habituelle.
Tant que la numérisation n’est pas terminée et que vous n’avez pas reçu la notification OnScanComplete, vous ne pouvez pas exécuter BeginScan ni Scan à nouveau, même avec un autre scanner. L’avantage de la numérisation asynchrone n’est pas de pouvoir effectuer plusieurs opérations de numérisation simultanément, mais de pouvoir traiter les images déjà reçues pendant que les nouvelles sont en cours de numérisation.
Voici un exemple de code pour le scénario de numérisation asynchrone :

C#

// Implémenter l'interface IScanCallback
class ScanningCallback :FREngine.IScanCallback
{
  // constructeur
  public ScanningCallback() {}
  ...
  // fournir l'implémentation des méthodes IScanCallback
  public void OnError(string sourceName, string message) { // signaler ou gérer l'erreur ici }
  public void OnImageScanned(string sourceName, string Path, ref bool cancel) { // insérer ici toute action à effectuer lors de la numérisation d'une image }
  public void OnScanComplete() { // insérer ici une action à effectuer une fois la numérisation terminée }
  // variables privées
  ...
}
// Créer le gestionnaire de numérisation, avec la journalisation désactivée
scanManager = engineLoader.Engine.CreateScanManager(false);
// Créer une liste de sources de numérisation filtrées par type d'API et d'interface utilisateur
FREngine.IScanSources sources = scanManager.FindScanSources(UIType, APIType);
// À titre d'exemple, sélectionner la première source de numérisation de la collection
FREngine.IScanSource selectedSource = sources[0];
// Accéder aux paramètres et aux fonctionnalités de la source de numérisation
FREngine.IScanSourceSettings settings = selectedSource.ScanSettings;
FREngine.IScanSourceCapabilities capabilities = selectedSource.Capabilities;
// Activer le mode recto-verso si le scanner le prend en charge
settings.DuplexMode = capabilities.HasDuplexMode;
// Activer la numérisation multi-pages et définir un délai de 10 secondes entre les pages
settings.MultipleImagesEnabled = true;
settings.PauseBetweenPagesMode = FREngine.ScanPauseModeEnum.SPM_PresetDelay;
settings.Delay = 10;
// Définir le chemin vers le dossier de résultats
string scanFolder = "D:\\SampleImages";
// Créer un objet de rappel
IScanningCallback callback = new ScanningCallback();
// Démarrer la numérisation
selectedSource.BeginScan(SSUIT_None, scanFolder, callback);
Une fois que vous avez fini d’utiliser ABBYY FineReader Engine, vous devez décharger l’objet Engine. Pour ce faire, 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;
        // déclencher 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;
}

Ressources nécessaires

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 Opening.Scanning Si vous modifiez le scénario standard, adaptez les modules requis en conséquence. Vous devez également spécifier les langues d’interface, les langues de reconnaissance et toutes les fonctionnalités supplémentaires utilisées par votre application (par exemple, 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 le paramétrage des différentes étapes de traitement :
  • Séparation des documents
    • Dans ce scénario, vous devrez peut-être regrouper le flux d’images entrant en documents. Par exemple, vous pouvez connaître le nombre de pages de chaque document, ou vous assurer de la présence de pages séparatrices avec des codes-barres entre la dernière page du premier document et la première page du document suivant. Consultez le scénario de reconnaissance de codes-barres.

Voir aussi

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