Der Linienerkennung dient ein aus zwei Teilen gebauter Algorithmus. Der erste Teil ist eine Schleife mit Pipeline, vorgesehen als Vorbereitungsphase, wovon die Ausgabe in zweitem Teil die tatsächliche Linienerkennung ermöglicht. Der Algorithmus wird mit der Methode getLines() in der Klasse Lines aufgerufen. Die Ausgaben von beiden Teilen sind entsprechende Objekte, SupportObject für Vorbereitungsphase und LineContainer für Linienerkennung. Im Allgemeinen sind die verwendeten Methoden eine Mischung von OpenCV und neu geschrieben Funktionen. Die Relationen sind in Bild 1 gezeichnet und die Elemente des Algorithmus in folgendem Text beschrieben.
Der erste Teil des Algorithmus ist ein Vorbereitungsschritt, in dem die Korrektur und Linienisolation durchgeführt werden. Das Pipeline besteht aus sieben Phasen, die aus der Klasse Lines durch einen Aufruf der Methode prepare() in der Klasse Preparation ausgeführt werden. Die Bearbeitung erfolgt auf einer Matrize des Bildes in Mat-Objekt. Die Ergebnisse jeder Transformation sind separat in dem sogennantem SupportObjekt gespeichert. Das ist auch die Ausgabe der prepare()-Methode.
**Die Schleife**
Je nach Ende jedes Schleifendurchlaufs werden die Längen der Hough-Linien, gespeichert in SupportObject, nach Winkel aufsummiert. Die Schleife entspricht einem Versuch, die potentiellen Linien, mit unterschiedlichem Winkel in eine optimale horizontale Position zu bringen. Das heißt, dass die Summe der Längen von den Hough-Linien mit Winkel 0.0 am Ende des Pipelines maximiert wird. Nachdem die beste Lösung gefunden wurde, werden die Hough-Linien zusammen mit dem Winkel in ein neues Objekt, SupportObject, gespeichert und zurück an die Klasse Lines übergeben.
**Linienidentifikation**
In dem zweiten Schritt werden Linien erkannt und gespeichert. Hough-Linien aus dem ersten Schritt werden analysiert und es wird versucht, die Notenlinien daraus zu erkennen. Der Algorithmus vergleicht die kumulative Länge der Hough-Linien und sucht die Konzentrationen auf bestimmter Höhe. Hohe Konzentration bedeutet eine hohe Summe von Längen und somit hohe Wahrscheinlichkeit für eine Linie. Eine bestimmbare Schwelle entscheidet, ob eine Linie erkannt wurde oder nicht. Für jede erkannte Linie werden die naheliegenden Hough-Linien weiter untersucht, um die Länge und Position zu präzisieren. Die Koordinaten einer neuen Linie sind in ein neues Objekt LineObject gespeichert und in eine Liste der anderen, schon identifizierten Linien addiert und als ein weiteres Objekt LineContainer ausgegeben.
Außer binarise() in Binarisation-Klasse und getLines() in Lines-Klasse, Linienidentifikation, sind die Methoden Teil von Klasse Imgproc der OpenCV Bibliotheken. Im Wesentlichen sind die Methoden in ihre eigenen Klassen gegliedert und mit den Parametern verwendet , die in ihren entsprechenden Klassen als Konstanten gesetzt sind.
*Die Rotation*
Die Rotation erfolgt durch das Anwenden von Methoden getRotationMatrix und warpAffine der Klasse Imgproc des OpenCV-Bibliotheken und sorgt dafür , dass die potentiellen Linien in eine horizontale Position gebracht werden. Der Prozess wird in einer separaten Klasse Rotation innerhalb der Methode applyRotation() durchgeführt.
Die Verschwemmung erfolgt in der Klasse Blur der Methode applyBlur(), durch Anwenden von Methode gaussianBlur() mit Linearem Muster von Breite 25 px und Höhe 1 px, und hebt die Linien hervor.
Die Binarisierung basiert auf der Unterscheidung von Helligkeit des Bildes und wird durch die Methode binarise() in der Klasse Binarisation durchgeführt. Eine bestimmte Schwelle gliedert Pixel in zwei Gruppen, welche entsprechend weiss und schwarz gefärbt werden. Der verwendete Wert entspricht der Blauen Farbe des Pixels und funktioniert auch wenn das Bild in Grautönen übergeben würde. Die Binarisierung trennt also potentielle Linien, in der Regel dunkler, von Hintergrund, in der Regel heller.
*Die Erosion und Vergrößerung*
Die Erosion und Vergrößerung, zusammengefasst in der Methode fineAdjust() in der Klasse FineAdjustment, werden die Linien auf Grund eines Musters verfeinert und Störungen entfernt. Hierfür sorgen die Methode morphologyEx() zusammen mit dem Musterelement aus getStructuringElement() der Klasse Imgproc. Das Musterelement hängt von der Bildbreite ab.
Auf dem binarisierten Bild werden dann Hough-Linie mithilfe der OpenCV Methode HoughLinesP(), innerhalb der Methode prepare() in der Oberklasse Preparation gezeichnet. Die Parameter sollten als ein Centil der Breite des Bildes für die Linienlänge und 4 px für die Linienbreite gesetzt werden.
Die Hauptidee für die Verwendung von Objekten, um Ergebnisse zu speichern, liegt in der Erweiterbarkeit und Flexibilität. Mit einer kleinen Ergänzung können Zwischenstufen der Bildtransformation zur Verfügung gestellt werden. Die Notenlinie z.B., ist nicht nur graphisches Element des Bildes, sondern dient auch Orientirung und Abgrenzung von den Notenzeilen. Nach Bedarf können zu den reinen Koordinaten zusätzliche Informationen gespeichert werden.
*SupportObject*
Das Objekt dient zur Speicherung von Transformationen des Originalbildes und enthält unter anderem den Winkel der Rotation und die Hough-Linien. Das Objekt kann mit weiteren Elementen ergänzt werden, um die Zwischenstufen der Transformation darstellen zu können. SupportObjekt wird in dem ersten Teil des Algorithmus verwendet und ist auch dessen Ausgabe.
*LineObject*
In LineObjekt sind die Start- und Endkoordinaten der identifizierten Notenlinien gespeichert. Sie sind innerhalb LineContainer-Objekt in einer Liste gespeichert.
*LineContainer*
LineContainer ist die Ausgabe des Algorithmus für Linienerkennung. Es enthält die Liste der identifizierten Notenlinien.