Zum Hauptinhalt springen
Ziel der Dokumentklassifizierung ist es, Dokumente verschiedenen vordefinierten Kategorien zuzuordnen. Das ist besonders nützlich, wenn Sie es mit einem Dokumentenfluss zu tun haben, der Dokumente unterschiedlicher Typen enthält, und den Typ jedes Dokuments bestimmen müssen. So möchten Sie beispielsweise Verträge, Rechnungen und Belege in verschiedene Ordner sortieren oder je nach Typ umbenennen. Dies lässt sich mit einem vortrainierten System automatisch erledigen. Eine der Haupteigenschaften der Dokumentklassifizierung besteht darin, dass Sie die zu unterscheidenden Dokumenttypen im Voraus kennen. ABBYY FineReader Engine kann Dokumente anhand ihres Inhalts oder anhand von Bildmerkmalen klassifizieren oder sowohl die Merkmale des erkannten Textes als auch des Bildes berücksichtigen. Betrachten wir den Prozess im Detail. Er besteht aus zwei Hauptschritten:
  1. Erstellen einer Klassifizierungsdatenbank
Wählen Sie für jede Kategorie mehrere typische Dokumente oder Seiten aus. Diese werden zum Erstellen der Klassifizierungsdatenbank verwendet.
  1. Klassifizieren von Dokumenten
Die im vorherigen Schritt erstellte Datenbank kann zur Klassifizierung von Dokumenten verwendet werden. Eingehende Dokumente werden einem vortrainierten Klassifizierungssystem zugeführt, das anhand der Klassifizierungsdatenbank die jeweilige Kategorie bestimmt. Unter Umständen müssen Sie Dokumente auch anhand bestimmter Attribute klassifizieren, z. B. nach Autor oder Barcode-Wert. Dieser Artikel behandelt diese Art der Klassifizierung nicht. Wenn Sie Dokumente anhand ihrer Attribute klassifizieren möchten, sollten Sie eigene Algorithmen implementieren, die zur Datenextraktion Textextraktion, Erkennung auf Feldebene oder Barcode-Erkennung verwenden können. Das unten beschriebene Verfahren wird außerdem durch das Demo-Tool Classification für Windows und das Codebeispiel Classification für Linux und macOS veranschaulicht.

Implementierung des Szenarios

Die in diesem Thema bereitgestellten Codebeispiele sind spezifisch für Windows.
Im Folgenden wird die empfohlene Methode zur Verwendung von ABBYY FineReader Engine zur Dokumentklassifizierung ausführlich beschrieben.
Um mit ABBYY FineReader Engine zu beginnen, müssen Sie das Objekt Engine 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 gegebenenfalls mit dem Pfad zu Ihrer Online License-Token-Datei und dem Online License-Passwort
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // FREngine.dll-Bibliothek laden
        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");
            }
            // Zeiger in Delegaten konvertieren
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // Funktion InitializeEngine aufrufen 
            // und dabei den Pfad zur Online License-Datei und das Online License-Passwort übergeben
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // FREngine.dll-Bibliothek freigeben
            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;
}
Erstellen Sie ein ClassificationEngine-Objekt, das als Factory für andere Objekte der Classification API dient. Verwenden Sie dafür die Methode CreateClassificationEngine des Engine-Objekts.

C#

FREngine.IEngine engine;
FREngine.IClassificationEngine classEngine = engine.CreateClassificationEngine();
Die Trainings- und Klassifizierungsmethoden arbeiten mit einem speziellen Objekttyp, der aus einem Dokument oder einer Seite erstellt wird: ClassificationObject, das alle für die Klassifizierung relevanten Informationen enthält.Gehen Sie wie folgt vor, um ein Dokument für die Verwendung in einem Klassifizierungsszenario vorzubereiten:
  1. Laden Sie die zu verarbeitenden Bilder. Dafür gibt es mehrere Möglichkeiten: Sie können beispielsweise das Objekt FRDocument mithilfe der Methode CreateFRDocument des Engine-Objekts erstellen und dann mit der Methode AddImageFile Bilder aus einer Datei zum erstellten FRDocument-Objekt hinzufügen.
  2. Wenn Sie einen Klassifikator trainieren oder verwenden möchten, der Textmerkmale berücksichtigt (CT_Combined, CT_Text), erkennen Sie das Dokument zunächst mit einer geeigneten Methode. Wir verwenden die Methoden Analyze und Recognize des Objekts FRDocument. Eine Dokumentensynthese ist für die Klassifizierung nicht erforderlich.
Obwohl die Parallelverarbeitung für die Klassifizierung selbst nicht unterstützt wird, benötigen Sie sie möglicherweise für die vorbereitende Erkennung von Dokumenten unter Windows und Linux. Wenn Sie eine große Anzahl von Dokumenten klassifizieren möchten, empfehlen wir die Verwendung von Batch Processor oder anderen Methoden zur Parallelverarbeitung, die unter Parallel Processing with ABBYY FineReader Engine beschrieben sind.
  1. Verwenden Sie die Methode CreateObjectFromDocument des Objekts ClassificationEngine, um ein ClassificationObject zu erstellen, das die Informationen der ersten Seite des Dokuments enthält. Wenn Sie eine andere Seite des Dokuments verwenden möchten, rufen Sie die Methode CreateObjectFromPage auf.
  2. Die Eigenschaft Description des ClassificationObject ist standardmäßig leer. Geben Sie diese Eigenschaft an, wenn Sie eine aussagekräftige Beschreibung benötigen.
Es kann gelegentlich vorkommen, dass das erkannte Dokument oder die erkannte Seite dennoch keinen erkannten Text enthält (zum Beispiel, wenn versehentlich eine leere Seite verwendet wurde). In diesem Fall kann das ClassificationObject nicht für Klassifikatoren verwendet werden, die Textmerkmale erfordern. Sie können die Eigenschaft SuitableClassifiers zur zusätzlichen Überprüfung verwenden.

C#

// Das FRDocument-Objekt erstellen
FREngine.IFRDocument frDocument = engine.CreateFRDocument();
// Die Bilder hinzufügen
frDocument.AddImageFile( "C:\\MyImage.tif", null, null );
// Optional: das Dokument analysieren und erkennen
frDocument.Analyze( null, null, null );
frDocument.Recognize( null, null );
// Das Klassifizierungsobjekt erstellen
FREngine.IClassificationObject clObject = classEngine.CreateObjectFromDocument( frDocument );
// Die Kategorie, zu der das Objekt gehört, in die Beschreibung eintragen
clObject.Description = "CategoryA_Object1";
Um einen Klassifikator zu trainieren, der zwischen mehreren Dokumenttypen unterscheiden kann, benötigen Sie einen kategorisierten Datensatz, der Beispiele für jeden Typ enthält. Verwenden Sie das Objekt TrainingData, um diesen Datensatz aufzubauen und zu verwalten:
  1. Erstellen Sie mithilfe der Methode CreateTrainingData des ClassificationEngine-Objekts ein leeres Objekt.
  2. Greifen Sie über die Eigenschaft Categories auf die Kategoriensammlung zu.
  3. Verwenden Sie die Methode AddNew des Objekts Categories mehrmals, um für jeden Dokumenttyp, den Sie klassifizieren möchten, eine Kategorie hinzuzufügen. Die Methode erwartet als Eingabeparameter einen string mit der Kategorienbezeichnung. Diese Bezeichnung wird von den Klassifizierungsmethoden zurückgegeben und muss daher innerhalb der Kategoriensammlung eindeutig sein.
  4. Öffnen Sie für jedes neu hinzugefügte Objekt Category über die Eigenschaft Objects die Sammlung der Klassifizierungsobjekte. Fügen Sie mithilfe der Methode IClassificationObjects::Add die Klassifizierungsobjekte hinzu, die zu dieser Kategorie gehören.
    Keine Kategorie darf leer bleiben. Aus offensichtlichen Gründen sind für das Training mindestens zwei Kategorien erforderlich.
  5. Nachdem Sie den Trainingsdatensatz eingerichtet haben, können Sie ihn zur späteren Verwendung in einer Datei auf der Festplatte speichern, etwa wenn sich die Genauigkeit des trainierten Modells als unzureichend erweist und Sie zur Verbesserung der Qualität Daten hinzufügen oder korrigieren möchten. Das Objekt TrainingData stellt dazu die Methode SaveToFile bereit.

C#

FREngine.ITrainingData trainingData = classEngine.CreateTrainingData();
FREngine.ICategories categories = trainingData.Categories;
// Die erste Kategorie hinzufügen
FREngine.ICategory category = categories.AddNew( "CategoryA" );
// Die in Schritt 3 vorbereiteten Klassifizierungsobjekte hinzufügen
category.Objects.Add( clObject ); // für alle Objekte aus dieser Kategorie wiederholen
...
// Für alle Kategorien wiederholen
...
// Nachdem alle Kategorien hinzugefügt wurden, den Trainingsdatensatz speichern
trainingData.SaveToFile( "C:\\trainingData.dat" );
Die Funktionalität für das Modelltraining wird vom Trainer-Objekt bereitgestellt. Verwenden Sie die CreateTrainer-Methode des ClassificationEngine-Objekts, um es zu erstellen.Es enthält alle Einstellungen für den Klassifikatortyp und das Trainingsverfahren in zwei Unterobjekten: TrainingParams und ValidationParams. Legen Sie fest, welche Einstellungen Sie benötigen, und passen Sie die entsprechenden Eigenschaften an:
  • Der Typ des Klassifikators (ITrainingParams::ClassifierType). Diese Einstellung legt fest, welche Merkmale des Dokuments bei der Kategorisierung berücksichtigt werden: Bildeigenschaften, der Inhalt des erkannten Textes oder beides. Wenn Sie einen Typ auswählen möchten, der den Textinhalt nutzt, müssen Sie sicherstellen, dass alle Klassifizierungsobjekte im Trainingsdatensatz aus zuvor erkannten Dokumenten erstellt wurden.
  • Der Trainingsmodus (ITrainingParams::TrainingMode). Diese Einstellung legt fest, ob der Trainingsprozess auf hohe Präzision (wie viele der ausgewählten Elemente korrekt sind), hohe Trefferquote (wie viele der korrekten Elemente ausgewählt werden) oder ein ausgewogenes Verhältnis zwischen beiden ausgerichtet sein soll.
  • Ob eine k-fache Kreuzvalidierung verwendet werden soll (IValidationParams::ShouldPerformValidation). Wir empfehlen, die Kreuzvalidierung zu verwenden, wenn Ihre Trainingsstichprobe nicht groß ist, da Sie damit mehrere Modelle auf den verschiedenen Partitionen derselben Stichprobe trainieren und das beste auswählen können. Wenn Ihnen eine große Menge kategorisierter Daten zur Verfügung steht, ist es möglicherweise besser, die Validierung zu deaktivieren, das Modell mit der gesamten Trainingsstichprobe zu trainieren und anschließend die Klassifizierungsmethoden (Schritt 6) zu verwenden, um das Modell an einer anderen Stichprobe zu testen und die Leistungskennzahlen selbst zu berechnen.
  • Die Parameter der k-fachen Kreuzvalidierung: die Anzahl der Teile, in die die Trainingsmenge aufgeteilt wird (IValidationParams::FoldsCount), und die Anzahl der Iterationen (IValidationParams::RepeatCount). Beachten Sie, dass die erforderliche Anzahl von Objekten in der Trainingsmenge bei jeder Iteration für den Textklassifikator mindestens 4 und für den kombinierten Klassifikator mindestens 8 betragen muss. Stellen Sie sicher, dass Ihre Trainingsmenge genügend Objekte enthält.
Jetzt können Sie ein Modell trainieren. Übergeben Sie das in Schritt 4 konfigurierte TrainingData-Objekt an die Methode TrainModel des Trainer-Objekts. Diese gibt eine TrainingResults-Sammlung zurück, die mit der derzeit verfügbaren Funktionalität nur ein einziges TrainingResult enthält. Wenn Sie eine Kreuzvalidierung durchgeführt haben, überprüfen Sie die Leistungswerte im zugehörigen Unterobjekt ValidationResult.
Modelltraining und -klassifizierung werden unter Linux und Windows unabhängig vom Wert von IMultiProcessingParams::MultiProcessingMode im sequenziellen Modus durchgeführt.
Die Eigenschaft ITrainingResult::Model ermöglicht den Zugriff auf das trainierte Klassifizierungsmodell. Sie können es mithilfe der Methode SaveToFile in einer Datei speichern oder es direkt zur Klassifizierung von Dokumenten verwenden (weiter zu Schritt 6).

C#

// Trainer-Objekt erstellen und Parameter einrichten
FREngine.ITrainer trainer = classEngine.CreateTrainer();
trainer.TrainingParams.ClassifierType = (int)FREngine.ClassifierTypeEnum.CT_Image; // der Klassifikator verwendet ausschließlich die Bildmerkmale
// Die übrigen Einstellungen bleiben auf den Standardwerten; das Modell wird direkt trainiert
FREngine.ITrainingResults results = trainer.TrainModel ( trainingData );
// F1-Score des Modells prüfen
double F1 = results[0].ValidationResult.FMeasure;
// Klassifikationsmodell abrufen
FREngine.IModel model = results[0].Model;
// Modell zur späteren Verwendung speichern
model.SaveToFile( "C:\\model.dat" );
Um das trainierte Modell für die Klassifizierung zu verwenden:
  1. Wenn das Modell derzeit nicht geladen ist, rufen Sie die Methode CreateModelFromFile des Objekts ClassificationEngine auf, um es aus einer Datei auf dem Datenträger zu laden.
  2. Bereiten Sie die Klassifizierungsobjekte aus den Dokumenten vor, die Sie klassifizieren möchten, wie in Schritt 3 beschrieben.
  3. Rufen Sie für jedes Klassifizierungsobjekt die Methode Classify des Objekts Model auf und übergeben Sie das ClassificationObject als Eingabeparameter. Die Methode gibt eine Sammlung von ClassificationResult-Objekten zurück, die jeweils die Kategorienbezeichnung und die Wahrscheinlichkeit für diese Kategorie enthalten. Die Ergebnisse sind nach Wahrscheinlichkeit vom besten zum schlechtesten sortiert. Rufen Sie das Ergebnis ab und prüfen Sie, ob die Wahrscheinlichkeit für Sie akzeptabel ist.
    Wenn der Klassifikator keine Kategorie zuweisen konnte, wird anstelle der Ergebnissammlung null zurückgegeben.
Das Modelltraining und die Klassifizierung werden unter Linux und Windows unabhängig vom Wert von IMultiProcessingParams::MultiProcessingMode im sequenziellen Modus durchgeführt.

C#

// Open the trained model
FREngine.IModel model = classEngine.CreateModelFromFile( "C:\\model.dat" );
// Classify the object
FREngine.IClassificationResults classResults = model.Classify( clObject );
// Access the best result and its probability
string label = classResults[0].CategoryLabel;
double probability = classResults[0].Probability;
Nachdem Sie Ihre Arbeit mit ABBYY FineReader Engine abgeschlossen haben, müssen Sie das Objekt Engine entladen. Verwenden Sie dazu die exportierte Funktion DeinitializeEngine.

C#

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;
}

Erforderliche Ressourcen

Sie können die Datei FREngineDistribution.csv verwenden, um automatisch eine Liste der Dateien zu erstellen, die für die Ausführung 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 Processing Processing.Classification Processing.Classification.NaturalLanguages Processing.OCR Processing.OCR, Processing.ICR Processing.OCR.NaturalLanguages Processing.OCR.NaturalLanguages, Processing.ICR.NaturalLanguages 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. Opening.PDF, wenn Sie PDF-Dateien öffnen müssen, oder Processing.OCR.CJK, wenn Sie Texte in CJK-Sprachen erkennen müssen). Weitere Informationen finden Sie unter Working with the FREngineDistribution.csv File.

Zusätzliche Optimierung

Weitere Informationen zum Einrichten der verschiedenen Verarbeitungsphasen finden Sie in diesen Artikeln:

Siehe auch

Implementierung grundlegender Anwendungsszenarien