Feedback, love to HS and SP
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
\section{Ziele}
|
||||
\label{ziele}
|
||||
|
||||
|
||||
|
||||
Das Ziel dieser Bachelorarbeit ist das Ermitteln einer Vorgehensweise für Texterkennung in Screenshots von grafischen Oberflächen. Verschiedene Algorithmen zur Bildbearbeitung vor der Texterkennung oder Nachbearbeitung \bzw Filterung der Ergebnisdaten werden evaluiert und anhand von festgelegten Qualitätskriterien analysiert.
|
||||
|
||||
Die prototypische Implementierung dient als Basis für jegliche Tests und Analysen, anhand derer die Algorithmen automatisch verglichen werden. Die entwickelten Komponenten werden als Bibliotheken zur Verfügung gestellt, um die Texterkennung inklusive automatischer Bildverarbeitung und Filterung der erkannten Inhalte \bzw Schlagworte später in anderen Anwendungen weiterverwenden zu können.
|
||||
@@ -4,9 +4,9 @@
|
||||
\subsection{Texterkennungssystem}
|
||||
\label{texterkennungssystem}
|
||||
|
||||
Die Nutzung der in \autoref{einleitung} erwähnten Anwendungen \bzw Dienstleistungen ist kostenpflichtig und die genaue innere Vorgehensweise dieser Programme ist nicht öffentlich bekannt \mcite{textract_pricing, gcv_pricing, azurevision_pricing}. Aufgrund dieser Tatsachen ist die Wahl des Texterkennungssystems für die prototypische Implementierung dieser Bachelorarbeit auf die seit 2005 unter der Freie-Software-Lizenz "Apache 2.0" veröffentlichten "Tesseract Open Source OCR Engine" (kurz: Tesseract) gefallen \mcite{Smith2007}. Diese basiert seit der Major-Version 4 auf einem neuronalen Netz, durch welches mithilfe von sprachspezifischen Trainingsdaten Texte in Bildern erkannt werden können. Außerdem stellt sie mit mittlerweile über 50.000 Sternen auf der Repository-Hosting-Plattform GitHub eines der beliebtesten Texterkennungssysteme dar \mcite{tessdoc}{tessrepo}.
|
||||
Die Nutzung der in \autoref{einleitung} erwähnten Anwendungen \bzw Dienstleistungen ist kostenpflichtig und die genaue innere Vorgehensweise dieser Programme ist nicht öffentlich bekannt \mcite{textract_pricing, gcv_pricing, azurevision_pricing}. Aufgrund dieser Tatsachen ist die Wahl des Texterkennungssystems für die prototypische Implementierung dieser Bachelorarbeit auf die seit 2005 unter der Freie-Software-Lizenz "Apache 2.0" veröffentlichten "Tesseract Open Source OCR Engine" (kurz: Tesseract) gefallen \mcite{Smith2007}. Diese basiert seit der Major-Version 4 auf einem neuronalen Netz, durch welches mithilfe von sprachspezifischen Trainingsdaten Texte in Bildern erkannt werden können \mcite{tessdoc}.
|
||||
|
||||
\subsection{Bildbearbeitungswerkzeug}
|
||||
\label{bildbearbeitungswerkzeug}
|
||||
|
||||
Als Werkzeug für die Durchführung der notwendigen Bildbearbeitungsschritte wurde die Softwarebibliothek "ImageMagick" \mcite{imagemagick} gewählt. Sie ist umfassend dokumentiert, flexibel und kann Dank der Unterstützung für eine Vielzahl von Programmiersprachen oftmals direkt in Programme eingebunden werden. Viele in der Bildverarbeitung genutzte Operationen sind außerdem bereits implementiert, was schnelles Prototyping vereinfacht und die Bibliothek zu einer idealen Wahl für die Realisierung von Bildbearbeitungsschritten in der prototypischen Implementierung macht.
|
||||
Als Werkzeug für die Durchführung der notwendigen Bildbearbeitungsschritte wurde die Softwarebibliothek "ImageMagick" \mcite{imagemagick} gewählt. Sie ist umfassend dokumentiert, flexibel und kann Dank der Unterstützung für eine Vielzahl von Programmiersprachen direkt in Programme eingebunden werden. Viele in der Bildverarbeitung genutzte Operationen sind bereits implementiert, was schnelles Prototyping vereinfacht und die Bibliothek zu einer idealen Wahl für die Realisierung von Bildbearbeitungsschritten in der prototypischen Implementierung macht.
|
||||
@@ -1,14 +1,14 @@
|
||||
\subsection{Postprocessing}
|
||||
\label{algorithmen_postprocessing}
|
||||
|
||||
Da die verarbeiteten Bilddaten \bzw deren extrahierte Textdaten später mittels einer schlagwortbasierten Suchfunktion durch den Nutzer auffindbar sein müssen, ist es notwendig, die Ergebnisdaten im Rahmen des Postprocessings weiterzuverarbeiten. Das Ziel ist es, die Redundanz innerhalb des Datensets zu reduzieren. Ebenso sollen falsch erkannte Ergebnisdaten identifiziert und aus der Schlagwortmenge entfernt werden.
|
||||
Die extrahierten Textdaten aus den verarbeiteten Bilddaten werden später in einer schlagwortbasierten Suchfunktion verwendet. Um Redundanz innerhalb des Datensets zu reduzieren und falsch erkannte Ergebnisdaten zu verhindern, müssen die Ergebnisdaten der Texterkennung im Rahmen des Postprocessings weiterverarbeitet werden.
|
||||
|
||||
\subsubsection{Filterung anhand der Genauigkeit}
|
||||
\label{algorithmen_confidence}
|
||||
|
||||
Tesseract stellt im Rahmen der Texterkennung neben den erkannten Texten auch die jeweiligen Metadaten zur Verfügung. Auch die geschätzte Genauigkeit (\engl{Confidence}) wird für jedes erkannte Wort mit angegeben. Sie bestimmt, mit welcher Sicherheit ein Texterkennungssystem das jeweilige Wort erkannt hat, wobei Wörter mit hoher Confidence eher richtig, mit niedriger Confidence eher falsch erkannt wurden.
|
||||
|
||||
Der Confidence-Filter prüft die jeweiligen Wörter auf ihre Metadaten und verwirft Wörter, deren Confidence unter einem fixen Schwellenwert liegt. Je nach Einstellung \bzw "Härte" des Filters wird die Anzahl der falsch erkannten Inhalte innerhalb der Schlagwortmenge drastisch reduziert. Ist der Filter zu streng eingestellt, werden jedoch insgesamt weniger Worte in die Ergebnisse mit aufgenommen und es kann vorkommen, dass auch ursprünglich korrekt erkannte Wörter aufgrund eines niedrigen Confidence-Wertes verworfen werden.
|
||||
Wie in \autoref{fig:screenshot_postprocessing_confidence} gezeigt, prüft der Confidence-Filter die jeweiligen Wörter auf ihre Metadaten und verwirft jene, deren Confidence unter einem fixen Schwellenwert liegt. Je nach Einstellung \bzw "Härte" des Filters wird die Anzahl der falsch erkannten Inhalte innerhalb der Schlagwortmenge drastisch reduziert. Ist der Filter zu streng eingestellt, werden jedoch insgesamt weniger Worte in die Ergebnisse mit aufgenommen und es kann vorkommen, dass auch ursprünglich korrekt erkannte Wörter aufgrund eines niedrigen Confidence-Wertes verworfen werden.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -19,14 +19,14 @@ Der Confidence-Filter prüft die jeweiligen Wörter auf ihre Metadaten und verwi
|
||||
\begin{minipage}{0.49\textwidth}
|
||||
\lstinputlisting[firstnumber=2,linerange={2-14}]{include/postprocessing/confidence.detailed.json}
|
||||
\end{minipage}
|
||||
\caption{Auszug aus den Ergebnisdaten der Texterkennung aus \ref{fig:screenshot_postprocessing} nach der Confidence-Filterung. Alle Wörter unter dem Schwellenwert werer entfernt.}
|
||||
\caption{Auszug aus den Ergebnisdaten der Texterkennung aus \ref{fig:screenshot_postprocessing} nach der Confidence-Filterung. Alle Wörter unter dem Schwellenwert werden entfernt.}
|
||||
\label{fig:screenshot_postprocessing_confidence}
|
||||
\end{figure}
|
||||
|
||||
\subsubsection{Normalisierung}
|
||||
\label{algorithmen_normalisierung}
|
||||
|
||||
Um die aus der Texterkennung gewonnenen Daten zunächst für die weitere Filterung vorzubereiten, ist es sinnvoll, die Redundanz der Daten möglichst zu reduzieren und die einzelnen Wörter zu normalisieren \bzw zu standardisieren. Beispielsweise kann durch das Umwandeln aller Textdaten in Kleinbuchstaben die Variation der Daten eingeschränkt werden, ohne jedoch für die Suche relevante Information zu verlieren.
|
||||
Um die aus der Texterkennung gewonnenen Daten zunächst für die weitere Filterung vorzubereiten, ist es sinnvoll, die Redundanz der Daten möglichst zu reduzieren und die einzelnen Wörter zu normalisieren \bzw zu standardisieren. Beispielsweise kann durch das Umwandeln aller Textdaten in Kleinbuchstaben die Variation der Daten eingeschränkt werden, ohne jedoch für die Suche relevante Information zu verlieren. Diese Methode wurd auch in \autoref{fig:screenshot_postprocessing_normalisierung} angewandt.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -44,16 +44,16 @@ Um die aus der Texterkennung gewonnenen Daten zunächst für die weitere Filteru
|
||||
\subsubsection{Vermeidung von Duplikaten}
|
||||
\label{algorithmen_duplikate}
|
||||
|
||||
Nach der Normalisierung werden Duplikate innerhalb der erkannten Textdaten entfernt. Dies verringert ebenfalls die Redundanz der Textdaten und steigert die Effizienz der nachfolgenden Filterverfahren.
|
||||
Nach der Normalisierung werden Duplikate innerhalb der erkannten Textdaten entfernt, um die Effizienz der nachfolgenden Filterverfahren zu erhöhen. In den Daten aus \autoref{fig:screenshot_postprocessing_duplikate} wird die Liste an erkannten Wörtern stark gekürzt und die Redundanz damit verringert. Es treten keine Duplikate mehr auf.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\begin{minipage}{0.49\textwidth}
|
||||
\lstinputlisting[firstnumber=2,linerange={2-14}]{include/postprocessing/normalize.json}
|
||||
\lstinputlisting[firstnumber=33,linerange={33-41}]{include/postprocessing/normalize.json}
|
||||
\end{minipage}
|
||||
\hfill
|
||||
\begin{minipage}{0.49\textwidth}
|
||||
\lstinputlisting[firstnumber=2,linerange={2-14}]{include/postprocessing/duplicates.json}
|
||||
\lstinputlisting[firstnumber=14,linerange={14-22}]{include/postprocessing/duplicates.json}
|
||||
\end{minipage}
|
||||
\caption{Auszug aus den Ergebnisdaten der Texterkennung aus \ref{fig:screenshot_postprocessing} nach der Duplikatentfernung.}
|
||||
\label{fig:screenshot_postprocessing_duplikate}
|
||||
@@ -62,18 +62,18 @@ Nach der Normalisierung werden Duplikate innerhalb der erkannten Textdaten entfe
|
||||
\subsubsection{Filterung anhand der Wortlänge}
|
||||
\label{algorithmen_wortlänge}
|
||||
|
||||
Verarbeitet das Texterkennungssystem Texte mit unregelmäßigen Abständen oder grafischen Artefakten in der Schrift, werden statt des eigentlichen Wortes fälschlicherweise oft kurze Symbolkombinationen erkannt. Um diese Kombinationen aus den Ergebnisdaten zu entfernen, können Zeichenketten mithilfe des Wortlängenfilters ungeachtet ihres Inhaltes verworfen werden.
|
||||
Verarbeitet das Texterkennungssystem Texte mit unregelmäßigen Abständen oder grafischen Artefakten in der Schrift, werden statt des eigentlichen Wortes fälschlicherweise oft kurze Symbolkombinationen erkannt. Um diese Kombinationen aus den Ergebnisdaten zu entfernen, können Zeichenketten, wie in \autoref{fig:screenshot_postprocessing_wortlänge} gezeigt, mithilfe des Wortlängenfilters ungeachtet ihres Inhaltes verworfen werden.
|
||||
|
||||
Zusätzlich kann dieser Filter an die Anforderung des Zielsystems angepasst werden. So sind beispielsweise Wörter, die weniger als zwei Zeichen beinhalten, für die Schlagwortsuche grundsätzlich nicht relevant.
|
||||
Zusätzlich kann dieser Filter an die Anforderung des Zielsystems angepasst werden. So haben beispielsweise Wörter, die weniger als zwei Zeichen beinhalten, einen für die Schlagwortsuche zu geringen Informationsgehalt und werden daher entfernt.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\begin{minipage}{0.49\textwidth}
|
||||
\lstinputlisting[firstnumber=2,linerange={2-14}]{include/postprocessing/normalize.json}
|
||||
\lstinputlisting[firstnumber=14,linerange={14-22}]{include/postprocessing/duplicates.json}
|
||||
\end{minipage}
|
||||
\hfill
|
||||
\begin{minipage}{0.49\textwidth}
|
||||
\lstinputlisting[firstnumber=2,linerange={2-14}]{include/postprocessing/duplicates.json}
|
||||
\lstinputlisting[firstnumber=11,linerange={11-19}]{include/postprocessing/wordlength.json}
|
||||
\end{minipage}
|
||||
\caption{Auszug aus den Ergebnisdaten der Texterkennung aus \ref{fig:screenshot_postprocessing} nach der Wortlängenfilterung. Alle Wörter, die kürzer sind als der Schwellenwert, werden aus den Ergebnisdaten entfernt.}
|
||||
\label{fig:screenshot_postprocessing_wortlänge}
|
||||
@@ -82,12 +82,12 @@ Zusätzlich kann dieser Filter an die Anforderung des Zielsystems angepasst werd
|
||||
\subsubsection{Sprachabhängige Filterung mittels Regular Expressions}
|
||||
\label{algorithmen_regex}
|
||||
|
||||
Nachdem die zu filternden Textdaten durch vorherige Schritte vorverarbeitet wurden, werden die Ergebnisdaten ein letztes Mal mithilfe von regulären Ausdrücken (\engl{Regular Expressions}) durchsucht. Aufgrund der guten Erweiterbarkeit der Regular Expressions kann für jede Sprache ein individueller Filter angelegt werden, der den jeweiligen Zeichensatz beschriftet und unbekannte Sonderzeichen oder Symbole entfernt. So sind beispielsweise im Deutschen Umlaute erlaubt, während häufig auftretende, jedoch unerwünschte Symbole wie das phonetische Zeichen "æ" oder mehrere hintereinandergereihte Leerzeichen explizit entfernt werden können.
|
||||
Nachdem die zu filternden Textdaten durch vorherige Schritte vorverarbeitet wurden, werden die Ergebnisdaten ein letztes Mal mithilfe von regulären Ausdrücken (\engl{Regular Expressions}) durchsucht. Aufgrund der dynamischen Erweiterbarkeit der Regular Expressions kann für jede Sprache ein individueller Filter angelegt werden, der den jeweiligen Zeichensatz beschriftet und unbekannte Sonderzeichen oder Symbole entfernt. So sind beispielsweise im Deutschen Umlaute erlaubt, während häufig auftretende, jedoch unerwünschte Symbole wie das phonetische Zeichen "æ" oder mehrere hintereinandergereihte Leerzeichen explizit entfernt werden können. Die Anwendung des deutschen Sprachfilters wird in \autoref{fig:screenshot_postprocessing_regex} gezeigt.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\begin{minipage}{0.49\textwidth}
|
||||
\lstinputlisting[firstnumber=2,linerange={2-14}]{include/postprocessing/duplicates.json}
|
||||
\lstinputlisting[firstnumber=7,linerange={7-19}]{include/postprocessing/duplicates.json}
|
||||
\end{minipage}
|
||||
\hfill
|
||||
\begin{minipage}{0.49\textwidth}
|
||||
|
||||
@@ -3,16 +3,18 @@
|
||||
|
||||
Beim sogenannten "Preprocessing" werden die zu verarbeitenden Bilder für die Texterkennung vorbereitet, um die Qualität der erkannten Textdaten zu verbessern.
|
||||
|
||||
Verwendet man moderne Tesseract-Implementierungen, sind in diesen oft bereits rudimentäre Bildverarbeitungswerkzeuge verfügbar \mcite{todo}. Mit diesen Werkzeugen werden die eingespeisten Bilder -- sofern nicht bereits im richtigen Format -- automatisch für die Texterkennung vorbereitet. Ohne weitere Einstellungen zu treffen, bewirkt diese Bildverarbeitung zwar ein Umwandeln der Eingangsgrafiken in ein meist gut für Tesseract geeignetes Bild. Nichtsdestotrotz ist es sinnvoll, die Bildverarbeitungsschritte individuell auf die erwarteten Eingangsdaten anzupassen. So können die Bilddaten den in \autoref{annahmen_bild_optimal} definierten optimalen Tesseract-Eingangsdaten angenähert werden.
|
||||
Verwendet man moderne Tesseract-Implementierungen, sind in diesen oft bereits rudimentäre Bildverarbeitungswerkzeuge verfügbar \mcite{todo}. Mit diesen Werkzeugen werden die eingespeisten Bilder -- sofern nicht bereits im richtigen Format -- automatisch für die Texterkennung vorbereitet. Ohne weitere Einstellungen zu treffen, bewirkt diese Bildverarbeitung zwar ein Umwandeln der Eingangsgrafiken in ein meist gut für Tesseract geeignetes Bild. Es ist jedoch zu beachten, dass due Bildverarbeitungsschritte individuell auf die erwarteten Eingangsdaten anzupassen sind. So können die Bilddaten den in \autoref{annahmen_bild_optimal} definierten optimalen Tesseract-Eingangsdaten angenähert werden.
|
||||
|
||||
Die folgenden Preprocessing-Schritte basieren auf der empfohlenen Vorgehensweise zur Verbesserung der Output-Qualität laut Tesseract-Dokumentation \mcite{tessdoc}. Gemäß den obigen Annahmen werden jedoch weder perspektivische Fehler, noch ein eventuelles Rauschen korrigiert. Konkret werden folgende Bildverarbeitungsschritte verglichen:
|
||||
|
||||
\subsubsection{Resampling}
|
||||
\label{algorithmen_resampling}
|
||||
|
||||
Bei Resampling wird die Bildauflösung durch "Neuabtastung" verändert. Um die für Tesseract optimale \mcite{tessdoc} Mindestauflösung von 300 dpi zu gewährleisten, muss das Eingangsbild, sofern es die Mindestauflösung unterschreitet, zunächst entsprechend vergrößert werden.
|
||||
Bei Resampling wird die Bildauflösung durch Interpolation verändert. Um die für Tesseract optimale \mcite{tessdoc} Mindestauflösung von 300 dpi zu gewährleisten, muss das Eingangsbild, sofern es die Mindestauflösung unterschreitet, zunächst entsprechend vergrößert werden.
|
||||
|
||||
Da Tesseract auf klare und scharfe Kontraste angewiesen ist, um Text korrekt zu identifizieren, eignen sich nicht alle von ImageMagick zur Verfügung gestellten Skalierungsmethoden für die Weiterverarbeitung. Wie in Abbildung \ref{fig:algorithmen_resampling_vergleich} zu sehen, neigen einige Filter besonders beim Hochskalieren dazu, Unschärfen oder Artefakte zu erzeugen, die die Genauigkeit der Texterkennung negativ beeinflussen können.
|
||||
% TODO erkläre Interpolation
|
||||
|
||||
Da Tesseract auf klare und scharfe Kontraste angewiesen ist, um Text korrekt zu identifizieren, eignen sich nicht alle von ImageMagick zur Verfügung gestellten Skalierungsmethoden für die Weiterverarbeitung. Wie in Abbildung \ref{fig:algorithmen_resampling_vergleich} zu sehen ist, neigen einige Filter besonders beim Hochskalieren dazu, Unschärfen oder Artefakte zu erzeugen, die die Genauigkeit der Texterkennung negativ beeinflussen können.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -31,22 +33,22 @@ Da Tesseract auf klare und scharfe Kontraste angewiesen ist, um Text korrekt zu
|
||||
\subcaptionbox
|
||||
{Lanczos}
|
||||
{\fbox{\includegraphics[width=0.24\textwidth]{include/resampling/Lanczos.png}}}
|
||||
\caption{Ein Vergleich unterschiedlicher Resampling-Filter. Bei Anwendung des Lanczos-Filters bleiben Details und Konturen vergleichsweise gut erhalten und der Text ist gut lesbar.}
|
||||
\caption{Ein Vergleich unterschiedlicher Resampling-Filter. Durch die Aufteilung der Fehler auf mehrere Pixel bleiben Details und Konturen bei Anwendung des Lanczos-Filters vergleichsweise gut erhalten und der Text ist gut lesbar.}
|
||||
\label{fig:algorithmen_resampling_vergleich}
|
||||
\end{figure}
|
||||
|
||||
Nach einigen Tests hat sich gezeigt, dass Bilder, die mittels des Spline-Verfahrens oder der Hermite-Interpolation skaliert wurden, weiche Konturen ohne harte Farbübergänge aufweisen. Tesseract profitiert jedoch stark von klaren Texten und hohen Kontrasten, weswegen diese Art des Resamplings keine ideale Basis für das Preprocessing bietet. Deswegen wird für die weiteren Schritte die Interpolation nach Lanczos für das Resampling verwendet.
|
||||
Nach einigen Tests fällt auf, dass Bilder, die mittels des Spline-Verfahrens oder der Hermite-Interpolation skaliert wurden, weiche Konturen ohne harte Farbübergänge aufweisen. Tesseract profitiert jedoch stark von klaren Texten und hohen Kontrasten, weswegen diese Art des Resamplings keine ideale Basis für das Preprocessing bietet. Deswegen wird für die weiteren Schritte die Interpolation nach Lanczos für das Resampling verwendet.
|
||||
|
||||
\subsubsection{Rahmen}
|
||||
\label{algorithmen_rahmen}
|
||||
|
||||
Befindet sich Text zu nah am Rand des Bildes, kommt es vor, dass dieser oft nicht richtig erkannt wird. Ebenso kann auch ein zu großer einfärbiger Rahmen am Rand des Bildes dazu führen, dass Bildsektionen fälschlicherweise als "leer" erkannt und übersprungen werden, wodurch der zu erkennende Text nicht in die Ergebnisdaten mit aufgenommen wird.
|
||||
Befindet sich Text zu nah am Rand des Bildes, kommt es vor, dass dieser oft nicht richtig erkannt wird. Ebenso kann auch ein zu großer einfärbiger Rahmen am Rand des Bildes die Texterkennung stören. Bei Rahmengrößen wie in \autoref{fig:rahmen_groß} kommt es vor, dass Bildsektionen fälschlicherweise als "leer" erkannt und übersprungen werden, wodurch der zu erkennende Text nicht in die Ergebnisdaten mit aufgenommen wird.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=.4\textwidth]{include/bsp_rahmen_groß.png}}
|
||||
\caption{Ein im Verhältnis zur Bildgröße zu großer einfärbiger Rahmen}
|
||||
\label{}
|
||||
\label{fig:rahmen_groß}
|
||||
\end{figure}
|
||||
|
||||
\subsubsection{Binarisierung}
|
||||
@@ -59,7 +61,7 @@ Das Erzeugen eines Binärbildes ist durch Anwendung von Segmentierungsverfahren
|
||||
|
||||
Ein häufig für die Bildsegmentierung genutztes Verfahren ist die feste Schwellenwertmethode, auf Englisch auch "Fixed Thresholding" genannt. Bei diesem Bildverarbeitungsverfahren wird ein manuell vordefinierter Grenzwert auf einzelne Pixelwerte angewandt. Liegt der Pixelwert über dem festgelegten Schwellenwert, gilt er als Teil des Vordergrunds, andernfalls als Hintergrund. Somit können Objekte, also die einzelnen Buchstaben in den Grafikdateien, von ihrem Hintergrund getrennt werden.
|
||||
|
||||
Das fixe Thresholding benötigt durch seine Simplizität einen geringen Berechnungsaufwand und weist daher eine hohe Performance auf. Allerdings kann es besonders bei Screenshotdateien vorkommen, dass die eigentlich bunten grafischen Elemente der Benutzeroberfläche aufgrund ihrer Helligkeit über dem Schwellenwert liegen. Dadurch werden sie, genau wie der Text, als Vordergrund wahrgenommen und die gesamte Fläche wird einfärbig. Somit kann jeglicher Text innerhalb dieser Fläche nicht vom Texterkennungssystem erkannt werden und die Qualität und Menge der erkannten Textdaten wird stark reduziert.
|
||||
Das fixe Thresholding benötigt durch den fest definierten Schwellenwert einen geringen Berechnungsaufwand und weist eine hohe Performance auf. Besonders bei Screenshotdateien kann es vorkommen, dass die eigentlich bunten grafischen Elemente der Benutzeroberfläche aufgrund ihrer Helligkeit über dem Schwellenwert liegen. Dadurch werden sie, genau wie der Text, als Vordergrund wahrgenommen und die gesamte Fläche wird einfärbig. Somit können jegliche Texte innerhalb dieser Fläche nicht vom Texterkennungssystem erkannt werden und die Qualität und Menge der erkannten Daten wird stark reduziert. Der Unterschied der Ergebnisdaten ist besonders im Vergleich von \autoref{thresholding_fixed_vergleich_gut} \bzw \autoref{thresholding_fixed_vergleich_schlecht} ersichtlich.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -82,7 +84,7 @@ Das fixe Thresholding benötigt durch seine Simplizität einen geringen Berechnu
|
||||
\subsubsubsection{Adaptive Schwellenwertmethode}
|
||||
\label{thresholding_adaptive}
|
||||
|
||||
Die adaptive Schwellenwertmethode gehört zu den halbautomatischen Schwellenwertalgorithmen. Bei diesem Verfahren wird der Schwellenwert auf Basis der lokalen Eigenschaften eines Bildbereichs angepasst, der durch die manuell festgelegte sogenannte "Blockgröße" definiert wird. Innerhalb eines Blocks wird schließlich dynamisch ein fester Schwellenwert ermittelt. Dadurch können im Gegensatz zur \hyperref[thresholding_fixed]{festen Schwellenwertmethode} verschiedenfarbige Texte auf Hintergründen unterschiedlicher Helligkeit besser abgegrenzt werden und die Menge an erkanntem Text wird erhöht.
|
||||
Die adaptive Schwellenwertmethode gehört zu den halbautomatischen Schwellenwertalgorithmen. Bei diesem Verfahren wird der Schwellenwert auf Basis der lokalen Eigenschaften eines Bildbereichs angepasst, der durch die manuell festgelegte sogenannte "Blockgröße" definiert wird. Diese bestimmt die Seitenlänge des Rechtecks, innerhalb dessen ein fester Schwellenwert ermittelt wird. Durch diese dynamische Berechnung können im Gegensatz zur \hyperref[thresholding_fixed]{festen Schwellenwertmethode} verschiedenfarbige Texte auf Hintergründen unterschiedlicher Helligkeit besser abgegrenzt werden und die Menge an erkanntem Text wird erhöht, wie in \autoref{thresholding_adaptive_vergleich_gut} ersichtlich. Wir die Blockgröße falsch gewählt, können jedoch Artefakte auftreten, welche bei entsprechender Menge, wie im Falle von \autoref{thresholding_adaptive_vergleich_schlecht}, die Texterkennung negativ beeinflusst.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -106,7 +108,7 @@ Die adaptive Schwellenwertmethode gehört zu den halbautomatischen Schwellenwert
|
||||
\subsubsubsection{Dreiecks-Schwellenwertmethode}
|
||||
\label{thresholding_triangle}
|
||||
|
||||
Das Dreiecks-Schwellenwertverfahren verwendet das Histogramm eines Bildes, um einen globalen Schwellenwert zu ermitteln. Innerhalb des Histogramms wird eine Linie vom Höchstwert (\engl{Peak}) zum Minimum gezeichnet und ermittelt die Normale mit der maximalen Länge. Dieses Verfahren erzielt die besten Ergebnisse, wenn die zu extrahierenden Elemente Intensitätswerte aufweisen, die an der Basis des ermittelten Peaks liegen. Für Screenshots von UI-Elementen mit komplexer Struktur und farblich stark variierenden Komponenten ist es eher nicht geeignet.
|
||||
Das Dreiecks-Schwellenwertverfahren verwendet die Häufigkeitsverteilung der Helligkeitswerte eines Bildes, um einen globalen Schwellenwert zu ermitteln. Werden diese Helligkeitswerte in einem Diagramm dargestellt, spricht man von einem Histogramm. Innerhalb des Histogramms wird eine Linie vom Höchstwert (\engl{Peak}) zum Minimum gezeichnet und ermittelt die Normale mit der maximalen Länge. Dieses Verfahren erzielt die besten Ergebnisse, wenn die zu extrahierenden Elemente Intensitätswerte aufweisen, die an der Basis des ermittelten Peaks liegen. Für Screenshots von UI-Elementen mit komplexer Struktur und farblich stark variierenden Komponenten ist es eher nicht geeignet.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -129,8 +131,7 @@ Das Dreiecks-Schwellenwertverfahren verwendet das Histogramm eines Bildes, um ei
|
||||
\subsubsubsection{Schwellenwertmethode nach Otsu}
|
||||
\label{thresholding_otsu}
|
||||
|
||||
Bei dem Schwellenwertverfahren nach Otsu wird der globale Schwellenwert für ein Bild anhand des jeweiligen Histogramms ermittelt. Aufgrund dieser Eigenschaften funktioniert das Verfahren am besten, wenn das Histogramm des Bildes eine bimodale Verteilung aufweist, also zwei klare Spitzen hat.
|
||||
|
||||
Das Schwellenwertverfahren nach Otsu ermittelt einen globalen Schwellenwert durch Einteilung des Bildes in zwei Klassen (Vordergrund und Hintergrund). Dazu wird für jede Position des Schwellenwerts im Histogramm die Varianz der beiden dadurch entstehenden Klassen ermittelt. Der Schwellenwert ist dann optimal, wenn die Varianz der jeweiligen KLassen minimal ist. Aufgrund dieser Eigenschaften funktioniert das Verfahren am besten, wenn das Histogramm des Bildes wie in \autoref{bimodal_histogram} eine bimodale Verteilung aufweist, also zwei klare Spitzen hat.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -139,7 +140,7 @@ Bei dem Schwellenwertverfahren nach Otsu wird der globale Schwellenwert für ein
|
||||
\label{bimodal_histogram}
|
||||
\end{figure}
|
||||
|
||||
Enthält ein Bild jedoch starkes Hintergrundrauschen, funktioniert die Schwellenwertermittlung nur unzuverlässig. Weist es lokale Helligkeitsunterschiede auf, wie es bei grafischen Oberflächen mit ihren unterschiedlich eingefärbten Oberflächensektionen oft der Fall ist, entstehen Dank der Bestimmung eines einzelnen globalen Wertes für das gesamte Bild ähnliche Probleme wie bei der \hyperref[thresholding_fixed]{fixen Schwellenwertmethode}.
|
||||
Enthält ein Bild jedoch starkes Hintergrundrauschen, oder weist es lokale Helligkeitsunterschiede auf, wie es bei grafischen Oberflächen mit ihren unterschiedlich eingefärbten Oberflächensektionen oft der Fall ist, wird ein Schwellenwert ermittelt, der nicht immer für alle Inhalte des Bildes optimal ist. Dank der Bestimmung eines einzelnen globalen Wertes für das gesamte Bild entstehen ähnliche Probleme wie bei der \hyperref[thresholding_fixed]{fixen Schwellenwertmethode} und die Texterkennung liefert Ergebnisse mit geringem Informationsgehalt. Die Unterschiede zwischen den Ergebnissen für gut geeignete Bilder im Vergleich zu Bildern mit großen lokalen Unterschieden sind in \autoref{thresholding_otsu_vergleich_gut} \bzw \autoref{thresholding_otsu_vergleich_schlecht} ersichtlich.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -162,11 +163,7 @@ Enthält ein Bild jedoch starkes Hintergrundrauschen, funktioniert die Schwellen
|
||||
\subsubsubsection{Schwellenwertmethode nach Kapur}
|
||||
\label{thresholding_kapur}
|
||||
|
||||
Die Schwellenwertmethode nach Kapur, Sahoo und Wong zielt darauf ab, einen Schwellenwert zu finden, der die Entropie zwischen den Vorder- und Hintergrundregionen maximiert.
|
||||
|
||||
% TODO kurzer Mathematischer Exkurs??
|
||||
|
||||
Dieses Schwellenwertverfahren liefert gute Ergebnisse bei Bildern mit starker Varianz der Vorder- und Hintergrundkontraste \bzw einer breiten Helligkeitsverteilung.
|
||||
Die Schwellenwertmethode nach Kapur, Sahoo und Wong zielt darauf ab, einen Schwellenwert zu finden, der die Entropie zwischen den Vorder- und Hintergrundregionen maximiert. Wie in \autoref{thresholding_kapur_vergleich_gut} und \autoref{thresholding_kapur_vergleich_schlecht} zu sehen, liefert die Verwendung dieses Schwellenwertverfahrens gute Ergebnisse bei Bildern mit starker Varianz der Vorder- und Hintergrundkontraste \bzw einer breiten Helligkeitsverteilung.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
\section{Annahmen}
|
||||
\label{annahmen}
|
||||
|
||||
Um die Texterkennung mittels Tesseract und die anschließende Filterung der Ergebnisdaten zu verbessern, ist es sinnvoll, anwendungsspezifische Annahmen für den Verarbeitungsablauf festzulegen.
|
||||
Um die Texterkennung mittels Tesseract und die anschließende Filterung der Ergebnisdaten zu verbessern, werden anwendungsspezifische Annahmen für den Verarbeitungsablauf festgelegt.
|
||||
|
||||
\subsection*{Preprocessing}
|
||||
\subsection{Preprocessing}
|
||||
\label{annahmen_preprocessing}
|
||||
|
||||
\subsubsection*{Eigenschaften von Screenshots}
|
||||
\subsubsection{Eigenschaften von Screenshots}
|
||||
\label{annahmen_bild_eigenschaften}
|
||||
|
||||
Im Falle dieser Bachelorarbeit handelt es sich bei den zu verarbeitenden Bildern ausschließlich um digitale Bildschirmaufnahmen von grafischen Benutzeroberflächen. Es kann also angenommen werden, dass die Screenshots keine Transparenz aufweisen, die Perspektive der Aufnahme nicht verzerrt ist und der Kontrast in den meisten Fällen ausreicht, um die relevanten Inhalte zu erkennen. Weiters ist bei der Bildverarbeitung auf farbige Hintergrundflächen zu achten, mit deren Unterstützung Bildschirmelemente in modernen grafischen Oberflächen oft gruppiert oder getrennt werden. Nach Sichtung des zu verarbeitenden Bilddatensatzes fällt außerdem auf, dass manche Screenshots durch das Selektieren mit der Maus sehr eng abgeschnitten wurden. Auch das ist bei der Vorverarbeitung zu berücksichtigen.
|
||||
Die zu verarbeitenden Bilder im Kontext dieser Bachelorarbeit sind ausschließlich digitale Bildschirmaufnahmen von grafischen Benutzeroberflächen. Es kann also angenommen werden, dass die Screenshots keine Transparenz aufweisen, die Perspektive der Aufnahme nicht verzerrt ist. Im Großteil der evaluierten Fälle ist auch der Kontrast ausreichend, um die relevanten Inhalte zu erkennen. Weiters ist bei der Bildverarbeitung auf farbige Hintergrundflächen zu achten, mit deren Unterstützung Bildschirmelemente in modernen grafischen Oberflächen oft markiert, gruppiert oder getrennt werden. Nach Sichtung des zu verarbeitenden Bilddatensatzes fällt auf, dass manche Screenshots durch das Selektieren mit der Maus sehr eng abgeschnitten wurden. Das ist bei dem Preprocessing ebenfalls zu berücksichtigen. Eine beispielhafte Auswahl typischer Screenshots findet sich in \autoref{annahmen_bild_eigenschaften_beispiel}.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
@@ -21,7 +21,7 @@ Im Falle dieser Bachelorarbeit handelt es sich bei den zu verarbeitenden Bildern
|
||||
\begin{minipage}{\textwidth}
|
||||
\includegraphics[width=\textwidth]{include/screenshots/historian_assistent_001.png}
|
||||
\end{minipage}\hfill
|
||||
\vspace{\baselineskip}
|
||||
\vfill
|
||||
\begin{minipage}{\textwidth}
|
||||
\includegraphics[width=\textwidth]{include/screenshots/driver_archdrv_variablendefinition_001.png}
|
||||
\end{minipage}\hfill
|
||||
@@ -30,29 +30,26 @@ Im Falle dieser Bachelorarbeit handelt es sich bei den zu verarbeitenden Bildern
|
||||
\label{annahmen_bild_eigenschaften_beispiel}
|
||||
\end{figure}
|
||||
|
||||
\subsubsection*{Optimieren von Daten für Tesseract}
|
||||
\subsubsection{Optimieren von Daten für Tesseract}
|
||||
\label{annahmen_bild_optimal}
|
||||
|
||||
Für die Verwendung von Tesseract ist es wichtig, unabhängig von der Diversität der Ausgangsdaten möglichst einheitliche Bilder zu erzeugen. Während störende Elemente wie Bildrauschen aus dem Bild entfernt werden sollen, sollen Texte unabhängig von der Hinter- bzw. Vordergrundfarbe gut zu erkennen und leicht von Formen oder grafischen Symbolen abzugrenzen sein \mcite{sporici2020improving} \mcite{mursari2021effectiveness}.
|
||||
Für die Verwendung von Tesseract ist es wichtig, unabhängig von der Diversität der Ausgangsdaten möglichst einheitliche Bilder zu erzeugen. Während störende Elemente wie Bildrauschen aus dem Bild entfernt werden, sollen Texte ohne Einfluss der eigentlichen Hinter- bzw. Vordergrundfarbe gut zu erkennen sein. Auch eine deutliche Abgrenzung von Formen oder grafischen Symbolen ist von großer Wichtigkeit. \mcite{sporici2020improving} \mcite{mursari2021effectiveness}. Wurde ein Screenshot ideal vorbereitet, wie in \autoref{fig:screenshot_comparison_optimal} gezeigt, verschwinden farbige Hintergrundflächen und grafische Dekorationselemente. Übrig bleibt nur der gut lesbare textuelle Inhalt des Bildes.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\begin{minipage}{0.4\textwidth}
|
||||
\fbox{\includegraphics[width=\textwidth]{include/screenshots/command-processing_screentypes_controlgroup_005.png}}
|
||||
\end{minipage}
|
||||
\hspace{0.1\textwidth}
|
||||
\begin{minipage}{0.4\textwidth}
|
||||
\fbox{\includegraphics[width=\textwidth]{\detokenize{include/results/ThresholdProcessor(40\%).00.command-processing_screentypes_controlgroup_005.png}}}
|
||||
\end{minipage}
|
||||
\centering
|
||||
\fbox{\includegraphics[width=0.45\textwidth]{include/screenshots/command-processing_screentypes_controlgroup_005.png}}
|
||||
\hfill
|
||||
\fbox{\includegraphics[width=0.45\textwidth]{\detokenize{include/results/ThresholdProcessor(40\%).00.command-processing_screentypes_controlgroup_005.png}}}
|
||||
\caption{Ein optimales Ergebnisbild. Jegliche farblichen Flächen wurden durch die Bildverarbeitung entfernt. Übrig bleibt klar lesbarer Text mit einem hohen Kontrast zum Hintergrund.}
|
||||
\label{fig:screenshot_comparison_optimal}
|
||||
\label{fig:screenshot_comparison_optimal}
|
||||
\end{figure}
|
||||
|
||||
\subsection*{Postprocessing}
|
||||
\subsection{Postprocessing}
|
||||
\label{annahmen_postprocessing}
|
||||
|
||||
\subsubsection*{Filtern von Symbolen}
|
||||
\subsubsection{Filtern von Symbolen}
|
||||
|
||||
Bei der Texterkennung kommt es vor, dass grafische Elemente als Unicode-Symbole erkannt werden. Beispielsweise finden sich in den ungefilterten Ergebnisdaten oft Aufzählungszeichen "•" oder diverse Varianten von Bindestrichen "‒". Diese Zeichen sind gemäß Anwendungsanforderungen nicht relevant für die Schlagwortsuche und können somit entfernt \bzw ignoriert werden.
|
||||
Bei der Texterkennung kann es vorkommen, dass grafische Elemente als diverse Unicode-Symbole erkannt werden. Wie in \autoref{fig:screenshot_postprocessing}, wird oftmals versucht, grafische Dekorationselemente textuell nachzubilden. Auch finden sich in den ungefilterten Ergebnisdaten oft Aufzählungszeichen wie "•" oder unterschiedliche Varianten von Bindestrichen "‒". Diese Zeichen sind gemäß Anwendungsanforderungen nicht relevant für die Schlagwortsuche und können somit entfernt \bzw ignoriert werden.
|
||||
|
||||
\begin{figure}[t]
|
||||
\centering
|
||||
@@ -67,12 +64,12 @@ Bei der Texterkennung kommt es vor, dass grafische Elemente als Unicode-Symbole
|
||||
\label{fig:screenshot_postprocessing}
|
||||
\end{figure}
|
||||
|
||||
\subsubsection*{Mehrsprachigkeit}
|
||||
\subsubsection{Mehrsprachigkeit}
|
||||
\label{annahmen_mehrsprachigkeit}
|
||||
|
||||
Eine weitere Anforderung an das Textverarbeitungssystem ist das Einlesen und Interpretieren mehrsprachiger Bilddateien. So sollen beispielsweise Bilder mit englischen, deutschen oder italienischen Inhalten zugeführt und die Ergebnisdaten richtig verarbeitet werden können. Um eine Filterung für verschiedene Zeichensätze zu ermöglichen und eine Unterstützung für Sprachen mit nicht-lateinischen Schriften zu gewährleisten, werden dynamische Sprachfilter verwendet, die individuell an die jeweilige Sprache angepasst werden können. Um die Ergebnisdaten nicht unnötig zu verkomplizieren, werden für die initialen Tests und die Beschreibung der generellen Vorgehensweise im Rahmen dieser Bachelorarbeit jedoch nur deutsche oder englische Inhalte verarbeitet.
|
||||
Das Textverarbeitungssystem muss in der Lage sein, mehrsprachige Bilddateien Einlesen und Interpretieren zu können. So sollen beispielsweise Bilder mit englischen, deutschen oder italienischen Inhalten zugeführt und die Ergebnisdaten richtig verarbeitet werden können. Um eine Filterung für verschiedene Zeichensätze zu ermöglichen und eine Unterstützung für Sprachen mit nicht-lateinischen Schriften zu gewährleisten, werden dynamische Sprachfilter verwendet, die individuell an die jeweilige Sprache angepasst werden können. Für die weitere Beschreibung der generellen Vorgehensweise und Tests werden in den folgenden Schritten jedoch nur deutsche oder englische Inhalte verwendet.
|
||||
|
||||
\subsubsection*{Schlagworte}
|
||||
\subsubsection{Schlagworte}
|
||||
\label{annahmen_schlagworte}
|
||||
|
||||
Für die spätere Suche von Screenshots sollen relevante Schlagworte aus den erkannten Textdaten extrahiert werden. Ein Wort eignet sich dann als Schlagwort, wenn es in relevantem Bezug zum jeweiligen Bild steht und dabei idealerweise eine wichtige Aktion oder Information widerspiegelt. Inhalte, die direkt in der grafischen Benutzeroberfläche ersichtlich sind, eignen sich demnach besonders gut als Suchworte. Damit die Menge an Schlagwörtern allerdings nicht zu unspezifisch wird, sollte es vermieden werden, allgemeine sogenannte Stoppwörter (\engl{Stop words}) ohne besondere Semantik, wie "und", "oder", in das Ergebnis mit aufzunehmen. Sie beinhalten keine spezifische Information und fördern aufgrund ihrer Häufigkeit das Auftreten von Verwechslungen.
|
||||
Für die spätere Suche von Screenshots sollen relevante Schlagworte aus den erkannten Textdaten extrahiert werden. Ein Wort eignet sich dann als Schlagwort, wenn es in relevantem Bezug zum jeweiligen Bild steht und dabei eine wichtige Aktion oder Information widerspiegelt. Inhalte, die direkt in der grafischen Benutzeroberfläche ersichtlich sind, haben daher einen hohen Informationsgehalt und eignen sich besonders gut als Suchworte. Um die Schlagwortmenge so aussagekräftig wie möglich zu halten, müssen Wörter mit geringer Bedeutung entfernt werden. Beispielsweise haben sogenannte Stoppwörter (\engl{Stop words}) wie "und" oder "oder" keine besondere Semantik und fördern aufgrund ihrer Häufigkeit das Auftreten von Verwechslungen.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
\section{Analyse}
|
||||
\label{analyse}
|
||||
|
||||
Nachdem die vorbereiteten Bilddaten an das Texterkennungssystem gemäß \autoref{implementierung} übergeben und die Ergebnisse ermittelt wurden, werden die extrahierten Textdaten nun mit den manuell erstellten "Soll-Daten" verglichen. Anhand der Statistik kann festgestellt werden, welche Vorgehensweise zu der besten Qualität führt. Um die Ergebnisse zu visualisieren, erstellt der in \autoref{components_reportgenerator} beschriebene "ReportGenerator" auf Basis der Bilddateinamen automatisch einen Bericht mit den Vergleichsdaten in Tabellenform. Für eine bessere Lesbarkeit wird der erstellte Bericht in verschiedene Kategorien unterteilt.
|
||||
Nachdem die vorbereiteten Bilddaten an das Texterkennungssystem gemäß \autoref{implementierung} übergeben und die Ergebnisse ermittelt wurden, werden die extrahierten Textdaten nun mit den manuell erstellten "Soll-Daten" verglichen. Anhand der Statistik kann festgestellt werden, welche Vorgehensweise zu der besten Qualität führt. Um die Ergebnisse zu visualisieren, erstellt der in \autoref{components_reportgenerator} beschriebene "ReportGenerator" auf Basis der Bilddateinamen automatisch einen Bericht mit den Vergleichsdaten in Tabellenform. Der erstellte Bericht wird in verschiedene Kategorien unterteilt.
|
||||
|
||||
\subsection*{Vergleich im Detail}
|
||||
\subsection{Vergleich im Detail}
|
||||
\label{report_detailed}
|
||||
|
||||
\subsubsection*{Processor Stats}
|
||||
\subsubsection{Processor Stats}
|
||||
|
||||
In der Sektion "Processor Stats", siehe \autoref{tbl:report_detailed_processorstats}, wird die Gesamtwortfehlerrate pro Bild mit dem jeweiligen Prozessor in Verhältnis gesetzt. Auch wenn es Bilder gibt, die aufgrund ihrer Eigenschaften (niedrige Auflösung, schwierige Farbgebung, etc.) von allen Prozessoren gleichermaßen schlecht erkannt werden, fallen bei gewissen Verfahren Spezialfälle auf. So werden beispielsweise die Textdaten in den Dialog-Knöpfen des Bilds "worldview\_zoom\_steps\_001" Dank eines falsch gewählten Schwellenwerts unkenntlich gemacht. Die Texterkennung schlägt fehl.
|
||||
In der Sektion "Processor Stats", siehe \autoref{tbl:report_detailed_processorstats}, wird die Gesamtwortfehlerrate pro Bild mit dem jeweiligen Prozessor in Verhältnis gesetzt. Anhand der Metriken ist zu erkennen, dass gewisse Bilder aufgrund ihrer Eigenschaften (niedrige Auflösung, schwierige Farbgebung, etc.) von allen Prozessoren gleichermaßen schlecht erkannt werden. Jedoch fallen auch Spezialfälle auf: So werden beispielsweise die Textdaten in den Dialog-Knöpfen des Bilds "worldview\_zoom\_steps\_001" Dank eines falsch gewählten Schwellenwerts unkenntlich gemacht. Die Texterkennung schlägt fehl.
|
||||
|
||||
\begin{table}[!ht]
|
||||
\centering
|
||||
@@ -17,7 +17,7 @@ In der Sektion "Processor Stats", siehe \autoref{tbl:report_detailed_processorst
|
||||
\label{tbl:report_detailed_processorstats}
|
||||
\end{table}
|
||||
|
||||
\subsubsection*{Scan Results}
|
||||
\subsubsection{Scan Results}
|
||||
|
||||
Die Sektion "Scan Results" bildet den Abschluss des Detailvergleichs. Hier werden alle Verfahrenskombinationen einzeln und mit allen verfügbaren Daten aufgeführt.
|
||||
|
||||
@@ -35,10 +35,10 @@ Die Sektion "Scan Results" bildet den Abschluss des Detailvergleichs. Hier werde
|
||||
\label{tbl:report_detailed_scanresults_words}
|
||||
\end{table}
|
||||
|
||||
\subsection*{Prozessoren im Überblick}
|
||||
\subsection{Prozessoren im Überblick}
|
||||
\label{report_processingsummary}
|
||||
|
||||
Neben dem Detailvergleich beinhaltet der generierte Bericht auch die "Processing Summary". Diese Kategorie zeigt eine vereinfachte Übersicht aller Ergebnisse. Je nach Rubrik wird jeweils der Median \bzw Durchschnitt der \hyperref[metriken_cer]{Character Error Rate} und \hyperref[metriken_wer]{Word Error Rate} berechnet.
|
||||
Neben dem Detailvergleich beinhaltet der generierte Bericht auch die "Processing Summary". Diese Kategorie zeigt eine kurze Übersicht aller Ergebnisse. Je nach Rubrik wird jeweils der Median \bzw Durchschnitt der \hyperref[metriken_cer]{Character Error Rate} und \hyperref[metriken_wer]{Word Error Rate} berechnet.
|
||||
|
||||
Auf Basis der Daten in \autoref{tbl:report_summary_wer}, \autoref{tbl:report_summary_cer} und \autoref{tbl:report_summary_time} lässt sich der Gesamterfolg der Bildvorbereitung \bzw der darauf folgenden Filterung feststellen.
|
||||
|
||||
|
||||
@@ -3,30 +3,31 @@
|
||||
|
||||
\subsection{Vergleichsdaten}
|
||||
|
||||
Als Ausgangsdaten für die Durchführung wurde eine zufällige Auswahl an Dokumentationsscreenshots getroffen. Zusätzlich wurden auch Bilder in die Stichprobe mit aufgenommen, die beispielsweise aufgrund ihrer Auflösung oder Kontrastverhältnisse schwer lesbar sind.
|
||||
Als Ausgangsdaten für die Durchführung wurde eine zufällige Auswahl an Dokumentationsscreenshots, wie in \autoref{fig:screenshot_beispiel_gut} abgebildet, getroffen. Zusätzlich wurden auch Bilder wie in \autoref{fig:screenshot_beispiel_schlecht} in die Stichprobe mit aufgenommen, die beispielsweise aufgrund ihrer Auflösung oder Kontrastverhältnisse schwer lesbar sind.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=.7\textwidth]{include/screenshots/driver_SEL_Options_002.png}}
|
||||
\caption{Ein gut für die Texterkennung geeigneter Screenshot. Die wesentlichen Inhalte weisen einen guten Kontrast zum Hintergrund auf und befinden sich in Bereichen mit gleichmäßiger Helligkeit.}
|
||||
\label{}
|
||||
\label{fig:screenshot_beispiel_gut}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\fbox{\includegraphics[width=.7\textwidth]{include/screenshots/editor_startpage_project-exist_001.png}}
|
||||
\caption{Ein schlecht lesbarer Screenshot. Aufgrund der vielen Symbole und der bunten Flächen stellt dieses Bild eine Herausforderung für das Texterkennungssystem dar.}
|
||||
\label{}
|
||||
\label{fig:screenshot_beispiel_schlecht}
|
||||
\end{figure}
|
||||
|
||||
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.
|
||||
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. Ein Beispiel dafür ist der Screenshot "zrs\_ZAMS\_filter-alarmgroup\_001" in \autoref{fig:screenshot_verschlagwortet}, welches insgesamt 15 verschiedene Wörter beinhaltet.
|
||||
|
||||
\begin{figure}[ht]
|
||||
\centering
|
||||
\begin{minipage}{0.5\textwidth}
|
||||
\includegraphics[width=\textwidth]{include/screenshots/zrs_ZAMS_filter-alarmgroup_001.png}
|
||||
\includegraphics[width=0.99\textwidth]{include/screenshots/zrs_ZAMS_filter-alarmgroup_001.png}
|
||||
\end{minipage}
|
||||
\hspace{0.1\textwidth}
|
||||
\begin{minipage}{0.4\textwidth}
|
||||
\hfill
|
||||
\begin{minipage}{0.45\textwidth}
|
||||
\lstinputlisting[numbers=none]{include/screenshots/zrs_ZAMS_filter-alarmgroup_001.json}
|
||||
\end{minipage}
|
||||
\caption{Ein Screenshot und die daraus manuell extrahierten Schlagworte.}
|
||||
@@ -49,104 +50,105 @@ In der prototypischen Implementierung, geschrieben in der Programmiersprache \cs
|
||||
\subsubsection{Verarbeitungsketten}
|
||||
\label{components_processorchain}
|
||||
|
||||
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.
|
||||
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 gemäß Programm \ref{prg:processor_interface} als Prozessoren (\engl{Processors}) zu definieren. So stellt beispielsweise das Normalisieren eines durch Tesseract erkannten Wortes einen Verarbeitungsschritt dar, wie in Programm \ref{prg:processor_implementation} gezeigt.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
public interface IProcessor
|
||||
{
|
||||
IEnumerable Process(IEnumerable inputs);
|
||||
}
|
||||
public interface IProcessor
|
||||
{
|
||||
IEnumerable Process(IEnumerable inputs);
|
||||
}
|
||||
|
||||
public interface IProcessor<in TInput, out TOutput> : IProcessor
|
||||
{
|
||||
IEnumerable<TOutput> Process(IEnumerable<TInput> 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);
|
||||
}
|
||||
new IEnumerable Process(IEnumerable inputs)
|
||||
{
|
||||
return Process((IEnumerable<TInput>)inputs);
|
||||
}
|
||||
}
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "IProcessor.cs": Schnittstelle eines Prozessors.}
|
||||
\label{program:processor_interface}
|
||||
\label{prg:processor_interface}
|
||||
\end{program}
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
public class ToLowerProcessor
|
||||
public class ToLowerProcessor
|
||||
: Processor<ScanResult, ScanResult>
|
||||
{
|
||||
public override IEnumerable<ScanResult> Process(
|
||||
IEnumerable<ScanResult> inputs
|
||||
)
|
||||
{
|
||||
public override IEnumerable<ScanResult> Process(
|
||||
IEnumerable<ScanResult> inputs
|
||||
)
|
||||
{
|
||||
foreach (var kv in inputs)
|
||||
{
|
||||
foreach (var kv in inputs)
|
||||
{
|
||||
kv.Word.Text = kv.Word.Text.ToLower();
|
||||
yield return kv;
|
||||
}
|
||||
kv.Word.Text = kv.Word.Text.ToLower();
|
||||
yield return kv;
|
||||
}
|
||||
}
|
||||
}
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "ToLowerProcessor.cs": Normalisieren als einzelner Verarbeitungsschritt}
|
||||
\label{program:processor_implementation}
|
||||
\caption{Auszug aus Datei "ToLowerProcessor.cs": Normalisieren als einzelner Verarbeitungsschritt.}
|
||||
\label{prg:processor_implementation}
|
||||
\end{program}
|
||||
|
||||
Sollen mehrere Schritte verbunden werden, 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:
|
||||
Sollen mehrere Schritte verbunden werden, bietet das Processing-Framework die Möglichkeit, eine Verarbeitungskette aufzubauen. Gemäß der Schnittstellendefinition in Programm \ref{prg:processor_chain_interface} können Delegates oder komplette Prozessoren dynamisch als einzelne Schritte aneinandergereiht werden. Die Typensicherheit wird durch das generische Typensystem von \csharp stets gewahrt.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
public interface IProcessorChainConfiguration<TInput, TOutput> : IProcessorChain<TInput, TOutput>
|
||||
{
|
||||
IProcessorChainConfiguration<T, TOutput, TInput, TOutput> Use<T>(
|
||||
IProcessor<TInput, T> processor);
|
||||
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<T, TOutput, TInput, TOutput> Use<T>(
|
||||
Func<IEnumerable<TInput>, IEnumerable<T>> processorFunc);
|
||||
|
||||
IProcessorChainConfiguration<TInput, TOutput> Complete(
|
||||
IProcessor<TInput, TOutput> processor);
|
||||
IProcessorChainConfiguration<TInput, TOutput> Complete(
|
||||
IProcessor<TInput, TOutput> processor);
|
||||
|
||||
IProcessorChainConfiguration<TInput, TOutput> Complete(
|
||||
Func<IEnumerable<TInput>, IEnumerable<TOutput>> processorFunc);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
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(
|
||||
IProcessor<TInput, TOutput> processor);
|
||||
|
||||
IProcessorChain<TInChain, TOutChain> Complete(
|
||||
Func<IEnumerable<TInput>, IEnumerable<TOutput>> processorFunc);
|
||||
}
|
||||
IProcessorChain<TInChain, TOutChain> Complete(
|
||||
Func<IEnumerable<TInput>, IEnumerable<TOutput>> processorFunc);
|
||||
}
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "IProcessorChainConfiguration.cs": Schnittstelle zur Konfiguration einer Verarbeitungskette}
|
||||
\label{program:processor_chain_interface}
|
||||
\label{prg:processor_chain_interface}
|
||||
\end{program}
|
||||
|
||||
Ist die Aufbauphase abgeschlossen, kann die Verarbeitungskette schlussendlich gestartet werden.
|
||||
Ist die Aufbauphase abgeschlossen, kann die Verarbeitungskette, konfiguriert in Programm \ref{prg:processor_chain_implementation}, gestartet werden.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
var postProcessor = new ProcessorChainConfiguration<ScanResult, ScanResult>()
|
||||
.Use(new ConfidenceFilter(50))
|
||||
.Use(new ToLowerProcessor())
|
||||
.Use(new DuplicateFilter())
|
||||
.Complete(new RegexFilter(WordRegex));
|
||||
var postProcessor = new ProcessorChainConfiguration<ScanResult, ScanResult>()
|
||||
.Use(new ConfidenceFilter(50))
|
||||
.Use(new ToLowerProcessor())
|
||||
.Use(new DuplicateFilter())
|
||||
.Complete(new RegexFilter(WordRegex));
|
||||
|
||||
// ...
|
||||
// ...
|
||||
|
||||
postProcessor.Process(data);
|
||||
postProcessor.Process(data);
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "ImageViewModel.cs": Konfiguration und Starten einer Verarbeitungskette}
|
||||
\label{program:processor_chain_implementation}
|
||||
\caption{Auszug aus Datei "ImageViewModel.cs": Konfiguration und Starten einer Verarbeitungskette.}
|
||||
\label{prg:processor_chain_implementation}
|
||||
\end{program}
|
||||
|
||||
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.
|
||||
@@ -154,66 +156,64 @@ Abhängig von den verwendeten Prozessoren können also Eingangsdaten jeglichen T
|
||||
\subsubsubsection{Bildverarbeitungskette}
|
||||
\label{processor_chain_image}
|
||||
|
||||
Für den grundlegenden Ablauf der Bildverarbeitung und der anschließenden Ergebnisfilterung werden die Erkenntnisse aus \autoref{konzept} mithilfe des in \autoref{components_processorchain} beschriebenen Processing-Frameworks angewandt.
|
||||
Für den Ablauf der Bildverarbeitung und der anschließenden Ergebnisfilterung werden die Erkenntnisse aus \autoref{konzept} mithilfe des in \autoref{components_processorchain} beschriebenen Processing-Frameworks angewandt. Die Resultierende Konfiguration ist in Programm \ref{prg:preprocessor_definition} und Programm \ref{prg:postprocessor_definition} definiert.
|
||||
|
||||
Angefangen mit einem Ausgangsbild, welches über die Softwarebibliothek Magick.NET geladen wurde, beginnt die Bildverarbeitung zunächst mit dem Resampling. Falls der geladene Screenshot die Mindestauflösung von 300dpi unterschreitet, wird es mittels Lanczos2-Verfahren, eine von Magick.NET mitgelieferte Implementierung des Lanczos2-Algorithmus mit leichter Schärfung \mcite{imagemagick}, auf die Mindestauflösung vergrößert. Anschließend wird das Bild normalisiert, in Graustufen umgewandelt und jegliche Transparenz durch einen weißen Hintergrund ersetzt. Danach wird es mittels Schwellwertverfahren binarisiert und rund um das Bild wird ein Rahmen mit einer Dicke von 10px eingefügt. Um Texterkennungsfehler durch falsche Vorder- \bzw Hintergrundfarben auszuschließen, wird das Bild schlussendlich gemeinsam mit einer farblich invertierten Version an das Texterkennungssystem weitergegeben.
|
||||
Angefangen mit einem Ausgangsbild, welches über die Softwarebibliothek Magick.NET geladen wurde, beginnt die Bildverarbeitung zunächst mit dem Resampling. Falls der geladene Screenshot die Mindestauflösung von 300dpi unterschreitet, wird es mittels Lanczos2-Verfahren, eine von Magick.NET mitgelieferte Implementierung des Lanczos2-Algorithmus mit leichter Schärfung \mcite{imagemagick}, auf die Mindestauflösung vergrößert. Anschließend wird das Bild normalisiert, in Graustufen umgewandelt und jegliche Transparenz durch einen weißen Hintergrund ersetzt. Danach wird es mittels Schwellwertverfahren binarisiert. Rund um das Bild wird ein Rahmen mit einer Dicke von 10px eingefügt. Um Texterkennungsfehler durch falsche Vorder- \bzw Hintergrundfarben auszuschließen, wird das Bild gemeinsam mit einer farblich invertierten Version an das Texterkennungssystem weitergegeben.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
var preprocessing = new ProcessorChainConfiguration<MagickImage, MagickImage>()
|
||||
.Use(new CloneImageProcessor())
|
||||
.Use(new ResizeProcessor(FilterType.Lanczos2Sharp, PixelInterpolateMethod.Mesh))
|
||||
.Use(new NormalizeProcessor())
|
||||
.Use(_thresholdProcessor)
|
||||
.Use(new AddBorderProcessor(10))
|
||||
.Use(new BinarizeProcessor())
|
||||
.Use(new NegateCloneProcessor())
|
||||
.Complete(OnPreprocessed);
|
||||
var preprocessing = new ProcessorChainConfiguration<MagickImage, MagickImage>()
|
||||
.Use(new CloneImageProcessor())
|
||||
.Use(new ResizeProcessor(FilterType.Lanczos2Sharp, PixelInterpolateMethod.Mesh))
|
||||
.Use(new NormalizeProcessor())
|
||||
.Use(_thresholdProcessor)
|
||||
.Use(new AddBorderProcessor(10))
|
||||
.Use(new BinarizeProcessor())
|
||||
.Use(new NegateCloneProcessor())
|
||||
.Complete(OnPreprocessed);
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "EvaluationProcessor.cs": Definition der Preprocessing-Kette}
|
||||
\label{program:program_preprocessor_definition}
|
||||
\caption{Auszug aus Datei "EvaluationProcessor.cs": Definition der Preprocessing-Kette.}
|
||||
\label{prg:preprocessor_definition}
|
||||
\end{program}
|
||||
|
||||
Wurde der übergebene Screenshot vom Texterkennungssystem verarbeitet, müssen nun die Ergebnisse gefiltert werden. Dazu werden zunächst die Metadaten der einzelnen Wörter betrachtet und alle Elemente mit einer Confidence unter einem Schwellenwert von 50\% verworfen. Danach werden die erkannten Texte mittels der \csharp-Funktion ToLower() normalisiert und anschließend auf Duplikate untersucht. Sind alle Duplikate verworfen, werden die Wörter schlussendlich mittels sprachabhängigen Regular Expressions -- in diesem Fall gibt es gemäß den Annahmen in \autoref{annahmen_mehrsprachigkeit} einen Sprachfilter für Englisch und Deutsch -- gefiltert.
|
||||
Wurde der übergebene Screenshot vom Texterkennungssystem verarbeitet, müssen nun die Ergebnisse gefiltert werden. Dazu werden zunächst die Metadaten der einzelnen Wörter betrachtet und alle Elemente mit einer Confidence unter einem Schwellenwert von 50\% verworfen. Danach werden die erkannten Texte mittels der \csharp-Funktion ToLower() normalisiert und anschließend auf Duplikate untersucht. Sind alle Duplikate verworfen, werden die Wörter mittels sprachabhängigen Regular Expressions -- in diesem Fall gibt es gemäß den Annahmen in \autoref{annahmen_mehrsprachigkeit} einen Sprachfilter für Englisch und Deutsch -- gefiltert.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
var postprocessing = new ProcessorChainConfiguration<ScanResult, ScanResult>()
|
||||
.Use(new ConfidenceFilter(50))
|
||||
.Use(new ToLowerProcessor())
|
||||
.Use(new DuplicateFilter())
|
||||
.Complete(new RegexFilter(wordRegex));
|
||||
var postprocessing = new ProcessorChainConfiguration<ScanResult, ScanResult>()
|
||||
.Use(new ConfidenceFilter(50))
|
||||
.Use(new ToLowerProcessor())
|
||||
.Use(new DuplicateFilter())
|
||||
.Complete(new RegexFilter(wordRegex));
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "EvaluationProcessor.cs": Definition der Postprocessing-Kette}
|
||||
\label{program:program_postprocessor_definition}
|
||||
\caption{Auszug aus Datei "EvaluationProcessor.cs": Definition der Postprocessing-Kette.}
|
||||
\label{prg:postprocessor_definition}
|
||||
\end{program}
|
||||
|
||||
\subsubsection{Lookup}
|
||||
|
||||
Die "Lookup" Bibliothek abstrahiert das Speichern von Schlüssel-Wert-Paaren. Dabei kann flexibel zwischen verschiedenen Speicherimplementierungen gewechselt werden. So ist es beispielsweise möglich, die Werte in einer Listenstruktur im Arbeitsspeicher, in einer Datei oder -- mittels der EntityFramework-Bibliothek, welche von der .NET Foundation entwickelt wird -- in einer Datenbank persistent abzulegen.
|
||||
|
||||
Unabhängig von der Ablagestruktur im Hintergrund können Lookups mittels einer gemeinsamen Schnittstelle manipuliert werden:
|
||||
Die "Lookup" Bibliothek abstrahiert das Speichern von Schlüssel-Wert-Paaren. Dabei kann flexibel zwischen verschiedenen Speicherimplementierungen gewechselt werden. So ist es beispielsweise möglich, die Werte in einer Listenstruktur im Arbeitsspeicher, in einer Datei oder -- mittels der EntityFramework-Bibliothek, welche von der .NET Foundation entwickelt wird -- in einer Datenbank persistent abzulegen. Unabhängig von der Ablagestruktur im Hintergrund können Lookups mittels einer gemeinsamen Schnittstelle, abgebildert in Programm \ref{prg:lookup_interface}, manipuliert werden.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
public interface ILookup<TKey, TValue>
|
||||
: ILookup,
|
||||
IDictionary<TKey, ICollection<TValue>>,
|
||||
IDisposable
|
||||
{
|
||||
ICollection<TValue> Add(TKey key);
|
||||
public interface ILookup<TKey, TValue>
|
||||
: ILookup,
|
||||
IDictionary<TKey, ICollection<TValue>>,
|
||||
IDisposable
|
||||
{
|
||||
ICollection<TValue> Add(TKey key);
|
||||
|
||||
public void Add(TKey key, TValue value);
|
||||
public void Add(TKey key, TValue value);
|
||||
|
||||
public void AddRange(TKey key, IEnumerable<TValue> values);
|
||||
public void AddRange(TKey key, IEnumerable<TValue> values);
|
||||
|
||||
public bool Remove(TKey key, TValue value);
|
||||
public bool Remove(TKey key, TValue value);
|
||||
|
||||
public ICollection<TValue> GetOrAdd(TKey key);
|
||||
}
|
||||
public ICollection<TValue> GetOrAdd(TKey key);
|
||||
}
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "ILookup.cs": Definition der gemeinsamen Schnittstelle für Lookups}
|
||||
\label{program:program_lookup_interface}
|
||||
\label{prg:lookup_interface}
|
||||
\end{program}
|
||||
|
||||
\subsubsection{OCR}
|
||||
@@ -223,27 +223,27 @@ Die "OCR" Bibliothek enthält elementare Komponenten für die Texterkennung mitt
|
||||
\subsubsection{Automatische Berichterstellung}
|
||||
\label{components_reportgenerator}
|
||||
|
||||
Mithilfe des ReportGenerator-Frameworks wird die automatische Berichterstellung für unterschiedlichste Ausgabeformate abstrahiert. Durch die mitgelieferten Schnittstellendefinitionen ist es möglich, eigene Ausgabeformate zu definieren und den Funktionsumfang des ReportGenerators, wie beispielsweise das Erstellen von Tabellen oder das Anlegen und Überschriften, an die jeweilige Syntax und Dokumentstruktur anzupassen.
|
||||
Mithilfe des ReportGenerator-Frameworks wird die automatische Berichterstellung für unterschiedlichste Ausgabeformate abstrahiert. Durch die mitgelieferten Schnittstellendefinitionen ist es möglich, eigene Ausgabeformate zu definieren. Der gesamte Funktionsumfang des ReportGenerators, beispielsweise das Erstellen von Tabellen oder das Anlegen und Überschriften, kann durch die Implementerung von Interfaces wie Programm \ref{prg:reportgenerator_interface} an die jeweilige Syntax und Dokumentstruktur angepasst werden.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
public interface IDocumentGenerator : IStreamWriter
|
||||
{
|
||||
IDocumentGenerator Append(string? text = default);
|
||||
public interface IDocumentGenerator : IStreamWriter
|
||||
{
|
||||
IDocumentGenerator Append(string? text = default);
|
||||
|
||||
IDocumentGenerator AppendLine(string? text = default);
|
||||
IDocumentGenerator AppendLine(string? text = default);
|
||||
|
||||
IDocumentGenerator AppendParagraph(string? text = default);
|
||||
IDocumentGenerator AppendParagraph(string? text = default);
|
||||
|
||||
IDocumentGenerator AppendHeading(int level, string text);
|
||||
IDocumentGenerator AppendHeading(int level, string text);
|
||||
|
||||
IDocumentGenerator AppendTable(int columns, Action<ITableGenerator> table);
|
||||
IDocumentGenerator AppendTable(int columns, Action<ITableGenerator> table);
|
||||
|
||||
string FormatImage(string path, IBounds? bounds = default);
|
||||
}
|
||||
string FormatImage(string path, IBounds? bounds = default);
|
||||
}
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "IDocumentGenerator.cs": Hauptschnittstelle für den ReportGenerator}
|
||||
\label{program:program_reportgenerator_interface}
|
||||
\label{prg:reportgenerator_interface}
|
||||
\end{program}
|
||||
|
||||
\subsection{Programmablauf}
|
||||
@@ -252,29 +252,29 @@ Die prototypische Implementierung besteht neben den oben genannten Komponenten a
|
||||
|
||||
\subsubsection{Texterkennung}
|
||||
|
||||
Zu Beginn der Ausführung des Kommandozeilenprogramms wird für jedes zu verarbeitende Bild abhängig von den definierten Schwellenwertverfahren eine Reihe von Prozessoren angelegt. Dazu wurde der statische Teil der Bildverarbeitungskette gemäß \autoref{processor_chain_image} innerhalb der "EvaluationProcessor" Klasse definiert. Lediglich die zu evaluierenden Prozessoren für die jeweiligen Schwellwertverfahren können außerhalb der klasse dynamisch definiert werden. Der EvaluationProcessor legt die erzeugten Ergebnisdaten, bestehend aus den gefundenen Wörtern und zugehörigen Metadaten wie die Confidence, auf Dateiebene ab. Um überprüfen zu können, welches Bild schlussendlich an das Texterkennungssystem übergeben wurde, werden auch die verarbeiteten Bilder nach der Binarisierung gespeichert.
|
||||
Zu Beginn der Ausführung des Kommandozeilenprogramms wird für jedes zu verarbeitende Bild abhängig von den definierten Schwellenwertverfahren eine Reihe von Prozessoren angelegt. Dazu wurde der statische Teil der Bildverarbeitungskette gemäß \autoref{processor_chain_image} innerhalb der "EvaluationProcessor" Klasse definiert, wie in Programm \ref{prg:processor_definition_dynamic} auszugsweise dargestellt. Lediglich die zu evaluierenden Prozessoren für die jeweiligen Schwellwertverfahren können außerhalb der klasse dynamisch definiert werden. Der EvaluationProcessor legt die erzeugten Ergebnisdaten, bestehend aus den gefundenen Wörtern und zugehörigen Metadaten wie die Confidence, auf Dateiebene ab. Um überprüfen zu können, welches Bild schlussendlich an das Texterkennungssystem übergeben wurde, werden auch die verarbeiteten Bilder nach der Binarisierung gespeichert.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
private static IEnumerable<EvaluationProcessor> MakeThresholdVariations()
|
||||
private static IEnumerable<EvaluationProcessor> MakeThresholdVariations()
|
||||
{
|
||||
for (int i = 4; i <= 24; i += 4)
|
||||
{
|
||||
for (int i = 4; i <= 24; i += 4)
|
||||
{
|
||||
yield return new(new ThresholdAdaptiveProcessor(i));
|
||||
}
|
||||
|
||||
for (int i = 20; i <= 80; i += 10)
|
||||
{
|
||||
yield return new(new ThresholdProcessor(i));
|
||||
}
|
||||
|
||||
yield return new(new AutoThresholdProcessor(AutoThresholdMethod.Kapur));
|
||||
yield return new(new AutoThresholdProcessor(AutoThresholdMethod.OTSU));
|
||||
yield return new(new AutoThresholdProcessor(AutoThresholdMethod.Triangle));
|
||||
yield return new(new ThresholdAdaptiveProcessor(i));
|
||||
}
|
||||
|
||||
for (int i = 20; i <= 80; i += 10)
|
||||
{
|
||||
yield return new(new ThresholdProcessor(i));
|
||||
}
|
||||
|
||||
yield return new(new AutoThresholdProcessor(AutoThresholdMethod.Kapur));
|
||||
yield return new(new AutoThresholdProcessor(AutoThresholdMethod.OTSU));
|
||||
yield return new(new AutoThresholdProcessor(AutoThresholdMethod.Triangle));
|
||||
}
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "Program.cs": Definition der Thresholding Prozessoren}
|
||||
\label{program:program_processor_definition_dynamic}
|
||||
\caption{Auszug aus Datei "Program.cs": Definition der Thresholding Prozessoren.}
|
||||
\label{prg:processor_definition_dynamic}
|
||||
\end{program}
|
||||
|
||||
Ist die Erstellung der Bildbearbeitungsprozessoren abgeschlossen, wird jeder einzelne Prozessor über die Systembibliothek "System.Threading.Tasks" als eigene Ausführungseinheit (\engl{Task}) gestartet. In der Kommandozeile wird anschließend der aktuelle Status jedes Tasks angezeigt. Wurden alle Tasks abgeschlossen, wird das Programm beendet.
|
||||
@@ -283,48 +283,48 @@ Ist die Erstellung der Bildbearbeitungsprozessoren abgeschlossen, wird jeder ein
|
||||
|
||||
Wurden die in den jeweiligen Screenshots erkannten Textdaten abgelegt, werden diese Daten im zweiten Kommandozeilenprogramm "ReportGenerator" nun mit den manuell verschlagworteten Daten verglichen und die Ergebnisse in einen Bericht (\engl{Report}) gespeichert.
|
||||
|
||||
Als zentrale Komponente für den Vergleich spielt die Berechnung der in \autoref{metriken} erklärten Metriken eine wesentliche Rolle. Wie in Programm \ref{program:distance_levenshtein} ersichtlich, wird die Distanz zwischen zwei \csharp-Enumerables, seien es zwei Strings oder zwei Listen, über das Verfahren nach Levenshtein berechnet.
|
||||
Als zentrale Komponente für den Vergleich spielt die Berechnung der in \autoref{metriken} erklärten Metriken eine wesentliche Rolle. Wie in Programm \ref{prg:distance_levenshtein} ersichtlich, wird die Distanz zwischen zwei \csharp-Enumerables, seien es zwei Strings oder zwei Listen, über das Verfahren nach Levenshtein berechnet.
|
||||
|
||||
\begin{program}[!ht]
|
||||
\begin{CsCode}[numbers=none]
|
||||
public static double GetDistance<T>(T reference, T? hypothesis)
|
||||
public static double GetDistance<T>(T reference, T? hypothesis)
|
||||
where T : IEnumerable
|
||||
{
|
||||
var refArr = reference.Cast<object>().ToArray();
|
||||
var hypArr = hypothesis?.Cast<object>().ToArray() ?? Array.Empty<object>();
|
||||
{
|
||||
var refArr = reference.Cast<object>().ToArray();
|
||||
var hypArr = hypothesis?.Cast<object>().ToArray() ?? Array.Empty<object>();
|
||||
|
||||
var distance = new int[refArr.Length + 1, hypArr.Length + 1];
|
||||
var distance = new int[refArr.Length + 1, hypArr.Length + 1];
|
||||
|
||||
for (var x = 0; x <= refArr.Length; x++)
|
||||
{
|
||||
distance[x, 0] = x;
|
||||
}
|
||||
|
||||
for (var y = 0; y <= hypArr.Length; y++)
|
||||
{
|
||||
distance[0, y] = y;
|
||||
}
|
||||
|
||||
for (var x = 0; x < refArr.Length; x++)
|
||||
{
|
||||
for (var y = 0; y < hypArr.Length; y++)
|
||||
{
|
||||
var cost = Equals(refArr[x], hypArr[y]) ? 0 : 1;
|
||||
|
||||
var c1 = distance[x, y] + cost; // Bottom left
|
||||
|
||||
var c2 = distance[x, y + 1] + 1; // Top left
|
||||
var c3 = distance[x + 1, y] + 1; // Bottom right
|
||||
|
||||
distance[x + 1, y + 1] = Min(c1, c2, c3); // Top right
|
||||
}
|
||||
}
|
||||
|
||||
return distance[refArr.Length, hypArr.Length];
|
||||
for (var x = 0; x <= refArr.Length; x++)
|
||||
{
|
||||
distance[x, 0] = x;
|
||||
}
|
||||
|
||||
for (var y = 0; y <= hypArr.Length; y++)
|
||||
{
|
||||
distance[0, y] = y;
|
||||
}
|
||||
|
||||
for (var x = 0; x < refArr.Length; x++)
|
||||
{
|
||||
for (var y = 0; y < hypArr.Length; y++)
|
||||
{
|
||||
var cost = Equals(refArr[x], hypArr[y]) ? 0 : 1;
|
||||
|
||||
var c1 = distance[x, y] + cost; // Bottom left
|
||||
|
||||
var c2 = distance[x, y + 1] + 1; // Top left
|
||||
var c3 = distance[x + 1, y] + 1; // Bottom right
|
||||
|
||||
distance[x + 1, y + 1] = Min(c1, c2, c3); // Top right
|
||||
}
|
||||
}
|
||||
|
||||
return distance[refArr.Length, hypArr.Length];
|
||||
}
|
||||
\end{CsCode}
|
||||
\caption{Auszug aus Datei "Calculator.cs": Berechnung der Levenshtein-Distanz}
|
||||
\label{program:distance_levenshtein}
|
||||
\caption{Auszug aus Datei "Calculator.cs": Berechnung der Levenshtein-Distanz.}
|
||||
\label{prg:distance_levenshtein}
|
||||
\end{program}
|
||||
|
||||
Nach der Ermittlung der jeweiligen Distanzen auf Wort- \bzw Bildbasis werden sie mit den jeweiligen Ursprungsbildern, Prozessoren und den verwendeten Algorithmen in Bezug gesetzt. Die so aufbereiteten Ergebnisse werden anschließend an den ReportGenerator übergeben und in einen Bericht zusammengefasst.
|
||||
@@ -0,0 +1,20 @@
|
||||
[
|
||||
"bit",
|
||||
"float",
|
||||
"sie",
|
||||
"wort",
|
||||
"byte",
|
||||
"gewünschte",
|
||||
"das",
|
||||
"string",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"doppelwort",
|
||||
"treibervariable",
|
||||
"variablendefinition",
|
||||
"selektieren",
|
||||
"#:",
|
||||
"archive",
|
||||
"en"
|
||||
]
|
||||
@@ -1,15 +1,12 @@
|
||||
{
|
||||
"words": [
|
||||
"alarm",
|
||||
"group",
|
||||
"prefilter",
|
||||
"static",
|
||||
"enable",
|
||||
"alarm",
|
||||
"group",
|
||||
"prefiltering",
|
||||
"machine",
|
||||
"alarm",
|
||||
"emergency",
|
||||
"stop",
|
||||
"external",
|
||||
|
||||
@@ -0,0 +1,729 @@
|
||||
% $ biblatex auxiliary file $
|
||||
% $ biblatex bbl format version 3.2 $
|
||||
% Do not modify the above lines!
|
||||
%
|
||||
% This is an auxiliary file used by the 'biblatex' package.
|
||||
% This file may safely be deleted. It will be recreated by
|
||||
% biber as required.
|
||||
%
|
||||
\begingroup
|
||||
\makeatletter
|
||||
\@ifundefined{ver@biblatex.sty}
|
||||
{\@latex@error
|
||||
{Missing 'biblatex' package}
|
||||
{The bibliography requires the 'biblatex' package.}
|
||||
\aftergroup\endinput}
|
||||
{}
|
||||
\endgroup
|
||||
|
||||
|
||||
\refsection{0}
|
||||
\datalist[entry]{nty/global//global/global}
|
||||
\entry{asif2014overview}{article}{}
|
||||
\name{author}{4}{}{%
|
||||
{{hash=0c6d6102333ed505cde9090cb5efb093}{%
|
||||
family={Asif},
|
||||
familyi={A\bibinitperiod},
|
||||
given={AMAM},
|
||||
giveni={A\bibinitperiod}}}%
|
||||
{{hash=caacf4e23730d4e17949fcdfa528bb09}{%
|
||||
family={Hannan},
|
||||
familyi={H\bibinitperiod},
|
||||
given={Shaikh\bibnamedelima Abdul},
|
||||
giveni={S\bibinitperiod\bibinitdelim A\bibinitperiod}}}%
|
||||
{{hash=c4e893f95da7cb94bc4bc74acb0ada7f}{%
|
||||
family={Perwej},
|
||||
familyi={P\bibinitperiod},
|
||||
given={Yusuf},
|
||||
giveni={Y\bibinitperiod}}}%
|
||||
{{hash=a6dc6108c0ec8f3f5efe5accd9216cb5}{%
|
||||
family={Vithalrao},
|
||||
familyi={V\bibinitperiod},
|
||||
given={Mane\bibnamedelima Arjun},
|
||||
giveni={M\bibinitperiod\bibinitdelim A\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{e10971541519b8d6feb3c93bf4c3a163}
|
||||
\strng{fullhash}{8ceec1c2c8e343152b232a9265e0b752}
|
||||
\strng{bibnamehash}{e10971541519b8d6feb3c93bf4c3a163}
|
||||
\strng{authorbibnamehash}{e10971541519b8d6feb3c93bf4c3a163}
|
||||
\strng{authornamehash}{e10971541519b8d6feb3c93bf4c3a163}
|
||||
\strng{authorfullhash}{8ceec1c2c8e343152b232a9265e0b752}
|
||||
\field{sortinit}{A}
|
||||
\field{sortinithash}{2f401846e2029bad6b3ecc16d50031e2}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{journaltitle}{Int. J. Adv. Res. Sci. Eng}
|
||||
\field{number}{7}
|
||||
\field{title}{An overview and applications of optical character recognition}
|
||||
\field{volume}{3}
|
||||
\field{year}{2014}
|
||||
\field{pages}{261\bibrangedash 274}
|
||||
\range{pages}{14}
|
||||
\endentry
|
||||
\entry{chowdhary2020natural}{article}{}
|
||||
\name{author}{2}{}{%
|
||||
{{hash=dd466f5693f6e44c544acd7d6a28e1db}{%
|
||||
family={Chowdhary},
|
||||
familyi={C\bibinitperiod},
|
||||
given={KR1442},
|
||||
giveni={K\bibinitperiod}}}%
|
||||
{{hash=8b85e59bf81a08b351c1b0047ffe26df}{%
|
||||
family={Chowdhary},
|
||||
familyi={C\bibinitperiod},
|
||||
given={KR},
|
||||
giveni={K\bibinitperiod}}}%
|
||||
}
|
||||
\list{publisher}{1}{%
|
||||
{Springer}%
|
||||
}
|
||||
\strng{namehash}{54d532863c7e166fafc6619ad499538b}
|
||||
\strng{fullhash}{54d532863c7e166fafc6619ad499538b}
|
||||
\strng{bibnamehash}{54d532863c7e166fafc6619ad499538b}
|
||||
\strng{authorbibnamehash}{54d532863c7e166fafc6619ad499538b}
|
||||
\strng{authornamehash}{54d532863c7e166fafc6619ad499538b}
|
||||
\strng{authorfullhash}{54d532863c7e166fafc6619ad499538b}
|
||||
\field{sortinit}{C}
|
||||
\field{sortinithash}{4d103a86280481745c9c897c925753c0}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{journaltitle}{Fundamentals of artificial intelligence}
|
||||
\field{title}{Natural language processing}
|
||||
\field{year}{2020}
|
||||
\field{pages}{603\bibrangedash 649}
|
||||
\range{pages}{47}
|
||||
\endentry
|
||||
\entry{10.1145/219717.219778}{article}{}
|
||||
\name{author}{2}{}{%
|
||||
{{hash=cd1b3e71c2df8581a083b57279436fb9}{%
|
||||
family={Church},
|
||||
familyi={C\bibinitperiod},
|
||||
given={Kenneth\bibnamedelima W.},
|
||||
giveni={K\bibinitperiod\bibinitdelim W\bibinitperiod}}}%
|
||||
{{hash=fe02760619a80d4d62d1ebc7ee4cbb6c}{%
|
||||
family={Rau},
|
||||
familyi={R\bibinitperiod},
|
||||
given={Lisa\bibnamedelima F.},
|
||||
giveni={L\bibinitperiod\bibinitdelim F\bibinitperiod}}}%
|
||||
}
|
||||
\list{location}{1}{%
|
||||
{New York, NY, USA}%
|
||||
}
|
||||
\list{publisher}{1}{%
|
||||
{Association for Computing Machinery}%
|
||||
}
|
||||
\strng{namehash}{6fbb39470ad61a5355b429e7e037f8be}
|
||||
\strng{fullhash}{6fbb39470ad61a5355b429e7e037f8be}
|
||||
\strng{bibnamehash}{6fbb39470ad61a5355b429e7e037f8be}
|
||||
\strng{authorbibnamehash}{6fbb39470ad61a5355b429e7e037f8be}
|
||||
\strng{authornamehash}{6fbb39470ad61a5355b429e7e037f8be}
|
||||
\strng{authorfullhash}{6fbb39470ad61a5355b429e7e037f8be}
|
||||
\field{sortinit}{C}
|
||||
\field{sortinithash}{4d103a86280481745c9c897c925753c0}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{issn}{0001-0782}
|
||||
\field{journaltitle}{Commun. ACM}
|
||||
\field{month}{11}
|
||||
\field{number}{11}
|
||||
\field{title}{Commercial Applications of Natural Language Processing}
|
||||
\field{volume}{38}
|
||||
\field{year}{1995}
|
||||
\field{pages}{71\bibrangedash 79}
|
||||
\range{pages}{9}
|
||||
\verb{doi}
|
||||
\verb 10.1145/219717.219778
|
||||
\endverb
|
||||
\verb{urlraw}
|
||||
\verb https://doi.org/10.1145/219717.219778
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://doi.org/10.1145/219717.219778
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{eikvil1993optical}{article}{}
|
||||
\name{author}{1}{}{%
|
||||
{{hash=f6a56098c8e007448eff18cf0253ffb7}{%
|
||||
family={Eikvil},
|
||||
familyi={E\bibinitperiod},
|
||||
given={Line},
|
||||
giveni={L\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{f6a56098c8e007448eff18cf0253ffb7}
|
||||
\strng{fullhash}{f6a56098c8e007448eff18cf0253ffb7}
|
||||
\strng{bibnamehash}{f6a56098c8e007448eff18cf0253ffb7}
|
||||
\strng{authorbibnamehash}{f6a56098c8e007448eff18cf0253ffb7}
|
||||
\strng{authornamehash}{f6a56098c8e007448eff18cf0253ffb7}
|
||||
\strng{authorfullhash}{f6a56098c8e007448eff18cf0253ffb7}
|
||||
\field{sortinit}{E}
|
||||
\field{sortinithash}{8da8a182d344d5b9047633dfc0cc9131}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{journaltitle}{citeseer. ist. psu. edu/142042. html}
|
||||
\field{title}{Optical character recognition}
|
||||
\field{volume}{26}
|
||||
\field{year}{1993}
|
||||
\endentry
|
||||
\entry{cc_platforms_comparison}{inbook}{}
|
||||
\name{author}{2}{}{%
|
||||
{{hash=5172656ae4b37ab502657560eaba1def}{%
|
||||
family={Gupta},
|
||||
familyi={G\bibinitperiod},
|
||||
given={Urvashi},
|
||||
giveni={U\bibinitperiod}}}%
|
||||
{{hash=f507b71345da1e9ee7c0a5306de10432}{%
|
||||
family={Sharma},
|
||||
familyi={S\bibinitperiod},
|
||||
given={Rohit},
|
||||
giveni={R\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{bed551397b4d114e4b0e29c4b5e78ced}
|
||||
\strng{fullhash}{bed551397b4d114e4b0e29c4b5e78ced}
|
||||
\strng{bibnamehash}{bed551397b4d114e4b0e29c4b5e78ced}
|
||||
\strng{authorbibnamehash}{bed551397b4d114e4b0e29c4b5e78ced}
|
||||
\strng{authornamehash}{bed551397b4d114e4b0e29c4b5e78ced}
|
||||
\strng{authorfullhash}{bed551397b4d114e4b0e29c4b5e78ced}
|
||||
\field{sortinit}{G}
|
||||
\field{sortinithash}{32d67eca0634bf53703493fb1090a2e8}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{isbn}{978-981-99-3715-8}
|
||||
\field{month}{09}
|
||||
\field{title}{“Comparison of Different Cloud Computing Platforms for Data Analytics”}
|
||||
\field{year}{2023}
|
||||
\field{pages}{67\bibrangedash 78}
|
||||
\range{pages}{12}
|
||||
\verb{doi}
|
||||
\verb 10.1007/978-981-99-3716-5_7
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{islam2017survey}{article}{}
|
||||
\name{author}{1}{}{%
|
||||
{{hash=9a5e1a199b5da8919bcd44582dbe2d03}{%
|
||||
family={Islam},
|
||||
familyi={I\bibinitperiod},
|
||||
given={Noor},
|
||||
giveni={N\bibinitperiod},
|
||||
suffix={Islam},
|
||||
suffixi={I\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{9a5e1a199b5da8919bcd44582dbe2d03}
|
||||
\strng{fullhash}{9a5e1a199b5da8919bcd44582dbe2d03}
|
||||
\strng{bibnamehash}{9a5e1a199b5da8919bcd44582dbe2d03}
|
||||
\strng{authorbibnamehash}{9a5e1a199b5da8919bcd44582dbe2d03}
|
||||
\strng{authornamehash}{9a5e1a199b5da8919bcd44582dbe2d03}
|
||||
\strng{authorfullhash}{9a5e1a199b5da8919bcd44582dbe2d03}
|
||||
\field{sortinit}{I}
|
||||
\field{sortinithash}{8d291c51ee89b6cd86bf5379f0b151d8}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{journaltitle}{arXiv preprint arXiv:1710.05703}
|
||||
\field{title}{A survey on optical character recognition systems}
|
||||
\field{year}{2017}
|
||||
\endentry
|
||||
\entry{kalyanathaya2019advances}{article}{}
|
||||
\name{author}{3}{}{%
|
||||
{{hash=90e983b2663535ac57038ca9080c179b}{%
|
||||
family={Kalyanathaya},
|
||||
familyi={K\bibinitperiod},
|
||||
given={Krishna\bibnamedelima Prakash},
|
||||
giveni={K\bibinitperiod\bibinitdelim P\bibinitperiod}}}%
|
||||
{{hash=db479590e7dbaa96931fc276b485aff3}{%
|
||||
family={Akila},
|
||||
familyi={A\bibinitperiod},
|
||||
given={D},
|
||||
giveni={D\bibinitperiod}}}%
|
||||
{{hash=5ef75dd487083c2ea1d543ead4fa1603}{%
|
||||
family={Rajesh},
|
||||
familyi={R\bibinitperiod},
|
||||
given={P},
|
||||
giveni={P\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{d7b542fcf008e32eb04734bcae0847fd}
|
||||
\strng{fullhash}{d7b542fcf008e32eb04734bcae0847fd}
|
||||
\strng{bibnamehash}{d7b542fcf008e32eb04734bcae0847fd}
|
||||
\strng{authorbibnamehash}{d7b542fcf008e32eb04734bcae0847fd}
|
||||
\strng{authornamehash}{d7b542fcf008e32eb04734bcae0847fd}
|
||||
\strng{authorfullhash}{d7b542fcf008e32eb04734bcae0847fd}
|
||||
\field{sortinit}{K}
|
||||
\field{sortinithash}{c02bf6bff1c488450c352b40f5d853ab}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{journaltitle}{International Journal of Recent Technology and Engineering}
|
||||
\field{number}{5C}
|
||||
\field{title}{Advances in natural language processing--a survey of current research trends, development tools and industry applications}
|
||||
\field{volume}{7}
|
||||
\field{year}{2019}
|
||||
\field{pages}{199\bibrangedash 202}
|
||||
\range{pages}{4}
|
||||
\endentry
|
||||
\entry{karpinski2018metrics}{inproceedings}{}
|
||||
\name{author}{3}{}{%
|
||||
{{hash=509ee8d7156820e2a8345d7c7aa82e3f}{%
|
||||
family={Karpinski},
|
||||
familyi={K\bibinitperiod},
|
||||
given={Romain},
|
||||
giveni={R\bibinitperiod}}}%
|
||||
{{hash=98def5e841e91a9fae5f1771124aeafd}{%
|
||||
family={Lohani},
|
||||
familyi={L\bibinitperiod},
|
||||
given={Devashish},
|
||||
giveni={D\bibinitperiod}}}%
|
||||
{{hash=dfeb4cf44ab9690e8a2e1ab963aa2d01}{%
|
||||
family={Belaid},
|
||||
familyi={B\bibinitperiod},
|
||||
given={Abdel},
|
||||
giveni={A\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{4f6e5dba6a9f04ae36756d2c4708cb22}
|
||||
\strng{fullhash}{4f6e5dba6a9f04ae36756d2c4708cb22}
|
||||
\strng{bibnamehash}{4f6e5dba6a9f04ae36756d2c4708cb22}
|
||||
\strng{authorbibnamehash}{4f6e5dba6a9f04ae36756d2c4708cb22}
|
||||
\strng{authornamehash}{4f6e5dba6a9f04ae36756d2c4708cb22}
|
||||
\strng{authorfullhash}{4f6e5dba6a9f04ae36756d2c4708cb22}
|
||||
\field{sortinit}{K}
|
||||
\field{sortinithash}{c02bf6bff1c488450c352b40f5d853ab}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{booktitle}{IPCV'18-The 22nd Int'l Conf on Image Processing, Computer Vision, \& Pattern Recognition}
|
||||
\field{title}{Metrics for complete evaluation of ocr performance}
|
||||
\field{year}{2018}
|
||||
\endentry
|
||||
\entry{mursari2021effectiveness}{article}{}
|
||||
\name{author}{2}{}{%
|
||||
{{hash=6a39d0ed95e83164f03eaaa7529167d7}{%
|
||||
family={Mursari},
|
||||
familyi={M\bibinitperiod},
|
||||
given={Lily\bibnamedelima Rojabiyati},
|
||||
giveni={L\bibinitperiod\bibinitdelim R\bibinitperiod}}}%
|
||||
{{hash=1258a970837f0a4b20acc3d12472019f}{%
|
||||
family={Wibowo},
|
||||
familyi={W\bibinitperiod},
|
||||
given={Antoni},
|
||||
giveni={A\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{e5bc68f872a0e96a9e33bb2509e97bd0}
|
||||
\strng{fullhash}{e5bc68f872a0e96a9e33bb2509e97bd0}
|
||||
\strng{bibnamehash}{e5bc68f872a0e96a9e33bb2509e97bd0}
|
||||
\strng{authorbibnamehash}{e5bc68f872a0e96a9e33bb2509e97bd0}
|
||||
\strng{authornamehash}{e5bc68f872a0e96a9e33bb2509e97bd0}
|
||||
\strng{authorfullhash}{e5bc68f872a0e96a9e33bb2509e97bd0}
|
||||
\field{sortinit}{M}
|
||||
\field{sortinithash}{4625c616857f13d17ce56f7d4f97d451}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{journaltitle}{Computer Engineering and Applications Journal}
|
||||
\field{number}{3}
|
||||
\field{title}{The effectiveness of image preprocessing on digital handwritten scripts recognition with the implementation of OCR Tesseract}
|
||||
\field{volume}{10}
|
||||
\field{year}{2021}
|
||||
\field{pages}{177\bibrangedash 186}
|
||||
\range{pages}{10}
|
||||
\endentry
|
||||
\entry{levenshtein1966binary}{inproceedings}{}
|
||||
\name{author}{1}{}{%
|
||||
{{hash=5659d6c77daafc2e631e8115c543ee26}{%
|
||||
family={others},
|
||||
familyi={o\bibinitperiod},
|
||||
prefix={and},
|
||||
prefixi={a\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{5659d6c77daafc2e631e8115c543ee26}
|
||||
\strng{fullhash}{5659d6c77daafc2e631e8115c543ee26}
|
||||
\strng{bibnamehash}{5659d6c77daafc2e631e8115c543ee26}
|
||||
\strng{authorbibnamehash}{5659d6c77daafc2e631e8115c543ee26}
|
||||
\strng{authornamehash}{5659d6c77daafc2e631e8115c543ee26}
|
||||
\strng{authorfullhash}{5659d6c77daafc2e631e8115c543ee26}
|
||||
\field{sortinit}{o}
|
||||
\field{sortinithash}{2cd7140a07aea5341f9e2771efe90aae}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{title}{Binary codes capable of correcting deletions, insertions, and reversals}
|
||||
\endentry
|
||||
\entry{park2008empirical}{inproceedings}{}
|
||||
\name{author}{4}{}{%
|
||||
{{hash=603a950e6df5ec35a2bbc0da9c68f6c1}{%
|
||||
family={Park},
|
||||
familyi={P\bibinitperiod},
|
||||
given={Youngja},
|
||||
giveni={Y\bibinitperiod}}}%
|
||||
{{hash=e71c854b2c40e8871d548547c2b4d93e}{%
|
||||
family={Patwardhan},
|
||||
familyi={P\bibinitperiod},
|
||||
given={Siddharth},
|
||||
giveni={S\bibinitperiod}}}%
|
||||
{{hash=29a326b6a3b49ada47e4bfa2da42e070}{%
|
||||
family={Visweswariah},
|
||||
familyi={V\bibinitperiod},
|
||||
given={Karthik},
|
||||
giveni={K\bibinitperiod}}}%
|
||||
{{hash=cf86bb79bbb5c27e245572203ae59d5e}{%
|
||||
family={Gates},
|
||||
familyi={G\bibinitperiod},
|
||||
given={Stephen\bibnamedelima C},
|
||||
giveni={S\bibinitperiod\bibinitdelim C\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{bb6c9f5f15e310c72f8ff07c0e4e6c80}
|
||||
\strng{fullhash}{fd68a92d672c1f4ff0c711aed956a4c2}
|
||||
\strng{bibnamehash}{bb6c9f5f15e310c72f8ff07c0e4e6c80}
|
||||
\strng{authorbibnamehash}{bb6c9f5f15e310c72f8ff07c0e4e6c80}
|
||||
\strng{authornamehash}{bb6c9f5f15e310c72f8ff07c0e4e6c80}
|
||||
\strng{authorfullhash}{fd68a92d672c1f4ff0c711aed956a4c2}
|
||||
\field{sortinit}{P}
|
||||
\field{sortinithash}{ff3bcf24f47321b42cb156c2cc8a8422}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{booktitle}{Interspeech}
|
||||
\field{title}{An empirical analysis of word error rate and keyword error rate.}
|
||||
\field{volume}{2008}
|
||||
\field{year}{2008}
|
||||
\field{pages}{2070\bibrangedash 2073}
|
||||
\range{pages}{4}
|
||||
\endentry
|
||||
\entry{Smith2007}{inproceedings}{}
|
||||
\name{author}{1}{}{%
|
||||
{{hash=70a23f39cf7e5190c2b5f7028971dec9}{%
|
||||
family={R.},
|
||||
familyi={R\bibinitperiod},
|
||||
given={Smith},
|
||||
giveni={S\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{70a23f39cf7e5190c2b5f7028971dec9}
|
||||
\strng{fullhash}{70a23f39cf7e5190c2b5f7028971dec9}
|
||||
\strng{bibnamehash}{70a23f39cf7e5190c2b5f7028971dec9}
|
||||
\strng{authorbibnamehash}{70a23f39cf7e5190c2b5f7028971dec9}
|
||||
\strng{authornamehash}{70a23f39cf7e5190c2b5f7028971dec9}
|
||||
\strng{authorfullhash}{70a23f39cf7e5190c2b5f7028971dec9}
|
||||
\field{sortinit}{R}
|
||||
\field{sortinithash}{5e1c39a9d46ffb6bebd8f801023a9486}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{langid}{ngerman}
|
||||
\field{title}{An Overview of the Tesseract OCR Engine}
|
||||
\field{urlday}{12}
|
||||
\field{urlmonth}{6}
|
||||
\field{urlyear}{2023}
|
||||
\field{year}{2007}
|
||||
\field{dateera}{ce}
|
||||
\field{urldateera}{ce}
|
||||
\verb{urlraw}
|
||||
\verb https://ieeexplore.ieee.org/document/4376991
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://ieeexplore.ieee.org/document/4376991
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{sporici2020improving}{article}{}
|
||||
\name{author}{3}{}{%
|
||||
{{hash=3700c05149e96073a87200c9e4f28ad8}{%
|
||||
family={Sporici},
|
||||
familyi={S\bibinitperiod},
|
||||
given={Dan},
|
||||
giveni={D\bibinitperiod}}}%
|
||||
{{hash=2e4a3cc8ee93e46f58e2a53375e0c8fe}{%
|
||||
family={Cușnir},
|
||||
familyi={C\bibinitperiod},
|
||||
given={Elena},
|
||||
giveni={E\bibinitperiod}}}%
|
||||
{{hash=5f4b8c37d8c848b9926382faf85a337b}{%
|
||||
family={Boiangiu},
|
||||
familyi={B\bibinitperiod},
|
||||
given={Costin-Anton},
|
||||
giveni={C\bibinithyphendelim A\bibinitperiod}}}%
|
||||
}
|
||||
\list{publisher}{1}{%
|
||||
{MDPI}%
|
||||
}
|
||||
\strng{namehash}{f41d33235859d15bd0e7121e5c960e06}
|
||||
\strng{fullhash}{f41d33235859d15bd0e7121e5c960e06}
|
||||
\strng{bibnamehash}{f41d33235859d15bd0e7121e5c960e06}
|
||||
\strng{authorbibnamehash}{f41d33235859d15bd0e7121e5c960e06}
|
||||
\strng{authornamehash}{f41d33235859d15bd0e7121e5c960e06}
|
||||
\strng{authorfullhash}{f41d33235859d15bd0e7121e5c960e06}
|
||||
\field{sortinit}{S}
|
||||
\field{sortinithash}{b164b07b29984b41daf1e85279fbc5ab}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{journaltitle}{Symmetry}
|
||||
\field{number}{5}
|
||||
\field{title}{Improving the accuracy of Tesseract 4.0 OCR engine using convolution-based preprocessing}
|
||||
\field{volume}{12}
|
||||
\field{year}{2020}
|
||||
\field{pages}{715}
|
||||
\range{pages}{1}
|
||||
\endentry
|
||||
\entry{tong1996statistical}{inproceedings}{}
|
||||
\name{author}{2}{}{%
|
||||
{{hash=e34083ac616f8893d9bf5fa6495b804c}{%
|
||||
family={Tong},
|
||||
familyi={T\bibinitperiod},
|
||||
given={Xiang},
|
||||
giveni={X\bibinitperiod}}}%
|
||||
{{hash=56bb189748ed5eb9e94f4a35bf3e6097}{%
|
||||
family={Evans},
|
||||
familyi={E\bibinitperiod},
|
||||
given={David\bibnamedelima A},
|
||||
giveni={D\bibinitperiod\bibinitdelim A\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{e93ec31824795209e5723150931f48ba}
|
||||
\strng{fullhash}{e93ec31824795209e5723150931f48ba}
|
||||
\strng{bibnamehash}{e93ec31824795209e5723150931f48ba}
|
||||
\strng{authorbibnamehash}{e93ec31824795209e5723150931f48ba}
|
||||
\strng{authornamehash}{e93ec31824795209e5723150931f48ba}
|
||||
\strng{authorfullhash}{e93ec31824795209e5723150931f48ba}
|
||||
\field{sortinit}{T}
|
||||
\field{sortinithash}{9af77f0292593c26bde9a56e688eaee9}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{booktitle}{Fourth workshop on very large corpora}
|
||||
\field{title}{A statistical approach to automatic OCR error correction in context}
|
||||
\field{year}{1996}
|
||||
\endentry
|
||||
\entry{the_old_bailey_and_ocr}{inproceedings}{}
|
||||
\name{author}{2}{}{%
|
||||
{{hash=52791bdcfa2c414feb9e9da0988f9901}{%
|
||||
family={Ughetta},
|
||||
familyi={U\bibinitperiod},
|
||||
given={William},
|
||||
giveni={W\bibinitperiod}}}%
|
||||
{{hash=cef3a18f3097ba31cc4cf18c95bfdfbc}{%
|
||||
family={Kernighan},
|
||||
familyi={K\bibinitperiod},
|
||||
given={{Brian W.}},
|
||||
giveni={B\bibinitperiod}}}%
|
||||
}
|
||||
\list{language}{1}{%
|
||||
{English (US)}%
|
||||
}
|
||||
\list{publisher}{1}{%
|
||||
{Association for Computing Machinery, Inc}%
|
||||
}
|
||||
\strng{namehash}{c9b7567765381b82537dcef45a2f48e1}
|
||||
\strng{fullhash}{c9b7567765381b82537dcef45a2f48e1}
|
||||
\strng{bibnamehash}{c9b7567765381b82537dcef45a2f48e1}
|
||||
\strng{authorbibnamehash}{c9b7567765381b82537dcef45a2f48e1}
|
||||
\strng{authornamehash}{c9b7567765381b82537dcef45a2f48e1}
|
||||
\strng{authorfullhash}{c9b7567765381b82537dcef45a2f48e1}
|
||||
\field{sortinit}{U}
|
||||
\field{sortinithash}{6901a00e45705986ee5e7ca9fd39adca}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{booktitle}{Proceedings of the ACM Symposium on Document Engineering, DocEng 2020}
|
||||
\field{month}{9}
|
||||
\field{series}{Proceedings of the ACM Symposium on Document Engineering, DocEng 2020}
|
||||
\field{title}{The Old Bailey and OCR: Benchmarking AWS, Azure, and GCP with 180,000 Page Images}
|
||||
\field{year}{2020}
|
||||
\verb{doi}
|
||||
\verb 10.1145/3395027.3419595
|
||||
\endverb
|
||||
\keyw{Amazon Web Services,Google Cloud Platform,Historical Documents,Microsoft Azure,Old Bailey,Optical Character Recognition}
|
||||
\endentry
|
||||
\entry{wang2003word}{inproceedings}{}
|
||||
\name{author}{3}{}{%
|
||||
{{hash=8d8fdf47a09b680c9071fae4dcc827ba}{%
|
||||
family={Wang},
|
||||
familyi={W\bibinitperiod},
|
||||
given={Ye-Yi},
|
||||
giveni={Y\bibinithyphendelim Y\bibinitperiod}}}%
|
||||
{{hash=f4856677f688ac94b2cb06f12937080f}{%
|
||||
family={Acero},
|
||||
familyi={A\bibinitperiod},
|
||||
given={Alex},
|
||||
giveni={A\bibinitperiod}}}%
|
||||
{{hash=6a68ed902b1be827862f051c9ec5573c}{%
|
||||
family={Chelba},
|
||||
familyi={C\bibinitperiod},
|
||||
given={Ciprian},
|
||||
giveni={C\bibinitperiod}}}%
|
||||
}
|
||||
\list{organization}{1}{%
|
||||
{IEEE}%
|
||||
}
|
||||
\strng{namehash}{af2eaded12f0c9a621340815723e28ba}
|
||||
\strng{fullhash}{af2eaded12f0c9a621340815723e28ba}
|
||||
\strng{bibnamehash}{af2eaded12f0c9a621340815723e28ba}
|
||||
\strng{authorbibnamehash}{af2eaded12f0c9a621340815723e28ba}
|
||||
\strng{authornamehash}{af2eaded12f0c9a621340815723e28ba}
|
||||
\strng{authorfullhash}{af2eaded12f0c9a621340815723e28ba}
|
||||
\field{sortinit}{W}
|
||||
\field{sortinithash}{4315d78024d0cea9b57a0c6f0e35ed0d}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{booktitle}{2003 IEEE workshop on automatic speech recognition and understanding (IEEE Cat. No. 03EX721)}
|
||||
\field{title}{Is word error rate a good indicator for spoken language understanding accuracy}
|
||||
\field{year}{2003}
|
||||
\field{pages}{577\bibrangedash 582}
|
||||
\range{pages}{6}
|
||||
\endentry
|
||||
\entry{bimodal-histogram}{image}{}
|
||||
\name{author}{1}{}{%
|
||||
{{hash=93d707cc77f037fd02e1c8cfa75317cf}{%
|
||||
family={Commons},
|
||||
familyi={C\bibinitperiod},
|
||||
given={Wikimedia},
|
||||
giveni={W\bibinitperiod}}}%
|
||||
}
|
||||
\strng{namehash}{93d707cc77f037fd02e1c8cfa75317cf}
|
||||
\strng{fullhash}{93d707cc77f037fd02e1c8cfa75317cf}
|
||||
\strng{bibnamehash}{93d707cc77f037fd02e1c8cfa75317cf}
|
||||
\strng{authorbibnamehash}{93d707cc77f037fd02e1c8cfa75317cf}
|
||||
\strng{authornamehash}{93d707cc77f037fd02e1c8cfa75317cf}
|
||||
\strng{authorfullhash}{93d707cc77f037fd02e1c8cfa75317cf}
|
||||
\field{sortinit}{C}
|
||||
\field{sortinithash}{4d103a86280481745c9c897c925753c0}
|
||||
\field{labelnamesource}{author}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{title}{Example of a histogram exhibiting bimodalty}
|
||||
\field{urlday}{12}
|
||||
\field{urlmonth}{6}
|
||||
\field{urlyear}{2023}
|
||||
\field{year}{2014}
|
||||
\field{urldateera}{ce}
|
||||
\verb{urlraw}
|
||||
\verb https://commons.wikimedia.org/wiki/File:Bimodal-histogram.png
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://commons.wikimedia.org/wiki/File:Bimodal-histogram.png
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{textract_pricing}{online}{}
|
||||
\list{language}{1}{%
|
||||
{eng}%
|
||||
}
|
||||
\field{sortinit}{A}
|
||||
\field{sortinithash}{2f401846e2029bad6b3ecc16d50031e2}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{day}{23}
|
||||
\field{month}{5}
|
||||
\field{title}{Amazon Textract - Pricing}
|
||||
\field{urlday}{12}
|
||||
\field{urlmonth}{6}
|
||||
\field{urlyear}{2023}
|
||||
\field{year}{2023}
|
||||
\field{dateera}{ce}
|
||||
\field{urldateera}{ce}
|
||||
\verb{urlraw}
|
||||
\verb https://aws.amazon.com/textract/pricing/
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://aws.amazon.com/textract/pricing/
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{azurevision_pricing}{online}{}
|
||||
\list{language}{1}{%
|
||||
{eng}%
|
||||
}
|
||||
\field{sortinit}{A}
|
||||
\field{sortinithash}{2f401846e2029bad6b3ecc16d50031e2}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{day}{23}
|
||||
\field{month}{5}
|
||||
\field{title}{Azure AI Vision - Pricing}
|
||||
\field{urlday}{12}
|
||||
\field{urlmonth}{6}
|
||||
\field{urlyear}{2023}
|
||||
\field{year}{2023}
|
||||
\field{dateera}{ce}
|
||||
\field{urldateera}{ce}
|
||||
\verb{urlraw}
|
||||
\verb https://azure.microsoft.com/en-gb/pricing/details/cognitive-services/computer-vision/
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://azure.microsoft.com/en-gb/pricing/details/cognitive-services/computer-vision/
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{gcv_pricing}{online}{}
|
||||
\list{language}{1}{%
|
||||
{eng}%
|
||||
}
|
||||
\field{sortinit}{G}
|
||||
\field{sortinithash}{32d67eca0634bf53703493fb1090a2e8}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{day}{23}
|
||||
\field{month}{5}
|
||||
\field{title}{Google Cloud Vision - Pricing}
|
||||
\field{urlday}{12}
|
||||
\field{urlmonth}{6}
|
||||
\field{urlyear}{2023}
|
||||
\field{year}{2023}
|
||||
\field{dateera}{ce}
|
||||
\field{urldateera}{ce}
|
||||
\verb{urlraw}
|
||||
\verb https://cloud.google.com/vision/pricing
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://cloud.google.com/vision/pricing
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{imagemagick}{online}{}
|
||||
\list{language}{1}{%
|
||||
{eng}%
|
||||
}
|
||||
\field{sortinit}{I}
|
||||
\field{sortinithash}{8d291c51ee89b6cd86bf5379f0b151d8}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{day}{23}
|
||||
\field{month}{5}
|
||||
\field{title}{ImageMagick Homepage}
|
||||
\field{urlday}{12}
|
||||
\field{urlmonth}{6}
|
||||
\field{urlyear}{2023}
|
||||
\field{year}{2023}
|
||||
\field{dateera}{ce}
|
||||
\field{urldateera}{ce}
|
||||
\verb{urlraw}
|
||||
\verb https://www.imagemagick.org/
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://www.imagemagick.org/
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{tessdoc}{online}{}
|
||||
\list{language}{1}{%
|
||||
{eng}%
|
||||
}
|
||||
\field{sortinit}{T}
|
||||
\field{sortinithash}{9af77f0292593c26bde9a56e688eaee9}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{day}{23}
|
||||
\field{month}{5}
|
||||
\field{title}{Tesseract Documentation}
|
||||
\field{urlday}{12}
|
||||
\field{urlmonth}{6}
|
||||
\field{urlyear}{2023}
|
||||
\field{year}{2023}
|
||||
\field{dateera}{ce}
|
||||
\field{urldateera}{ce}
|
||||
\verb{urlraw}
|
||||
\verb https://tesseract-ocr.github.io/
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://tesseract-ocr.github.io/
|
||||
\endverb
|
||||
\endentry
|
||||
\entry{todo}{online}{}
|
||||
\list{language}{1}{%
|
||||
{eng}%
|
||||
}
|
||||
\field{sortinit}{T}
|
||||
\field{sortinithash}{9af77f0292593c26bde9a56e688eaee9}
|
||||
\field{labeltitlesource}{title}
|
||||
\field{day}{23}
|
||||
\field{month}{5}
|
||||
\field{title}{TODO: MISSING SOURCE}
|
||||
\field{urlday}{4}
|
||||
\field{urlmonth}{1}
|
||||
\field{urlyear}{2024}
|
||||
\field{year}{2023}
|
||||
\field{dateera}{ce}
|
||||
\field{urldateera}{ce}
|
||||
\verb{urlraw}
|
||||
\verb https://example.com/todo
|
||||
\endverb
|
||||
\verb{url}
|
||||
\verb https://example.com/todo
|
||||
\endverb
|
||||
\endentry
|
||||
\enddatalist
|
||||
\endrefsection
|
||||
\endinput
|
||||
|
||||
@@ -59,6 +59,12 @@
|
||||
|
||||
%%%-----------------------------------------------------------------------------
|
||||
|
||||
\babelhyphenation[ngerman]{
|
||||
Text-er-ken-nung
|
||||
}
|
||||
|
||||
%%%-----------------------------------------------------------------------------
|
||||
|
||||
%%%-----------------------------------------------------------------------------
|
||||
\begin{document}
|
||||
\GetTitleStringSetup{expand}
|
||||
@@ -80,8 +86,6 @@
|
||||
|
||||
\advisor{Barbara Traxler MSc}
|
||||
|
||||
%\strictlicense % restriktive Lizenz anstatt Creative Commons (nicht empfohlen!)
|
||||
|
||||
%%%-----------------------------------------------------------------------------
|
||||
\frontmatter % Titelei (röm. Seitenzahlen)
|
||||
%%%-----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user