\section{Implementierung}
\label{implementierung}

\subsection{Vergleichsdaten}

Als Ausgangsdaten für die Durchführung wurden von allen Dokumentationsscreenshots 25 zufällige Elemente ausgewählt. Zusätzlich wurden auch Bilder in die Stichprobe mit aufgenommen, die beispielsweise aufgrund ihrer Auflösung oder Kontrastverhältnisse schwer lesbar sind.

% TODO Figure ein Beispielscreenshot

% TODO Figure ein Beispielscreenshot mit schlechter Lesbarkeit

Die textuellen Inhalte aller ausgewählten Bilder wurden anschließend manuell extrahiert und für den programmatischen Vergleich in einer Datei im selben Verzeichnis wie die Quellbilddatei festgehalten.

% TODO Screenshot und resultierende textdaten.

\subsection{Programmkomponenten}

\subsubsection{Bibliotheken}

In der prototypischen Implementierung, geschrieben in der Programmiersprache \csharp, wurden in Referenz an die in \autoref{technologien} vorgestellten Technologien und Werkzeuge folgende NuGet-Bibliotheken verwendet:

\begin{itemize}
  \item \textbf{Magick.NET}\\Version: 13.1.0\\Lizenz: Apache-2.0\\\url{https://www.nuget.org/packages/Magick.NET.Core}
  \item \textbf{Tesseract}\\Version: 5.2.0\\Lizenz: Apache-2.0\\\url{https://www.nuget.org/packages/Tesseract}
\end{itemize}

\subsubsection{Verarbeitungssystem}

Beim Entwurf des Verarbeitungssystems für die unterschiedlichen Bild- und Textverarbeitungsschritte wurde bewusst auf Flexibilität geachtet. Mithilfe von Interfaces und Builder-Methoden ist es möglich, Verarbeitungsschritte als Prozessoren (\engl{Processors}) zu definieren. So stellt beispielsweise das Normalisieren eines durch Tesseract erkannten Wortes einen Verarbeitungsschritt dar.

\begin{CsCode}[numbers=none]
  public interface IProcessor
    {
      IEnumerable Process(IEnumerable inputs);
    }

  public interface IProcessor<in TInput, out TOutput> : IProcessor
    {
      IEnumerable<TOutput> Process(IEnumerable<TInput> inputs);

      new IEnumerable Process(IEnumerable inputs)
      {
          return Process((IEnumerable<TInput>)inputs);
        }
    }
\end{CsCode}
\label{program:processor_interface}
\captionof{program}{Auszug aus Datei "IProcessor.cs": Schnittstelle eines Prozessors}

\begin{CsCode}[numbers=none]
  public class ToLowerProcessor
  : Processor<ScanResult, ScanResult>
    {
      public override IEnumerable<ScanResult> Process(
      IEnumerable<ScanResult> inputs
      )
      {
          foreach (var kv in inputs)
          {
              kv.Word.Text = kv.Word.Text.ToLower();
              yield return kv;
            }
        }
    }
\end{CsCode}
\label{program:processor_implementation}
\captionof{program}{Auszug aus Datei "ToLowerProcessor.cs": Normalisieren als einzelner Verarbeitungsschritt}

Sollen mehrere Schritte verbunden werden, ist es möglich, bietet das Processing-Framework die Möglichkeit, eine sogenannte Verarbeitungskette aufzubauen. Hier können Delegates oder komplette Prozessoren dynamisch als einzelne Schritte aneinandergereiht werden, wobei die Typensicherheit durch das generische Typensystem von \csharp stets gewahrt wird:

\begin{CsCode}[numbers=none]
  public interface IProcessorChainConfiguration<TInput, TOutput> : IProcessorChain<TInput, TOutput>
    {
      IProcessorChainConfiguration<T, TOutput, TInput, TOutput> Use<T>(
      IProcessor<TInput, T> processor);

      IProcessorChainConfiguration<T, TOutput, TInput, TOutput> Use<T>(
      Func<IEnumerable<TInput>, IEnumerable<T>> processorFunc);

      IProcessorChainConfiguration<TInput, TOutput> Complete(
      IProcessor<TInput, TOutput> processor);

      IProcessorChainConfiguration<TInput, TOutput> Complete(
      Func<IEnumerable<TInput>, IEnumerable<TOutput>> processorFunc);
    }

  public interface IProcessorChainConfiguration<TInput, TOutput, TInChain, TOutChain>
    {
      IProcessorChainConfiguration<T, TOutput, TInChain, TOutChain> Use<T>(
      IProcessor<TInput, T> processor);

      IProcessorChainConfiguration<T, TOutput, TInChain, TOutChain> Use<T>(
      Func<IEnumerable<TInput>, IEnumerable<T>> processorFunc);

      IProcessorChain<TInChain, TOutChain> Complete(
      IProcessor<TInput, TOutput> processor);

      IProcessorChain<TInChain, TOutChain> Complete(
      Func<IEnumerable<TInput>, IEnumerable<TOutput>> processorFunc);
    }
\end{CsCode}
\label{program:processor_chain_interface}
\captionof{program}{Auszug aus Datei "IProcessorChainConfiguration.cs": Schnittstelle zur Konfiguration einer Verarbeitungskette}

Ist die Aufbauphase abgeschlossen, kann die Verarbeitungskette schlussendlich gestartet werden.

\begin{CsCode}[numbers=none]
  var postProcessor = new ProcessorChainConfiguration<ScanResult, ScanResult>()
  .Use(new ConfidenceFilter(50))
  .Use(new ToLowerProcessor())
  .Use(new DuplicateFilter())
  .Complete(new RegexFilter(WordRegex));

  // ...

  postProcessor.Process(data);
\end{CsCode}
\label{program:processor_chain_implementation}
\captionof{program}{Auszug aus Datei "ImageViewModel.cs": Konfiguration und Starten einer Verarbeitungskette}

Abhängig von den verwendeten Prozessoren können also Eingangsdaten jeglichen Typs, in diesem Fall Bildobjekte der Magick.NET Bibliothek oder Ergebnisdaten des Texterkennungsvorgangs dynamisch verarbeitet werden.

\subsubsection{Verarbeitungskette}

% TODO
Detaillierte Erklärung der für diese BA verwendeten Verarbeitungskette bzw. deren Ablauf inklusive Code-Auszügen.

\subsection{Programmablauf}

% TODO

\subsubsection{Texterkennung}

% TODO
TODO: Beschreibung der Schlüsselkomponenten für die Texterkennung

\subsubsection{Vergleich mit Soll-Daten}

% TODO
TODO: Beschreibung der Schlüsselkomponenten für den programmatischen Vergleich mit den Soll-Daten

\subsubsection{Automatische Berichterstellung}

% TODO
TODO: Beschreibung der Schlüsselkomponenten für die automatische Report-Erstellung