Zum Hauptinhalt springen
Dieses Szenario ist nur für Windows verfügbar.
In diesem Szenario wird ABBYY FineReader Engine auf einem „Scancomputer“ verwendet, der Bilder scannt und als Dateien speichert. Dieses Szenario kann in einer frühen Phase der Dokumentverarbeitung als Teil anderer Szenarien verwendet werden, d. h. zum Erstellen elektronischer Versionen von Dokumenten für die weitere Verarbeitung. Einsatzbeispiele sind das Scannen von Dokumenten zu Archivierungszwecken, das Erstellen bearbeitbarer Versionen von Dokumenten und das Extrahieren bestimmter Daten aus Dokumenten. Papierdokumente werden gescannt, und die Bilder werden in einem elektronischen Format gespeichert. So entstehen hochwertige elektronische Versionen Ihrer gedruckten Dokumente. Dokumente können die folgenden Verarbeitungsstufen durchlaufen:
  1. Scannen
Dokumente können über eine der beiden von Scannern bereitgestellten Scan-Schnittstellen (TWAIN oder WIA), über die eigene Scan-Schnittstelle von ABBYY oder ohne Scan-Schnittstelle gescannt werden.
  1. Vorverarbeitung gescannter Bilder
Nach dem Scannen können die Bilder vorverarbeitet werden. Die Vorverarbeitung umfasst das Entfernen von Bildrauschen, die Korrektur verzerrter Textzeilen, die Farbinvertierung, das Entfernen schwarzer Ränder sowie die Korrektur der Bildausrichtung oder Auflösung. Doppelseiten können in zwei separate Bilder aufgeteilt werden. Verarbeitete Bilder können in verschiedenen Bildformaten wie JPEG, TIFF oder BMP gespeichert werden.

Implementierung des Szenarios

Im Folgenden finden Sie eine ausführliche Beschreibung der empfohlenen Vorgehensweise für den Einsatz von ABBYY FineReader Engine 12 in diesem Szenario. In der vorgeschlagenen Szenarioimplementierung entfällt die Phase der Bildvorbereitung. Hinweise zur Implementierung der Bildvorbereitung finden Sie weiter unten unter Zusätzliche Optimierung.
Um mit ABBYY FineReader Engine zu beginnen, müssen Sie das Engine-Objekt erstellen. Das Engine-Objekt ist das oberste Objekt in der Hierarchie der ABBYY FineReader Engine-Objekte und stellt verschiedene globale Einstellungen, einige Verarbeitungsmethoden sowie Methoden zum Erstellen anderer Objekte bereit.Zum Erstellen des Engine-Objekts können Sie die Funktion InitializeEngine verwenden. Siehe auch andere Möglichkeiten zum Laden des Engine-Objekts (Win).

C#

public class EngineLoader : IDisposable
{
    public EngineLoader()
    {
        // Initialisieren Sie diese Variablen mit dem vollständigen Pfad zu FREngine.dll, Ihrer Customer Project ID
        // und, falls zutreffend, dem Pfad zu Ihrer Online-Lizenz-Token-Datei und dem Online-Lizenz-Passwort
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // Laden Sie die Bibliothek 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");
            }
            // Konvertieren Sie Zeiger in Delegates
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // Rufen Sie die Funktion InitializeEngine auf 
            // und übergeben Sie den Pfad zur Online-Lizenz-Datei und das Online-Lizenz-Passwort
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // Geben Sie die Bibliothek FREngine.dll frei
            engine = null;
            // Alle Objekte vor dem Aufruf von FreeLibrary löschen
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            FreeLibrary(dllHandle);
            dllHandle = IntPtr.Zero;
            initializeEngine = null;
            deinitializeEngine = null;
            dllCanUnloadNow = null;
            throw;
        }
    }
    // Funktionen aus 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);
    // Funktionen aus 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();
    // private Variablen
    private FREngine.IEngine engine = null;
    // Handle für FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}
ABBYY FineReader Engine stellt ein ScanManager-Objekt zur Verwaltung der Scanquellen bereit. Die Eigenschaft ScanSources dieses Objekts ermöglicht den Zugriff auf die Liste aller verfügbaren Scanner, während die Methode FindScanSources es Ihnen erlaubt, Scanner nach dem bereitgestellten API-Typ und dem gewünschten Benutzeroberflächentyp zum Festlegen der Scanoptionen auszuwählen.Um die Dateien zu scannen und auf dem Datenträger zu speichern, können Sie eine der beiden folgenden Methoden des ScanSource-Objekts verwenden: die Methode Scan, die erst zurückkehrt, wenn der Scanvorgang abgeschlossen ist, und die Methode BeginScan, die den asynchronen Scanvorgang startet und sofort zurückkehrt.Sie können die Schnittstelle IScanCallback implementieren und damit Benachrichtigungen über den Fortschritt des Scanvorgangs erhalten.Über die ABBYY FineReader Engine 12 API sind folgende Parameter zugänglich: Helligkeit, Farbe, Auflösung, Bildkomprimierungstyp, Bildrotationswinkel, Größe des Scanbereichs, Duplex-Scanmodus, automatischer Einzugsmodus, eine Pause zwischen den Seiten und weitere. Die Scan-Parameter werden über die Eigenschaft ScanSettings des ScanSource-Objekts festgelegt. Diese Eigenschaft ist erforderlich, um auf das Objekt ScanSourceSettings zuzugreifen, das wiederum den Zugriff auf die Scan-Einstellungen einer Quelle ermöglicht.So scannen Sie die Bilder synchron:
  1. Erstellen Sie ein ScanManager-Objekt. Über den Eingabeparameter der Methode CreateScanManager können Sie festlegen, ob Scanprotokolle geschrieben werden.
  2. Wählen Sie die Scanquelle mit der FindScanSources-Methode des ScanManager-Objekts aus und geben Sie dabei den API- und UI-Typ an, der vom Scanner unterstützt werden soll.
  3. Wenn Sie festlegen, dass dem Benutzer kein Dialogfeld zum manuellen Einstellen der Scanoptionen angezeigt wird, konfigurieren Sie die Scanoptionen über die Eigenschaft ScanSettings der ausgewählten ScanSource. Wählen Sie die passenden Werte für Helligkeit, Auflösung und die übrigen Parameter in den entsprechenden Eigenschaften des Objekts ScanSourceSettings aus. Über die Eigenschaft Capabilities von ScanSource können Sie prüfen, welche Einstellungen für diesen Scanner verfügbar sind.
  4. Geben Sie den Namen des Ordners an, in dem gescannte Seiten gespeichert werden. Der Ordnername sollte eine BSTR-Variable sein, beispielsweise ScanFolder.
  5. Führen Sie die Scan-Methode des ScanSource-Objekts aus und geben Sie als Parameter den Typ des Dialogfelds an, das dem Benutzer angezeigt werden soll (übergeben Sie die Konstante SSUIT_None, damit kein Dialogfeld angezeigt wird), sowie den ScanFolder-Pfad zum Ordner mit den Ergebnissen.
  6. Die Bilddateinamen werden von dieser Methode als StringsCollection-Objekt zurückgegeben. Sie können die Bilddateinamen aus diesem StringsCollection-Objekt abrufen und die Dateien anschließend wie normale Bilddateien verarbeiten.
So scannen Sie die Bilder asynchron:
  1. Erstellen Sie ein Objekt, das die Schnittstelle IScanCallback implementiert. Bei asynchronen Scanvorgängen sind Benachrichtigungen über die Callback-Schnittstelle sehr nützlich.
  2. Erstellen Sie ein ScanManager-Objekt. Über den Eingabeparameter der Methode CreateScanManager können Sie angeben, ob Scanprotokolle geschrieben werden sollen.
  3. Wählen Sie die Scanquelle mit der Methode FindScanSources des ScanManager-Objekts aus und geben Sie dabei den API- und UI-Typ an, der vom Scanner unterstützt werden muss.
  4. Wenn Sie kein Dialogfeld anzeigen möchten, in dem der Benutzer die Scaneinstellungen selbst festlegen kann, passen Sie die Scaneinstellungen mithilfe der Eigenschaft ScanSettings der ausgewählten ScanSource an. Wählen Sie die passenden Werte für Helligkeit, Auflösung und die anderen Parameter in den entsprechenden Eigenschaften des ScanSourceSettings-Objekts aus. Sie können über die Eigenschaft Capabilities der ScanSource prüfen, welche Einstellungen für diesen Scanner verfügbar sind.
  5. Geben Sie den Namen des Ordners an, in dem gescannte Seiten gespeichert werden. Der Ordnername sollte eine BSTR-Variable sein, z. B. ScanFolder.
  6. Rufen Sie die Methode BeginScan des ScanSource-Objekts auf und übergeben Sie als Parameter den Typ des Dialogfelds, das dem Benutzer angezeigt werden soll (übergeben Sie die Konstante SSUIT_None, damit kein Dialogfeld angezeigt wird), sowie den ScanFolder-Pfad zum Ordner mit den Ergebnissen. Außerdem müssen Sie den Zeiger auf das von Ihnen erstellte Callback-Objekt übergeben.
  7. Der Pfad zur Bilddatei wird mit der Benachrichtigung OnImageScanned der Schnittstelle IScanCallback zurückgegeben; der Abschluss des Vorgangs wird durch die Benachrichtigung OnScanComplete signalisiert. Da Sie die Implementierung dieser Methoden bereitstellen, können Sie festlegen, was in jeder dieser Situationen geschehen soll. Wenn Sie beispielsweise den Pfad zu einer Bilddatei erhalten, können Sie damit wie mit jeder anderen Datei auf der Festplatte arbeiten und sie wie gewohnt zur Verarbeitung mit FineReader Engine laden.
Bis der Scanvorgang abgeschlossen ist und die Benachrichtigung OnScanComplete eingegangen ist, können Sie BeginScan oder Scan nicht erneut ausführen, auch nicht für einen anderen Scanner. Der Vorteil des asynchronen Scannens besteht nicht darin, dass Sie mehrere Scanvorgänge gleichzeitig ausführen können, sondern darin, dass Sie die bereits empfangenen Bilder verarbeiten können, während neue Bilder gescannt werden.
Hier ist ein Beispielcode für das asynchrone Scanning-Szenario:

C#

// IScanCallback-Schnittstelle implementieren
class ScanningCallback :FREngine.IScanCallback
{
  // Konstruktor
  public ScanningCallback() {}
  ...
  // Implementierung der IScanCallback-Methoden bereitstellen
  public void OnError(string sourceName, string message) { // Fehler hier melden oder behandeln }
  public void OnImageScanned(string sourceName, string Path, ref bool cancel) { // hier die gewünschten Aktionen beim Scannen eines Bildes einfügen }
  public void OnScanComplete() { // hier eine Aktion einfügen, die nach Abschluss des Scannens ausgeführt werden soll }
  // private Variablen
  ...
}
// Scan-Manager erstellen, mit deaktivierten Protokollen
scanManager = engineLoader.Engine.CreateScanManager(false);
// Liste der Scanquellen erstellen, gefiltert nach API- und UI-Typ
FREngine.IScanSources sources = scanManager.FindScanSources(UIType, APIType);
// Zur Veranschaulichung die erste Scanquelle aus der Sammlung auswählen
FREngine.IScanSource selectedSource = sources[0];
// Auf Einstellungen und Funktionen der Scanquelle zugreifen
FREngine.IScanSourceSettings settings = selectedSource.ScanSettings;
FREngine.IScanSourceCapabilities capabilities = selectedSource.Capabilities;
// Scanoptionen auf Duplexmodus setzen, sofern der Scanner diesen unterstützt
settings.DuplexMode = capabilities.HasDuplexMode;
// Optionen für mehrseitiges Scannen und 10-Sekunden-Verzögerung zwischen den Seiten festlegen
settings.MultipleImagesEnabled = true;
settings.PauseBetweenPagesMode = FREngine.ScanPauseModeEnum.SPM_PresetDelay;
settings.Delay = 10;
// Pfad zum Ergebnisordner festlegen
string scanFolder = "D:\\SampleImages";
// Callback-Objekt erstellen
IScanningCallback callback = new ScanningCallback();
// Scanvorgang starten
selectedSource.BeginScan(SSUIT_None, scanFolder, callback);
Nachdem Sie die Arbeit mit ABBYY FineReader Engine abgeschlossen haben, müssen Sie das Engine-Objekt entladen. Verwenden Sie dazu die exportierte Funktion DeinitializeEngine.

C#

public class EngineLoader : IDisposable
{
    // FineReader Engine entladen
    public void Dispose()
    {
        if (engine == null)
        {
            // Engine wurde nicht geladen
            return;
        }
        engine = null;
        // Vor dem Aufruf von FreeLibrary alle Objekte freigeben
        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;
        // Nach dem Bereinigen eine Ausnahme auslösen
        Marshal.ThrowExceptionForHR(hresult);
    }
    // Funktionen aus 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);
    // Funktionen aus 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();
    // private Variablen
    private FREngine.IEngine engine = null;
    // Handle für FREngine.dll
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

Erforderliche Ressourcen

Sie können die Datei FREngineDistribution.csv verwenden, um automatisch eine Liste der Dateien zu erstellen, die für die Funktionsfähigkeit Ihrer Anwendung erforderlich sind. Wählen Sie für die Verarbeitung in diesem Szenario in Spalte 5 (RequiredByModule) die folgenden Werte aus: Core Core.Resources Opening Opening, Processing Opening.Scanning Wenn Sie das Standardszenario ändern, passen Sie die erforderlichen Module entsprechend an. Sie müssen außerdem die Oberflächensprachen, Erkennungssprachen und alle zusätzlichen Funktionen angeben, die Ihre Anwendung verwendet (z. B. Processing.OCR.CJK, wenn Sie Texte in CJK-Sprachen erkennen müssen). Weitere Einzelheiten finden Sie unter Working with the FREngineDistribution.csv File.

Zusätzliche Optimierung

Dies sind die Abschnitte der Hilfedatei, in denen Sie weitere Informationen zum Einrichten der Parameter für die verschiedenen Verarbeitungsstufen finden:
  • Dokumententrennung
    • In diesem Szenario müssen Sie den eingehenden Bildstrom möglicherweise zu Dokumenten gruppieren. Beispielsweise kennen Sie eventuell die Seitenanzahl jedes Dokuments oder stellen sicher, dass sich zwischen der letzten Seite des ersten Dokuments und der ersten Seite des nächsten Dokuments Trennseiten mit Barcodes befinden. Weitere Informationen finden Sie im Szenario zur Barcode-Erkennung.

Siehe auch

Implementierung grundlegender Anwendungsszenarien