Interactive Environment

Aus toolbox_interaktion
Wechseln zu: Navigation, Suche

Bei der Projektarbeit „Interactive Environment“ handelt es sich um die Konzipierung und Entwicklung eines OpenSource Basis-Softwaresystems,
das es ermöglicht, verschiedenste Komponenten aus dem Bereich der Interaktion auf standardisierte Weise in Echtzeit zu verknüpfen.

Diese Komponenten können leicht nach systeminternen Aufgabengebieten unterteilt werden:

Zunächst soll es ermöglicht werden, eine einfache Anbindung von Inputs zur Verfügung zu stellen,
um Eingabegeräte wie Sensoren, Webcams, Kinect-Empfänger oder anderweitige Controller
beziehungsweise Eingabegeräte in das System einbinden zu können.

In diesem Zuge werden Analysemodule benötigt, die in der Lage sind, dem Benutzer eine Auswahl von Auswertungsoptionen zu überlassen,
um das Eingangssignal so bearbeiten und interpretieren zu können, dass eine interaktive Handlung mit diesem ermöglicht wird.
Das System muss in der Lage sein, Positionen, Gesten, Veränderungen, Dateiströme oder beispielsweise auch Audiodateien verarbeiten zu können.

Über eine vom Benutzer festlegbare Verknüpfung muss das System einzelne Verarbeitungselemente so bearbeiten können,
dass Mappings mit entsprechender Hintergrundlogik umsetzbar sind.

Des Weiteren stellt die Anwendung die Anbindung von verschiedensten Outputs, wie Beamern, Projektoren, Lasern, Lautsprechern oder auch Dateien
beziehungsweise Protokollen, sicher.

Für die Umsetzung dieses Vorhaben hat es sich das Projektteam zum Ziel gesetzt, eine neuartige, intuitiv bedienbare,
sowie zugleich funktionale Benutzeroberfläche zu entwerfen.
Um sich optisch von anderen Programmen aus dem Interaktionssektor (z.B. EyesWeb, LabVIEW, Max/MSP) abzugrenzen, hat man sich dazu entschlossen,
bewusst auf eine Flusssteuerung mit verbindenden Linien zu verzichten und einen neuen Ansatz gesucht.
Schlussendlich hat man sich auf ein Kreiskonzept verständigt, das über eine schalenbasierte Darstellung Hierarchieabläufe veranschaulicht.

Die Funktionalität wird weitestgehend von openFrameworks bereitgestellt. Dabei handelt es sich um eine Ansammlung von C++ Bibliotheken,
zusammengestellt mit dem Ziel, Entwicklern ein Open Source Framework bereit zu stellen, welches diese in ihrem kreativen Prozess nicht einschränkt,
sondern durch eine Auswahl der beliebtesten Bibliotheken für Einsatzgebiete wie Grafikanwendungen, Audioverarbeitungen oder 3D-Anwendungen, unterstützt.

Interactive Environment
Hauptprojektleiter: Dominik Hertlein
Projektleiter Controller: Fabian Bach
Projektleiter View: Dominik Hertlein
Projektleiterin Anwendung: Bahar Ertem
Mitglieder View: Dominik Hertlein
Leonie Barth
Nina Bühner
Tobias Kuhmann
Mitglieder Controller: Fabian Bach
Natalie Kurz
Mitglieder Anwendung: Natalia Allert
Bahar Ertem
Dorothee Mang

Projektverlauf

Zeitplanung

Für das organisierte Arbeiten ist es essentiell wichtig einen Zeitplan zu erstellen. Der Zeitplan ermöglicht es, Meilensteine zu definieren
und Aufgaben die erledigt werden müssen nicht zu vergessen. Nach dem ersten misslungenen Versuch wurde ein realistischer Zeitplan verfasst
an den es sich von nun an zu richten galt. Bei der Wahl der PMS1 war es für das Team wichtig, dass diese Open-Source
und somit in den meisten Fällen kostenlos ist. Zum anderen sollte sie schnell erlernbar und ohne größere Einarbeitungszeit verwendbar sein.
Zur Auswahl stand folgende Software: „ Codendi“, “GanttProject“, und „Open Proj“.
Letztendlich fiel die Wahl auf GanttProject, da die Software keinen eigenen PHP & MYSQL-Server wie bei OpenProj oder Codendi benötigt,
sondern ein reiner Desktop-Client ist. Durch seine geringe Größe, kann er schnell und problemlos auf jeden Rechner installiert werden
und fordert keine aktive Internetverbindung zur Bearbeitung des Zeitplans.

Brainstorming

In der Brainstormingphase sind sehr interessante Ideen zustande gekommen, aber auch Sachen die gar nicht so einfach zu realisieren wären.
Diese wurden auch Digital auf einer Mindmap dokumentiert. Natürlich mussten einige Dinge auch gleich wieder verworfen werden,
die an sich sehr schöne Ideen waren aber die Möglichkeit im Moment nicht bestand sie umzusetzen.
In dieser Kreativitätsphase wurde hauptsächlich überlegt was man für schöne Dinge tun kann mit dem Programm, welches am Ende realisiert werden soll.
Somit beschäftigte man sich mit dem Konzept des vorhandenen Programms „EyesWeb“. Dies war der erster Anlauf, da dieses Programm von seinen Anwendern
kein sehr positives Feedback bekam. Es war zu unübersichtlich sobald die Paches zu komplex wurden, und die Aufgabe war es, dieses Problem zu umgehen,
also eine schöne Benutzeroberfläche zu schaffen welche leicht bedienbar ist.
EyesWeb unterstützt eine große Anzahl von Eingabegeräten z.B. Kinect, Wii, Mikrofone), aber auch analoge Eingänge (z.B. für physiologische Signale),
um sie zu verarbeiten und sie in einer neuen Form wieder auszugeben.
Das Ziel war es also, sich vom alten Muster EyesWeb komplett zu lösen und neue Wege einzuschlagen.

Inspiration

Es wurden viele Bilder aus der Automobilbranche zusammentragen und überhaupt alle Prestige-Bereichen, in denen Bedienoberflächen eine große Rolle spielen
und sich viele kluge Köpfe damit auseinandersetzen. Noch bessere Lösungen könnte die Natur selbst liefern. Strukturen die jedem so geläufig sind, dass sie kaum auffallen, sei es die Spinne im Netz, die Anordnung der Bienenwaben, die Verästelungen in den Blättern, die sich verfeinern.
Vernetzung kommt nicht nur in der Natur, sondern auch im technischen Bereich vor.

Ein anderer Ansatz war nach den Konzepten anderer Programme zu suchen. Auch dazu haben sich sehr viele unterschiedliche Beispiele gefunden.
Manche Programme verbinden „Elemente“ über eine Timeline. Dies wurde als eine mögliche Lösung für unser „Kabel-Problem“ gesehen.
Es stellte sich jedoch später heraus, dass es mit einem Zeitstrahl nicht möglich ist, alle Blöcke so zu verbinden,
dass der Datenstrom durch alle nötigen Blöcke hindurchfließen kann.

Konzeption

Das grundlegende Ziel der Konzeptionsphase war es, nicht bereits bestehende Produkte zu kopieren, sondern viel mehr aus deren Schwachstellen zu lernen
und den Mut aufzubringen, auf dieser Basis etwas Neuartiges zu erschaffen. Eine wesentliche Schwachstelle der bewährten Systeme ist unserer Meinung nach
das Anzeigen von Beziehungen zwischen verschiedenen Elementen durch Kabelverbindungen, da diese das Gesamtbild mit zunehmender Komplexität des Systems
unübersichtlich und schwer nachvollziehbar erscheinen lassen.

Anhand der Ergebnisse aus der Inspirationsphase wurden von allen Projektteilnehmern erste grundlegende Entwürfe und Scribbles angefertigt, um eigene Ideen und Vorstellungen darstellen zu können. Im Zeitraum dieser Phase entstanden eine Vielzahl verschiedener Ansätze, wie potenzielle Programmoberflächen aussehen beziehungsweise mit welchen Elementen der Benutzer das Programm bedienen könnte.
Schlussendlich konnte sich allerdings nur ein Konzept – das sogenannte „Kreiskonzept“ - durchsetzen, welches von den Studierenden fortan verfeinert und präzisiert wurde.

Da am Anfang der Konzeption der „Verteilerblock“ noch nicht eingeführt war, wurde versucht, die Problematik mit zwei verschiedenen Ansichten zu lösen.

  • Ansicht von oben

In dieser Ansicht können Verbindungen, die direkt untereinander liegen, durch ein kleines Dreieck vom oberen zum unteren Block angezeigt werden.
Der Datenstrom in diesem Kreis fließt von außen nach innen. Die Verbindung von Blöcken, die nicht direkt untereinander liegen, wird in dieser Ansicht nicht angezeigt.

  • 3D Ansicht

Um die Verbindung dieser beiden Blöcke dennoch darstellen zu können, gibt es die 2. Ansicht.
Diese Ansicht zeigt die Kreise sozusagen in „3D“. Dadurch kann die Verbindung des einen Blocks mit einem anderen Block gezeigt werden.

Mit dem Konzept war ein vorhandener EyesWeb Patch gut darstellbar. Allerding werden die Verbindungen in der „3D- Ansicht“ wieder als „ Kabel“ dargestellt,
weshalb der Entwurf nicht sehr geeignet ist.

Projektmanagement

Der Großteil der ersten zeitlichen Projekthälfte wurde ohne einen ernannten Projektmanager durchgeführt. Erst als das Team merkte, dass es für effizienteres Arbeiten und der damit verbundenen klaren Aufgabenverteilung einen Projektmanager braucht wurde eine Wahl durchgeführt. Das Projektteam hat sich zu diesem Zeitpunkt nach den Vertiefungsfächern in zwei Entwicklungsteams eingeteilt, die Gestaltungen und Realisierung der Oberfläche übernahmen die Gruppenmitglieder mit der Vertiefung Audio-und Videotechnik. Das andere Team, das für die eigentliche Programmierung und die Funktionen des Programms verantwortlich ist, übernahmen die Gruppenmitglieder mit der Vertiefungsrichtung Internetprogrammierung. Wir nannten diese zwei Gruppenteile „View“ und „Controller“.
Für jede Teilgruppe wurde zudem ein Manager ernannt. Somit waren die Aufgaben klar verteilt und sinngemäß zu erfüllen. An der Wahl waren alle studierenden Teammitglieder beteiligt. Bei einem Meeting wurden Mitglieder vorgeschlagen und die Wahl durchgeführt. Die ernannten Manager sind Dominik Hertlein für die Untergruppe „View“ und Fabian Bach für die Untergruppe „Controller“. Geplant ist außerdem die Wahl eines Managers für die gesamte Gruppe da sich im nächsten Semester um die Implementierung und die Vereinigung der beiden Komponenten gekümmert werden muss.

Aufgabenverteilung:

Nachdem die Projektmanager ernannt wurden mussten diese die anstehenden Aufgaben für das Team definieren und mit einem Abgabedatum an ein oder mehrere Mitglieder verteilen. Dieser Schritt führte zu einem schnellerem Projektfortschritt und besseren Ergebnissen.

OpenFrameworks

Sobald ein Konzept ausgearbeitet ist, muss entschieden werden, mit welchen Mitteln und Werkzeugen es realisiert werden kann. Das auf C++ basierende Framework „OpenFrameworks“ wurde ausgewählt, da es sich mit den umfangreichen Möglichkeiten in Form von Addons am besten geeignet ist.
Anfangs war es wichtig, dass sich das ganze Projektteam in OpenFrameworks einarbeitet, da es sowohl für die View als auch für die Controller Gruppe notwendig sein wird. Dazu wurde eine Einführung abgehalten um die Grundfunktionen kennenzulernen.
Danach konnten alle Gruppenmitglieder selbst programmieren und die Möglichkeiten testen.

Software-Architektur

Für die Software-Entwicklung ist es wichtig eine Software-Architektur zu entwickeln um später einen funktionierenden Code aus einer Architektur zu erstellen. Die Teilgruppe Controller erhielt Unterstützung durch Prof. Dr. Mahr um die grundlegenden Schritte für eine Software-Architektur zu tätigen. Die vorher erstellten Use-Case Diagramme waren hilfreich für den Anfang, allerdings müssen noch einige Schritte unternommen werden in Form von weiteren Diagrammen die von der groben Strukturierung immer feiner in die unteren Ebenen eintauchen. Es wurde auch ein Klassendiagramm erstellt zu dem Herr Mahr jedoch riet, dies auf später zu verlegen, da ohne eine bessere Oberstruktur noch nicht alle Klassen definiert werden konnten. Er gab uns Anhaltspunkte an denen wir arbeiten müssen und sagte uns, dass wir vom eigentlichen Programmieren noch weit entfernt wären. Wir brauchten erst einmal eine grobe Struktur die dann immer weiter ausgearbeitet werden müsste. Er malte uns jedoch eine Skizze aus der wir viel entnehmen konnten um unseren Plan in die Tat umzusetzen. Er erklärte uns wir sollen mit dieser Architektur weiter in die einzelnen Klassen eintauchen. Schritt für Schritt werden hier die einzelnen Cases weiter ausgearbeitet bis man am Ende eine brauchbare Klassen Architektur hat. Dies ist unser Vorhaben für das kommende Semester.

Requirement Engineering

Aus der Vorlesung Software Engineering im dritten Semester war bekannt, dass bei jedem Projekt im Software Bereich bestimmte Anforderungen erstellt werden müssen in Form eines Requirement-Engineerings. Die Controller Gruppe erstellte Use-Case Diagramme, erarbeitete Use- Case Spezifikationen aus einem gesamt Use-Case Diagramm, bearbeitete ein Volere Dokument, erstellte ein erstes Klassendiagramm und verfasste eine Anforderungsdefinition mit bestimmten Prioritäten. Da die von den Controller Mitgliedern in Einzelarbeit erstellten UseCase Diagramme noch zu ungenau waren, wurde gemeinsam ein gesamt UseCase Diagramm erarbeitet. Auf Rat von Prof. Dr. Mahr wird zu späterem Zeitpunkt ebenfalls ein gesamt UseCase Diagramm zu der Untergruppe View erstellt und mit dem der Controller Gruppe zusammengeführt um ein UseCase Diagramm für das ganze Projektziel zu erhalten.

Zudem sollte eine UseCase Spezifikation erstellt werden, damit wir ein übersichtliches UseCase Diagramm erstellen können. Zudem war diese nötig um Herrn Mahr besser in unser Vorhaben einzuarbeiten. Nachdem jeder für sich ein oder mehrere UseCase Diagramme erstellt hatte, setzen wir uns in der Teilgruppe Controller zusammen und besprachen die einzelnen Ergebnisse. Anschließend definierten wir gemeinsam eine UseCase Spezifikation zur Veranschaulichung unserer Vorgehensweise. So konnten wir das Endergebnis und das finale UseCase Diagramm erstellen und es nachvollziehbarer gestalten.

Die Anforderungsdefinition war ein weiterer wichtiger Bestandteil des Requirement-Engineerings. In diesem Dokument wurden alle Funktionen, welche die zu erstellende Software im Lauf des Projektes erhalten soll, festgehalten und durch Priorisierung in Wichtigkeitsbereiche geteilt.

Eine der wichtigen Aufgaben die zu erfüllen waren, war auch das Erstellen und Ergänzen des Volere Dokuments. Diese Aufgabe übernahmen Natalie Kurz und Natalia Allert, da dies ein ziemlich großes Dokument ist wurde es zwei Personen zugeteilt. Dies ist zwar noch nicht komplett vollständig, jedoch wird noch im nächsten Semester weiter daran gearbeitet und es wird immer wieder aktualisiert und vervollständigt, da sich ja auch ab und an etwas ändert oder etwas Neues dazu kommt. Dieses Dokument ist ähnlich aufgebaut wie ein Pflichtenheft dass man in solchen Entwicklungsarbeiten steht führen sollte. Das Volere ist nur etwas umfangreicher und detaillierter. Jede Anforderung und Definition sind hier genauestens beschrieben und protokolliert.

Prototyp-Programmierung

Nachdem sich die Gruppe auf das Kreiskonzept einigte, begann die View-Gruppe parallel den ersten Prototyp zu entwickeln. Hierbei bekamen sie Hilfe von ihrem Projektbetreuer Johannes Brendel, der sie bei der Entwicklung tatenkräftig unterstützte. Die Idee hierbei war, einen Prototyp zu entwickeln der durch Objektorientierte-Programmierung von Grund auf für spätere Funktionen erweiterbar ist. Dadurch kann der Benutzer erste eigene Systeme erstellen. Der bisherige Prototyp ist in der Lage auf Tastendruck Ringe innerhalb eines Hauptkreises hinzuzufügen und auch wieder zu löschen.

Während der Recherche nach einer geeigneten Programmiersprache zur Erstellung von Benutzeroberflächen, stieß man auf einige Probleme. Es war schwierig einen gewissen Überblick zu bekommen, welche Programmiersprache für unsere Zwecke empfehlenswert wäre. In vielen Internetforen spalteten sich die Meinungen. Einige User empfohlen Java oder QT, andere wiederum Visual C#. Nachdem man sich zu den letztgenannten Vorschlägen einige Beispieloberflächen angesehen hatte, war man mit dem Ergebnis trotzdem nicht zufrieden. Die Bedienflächen wirkten bieder und altbacken.

Nach Absprache mit Herrn Brendel ist man zu der Entscheidung gekommen, das komplette User- Interface in openframeworks zu programmieren. Dadurch besitzen wir mehr Freiheiten in der Erstellung der einzelnen Bedienelemente und sind nicht auf vorhandene Elemente angewiesen. Außerdem spezialisiert sich diese Programmbibliothek besonders auf Projekte wie dem unseren.

Um zu verstehen wie ein solches openframeworks-Projekt aufgebaut ist und auf welche Besonderheiten man achtgeben muss, sah das Team sich die Tutorials auf der offiziellen Homepage an. Später programmierte jeder einzeln anhand dieser Anleitungen erste eigene Programme. Ein weiterer Vorteil von openframeworks sind die zahlreichen Addons.

Usability

Usability ist ein interessantes Themenfeld. Gerade für unser Projekt, da es von althergebrachten sehr stark abweicht. Um unser Kreiskonzept in unseren Anfängen vorzustellen und uns Meinungen von Experten einzuholen, hatten wir eine Besprechung mit den Leitern des Usability-Labors. Anhand eines Signals und seines funktionalen Verlauf im Eyes-Web dem wir unser Kreiskonzept gegenüberstellten, erklärten wir das Prinzip unserer Anwendung. Die Resonanz fiel zurückhaltend aus, da unser grafisches Modell in seiner starren grafischen Anordnung auch seine Tücken hat. Auch trafen wir den Design-Professor, Experte für interaktive Oberflächen, der uns den Rat gab, unsere Oberfläche mit Pappe nachzubilden. Im neuen Semester werden wir unser Engagement in dieser Richtung noch verstärken und es sollen dann auch tatsächliche Tests im Usability-Labor gemacht werden.

Ausblick

Für das nächste Semester gilt es, an dem Gelernten dieses Semesters anzuknüpfen, niemals das Ziel vor Augen zu vergessen und konsequent zu arbeiten. Der Prototyp muss weiterentwickelt und zu einer ausgereiften Benutzeroberfläche gestaltet werden. Ein ordentlicher Usability Test muss zeitnah vollzogen werden um den Projektverlauf positiv zu beeinflussen. Die Software- Architektur muss vervollständigt und fortgeführt werden und eine Zusammenführung der Arbeiten der Controller und View Gruppen muss erfolgen. Am Projektmanagement muss weitergehend gearbeitet werden um nicht wieder in ein Tief einzusinken.









Software und Technik

Die typische Herangehensweise zur Entwicklung einer Softwarearchitektur bestehend aus der Formulierung von Use-Cases, Aktivitätsdiagrammen, Klassendiagramm und der abschließenden Implementierung behielt auch das Team bei.

Use Cases

Um ein besseres Verständnis der Funktionen unserer Software zu bekommen und um die Benutzer des Systems zu definieren, haben wir Use-Case Diagramme erstellt.
Bereits in der ersten Projekthälfte wurden Use Cases sowohl in Diagramm- als auch in Text-Form ausgearbeitet. Sie dienten vor allem zur Festlegung des Funtionsumfangs des Projektes. In der zweiten Hälfte des Projektes wurden die Use Cases noch einmal überarbeitet und ergänzt.

Hauptaktionen

Wie auf der Abbildung „Use-Case auf Hauptaktionen reduziert“ zu sehen ist, haben wir zwei Arten von Usern. Zum einen den Benutzer, zum anderen den Komponist. Diese User unterscheiden sich darin, dass der Benutzer einen Patch ausschließlich benutzt, ihn also lediglich abspielt. Der Komponist hingegen kann sowohl den Patch benutzen als auch einen Patch komponieren. Er hat die Möglichkeit einen neuen Patch zu erstellen. Um die Use-Cases übersichtlicher zu gestalten, haben wir sie hierarchisch aufgebaut. Dabei haben sich zwei Hauptfunktionen herauskristallisiert. Die Funktionen „Patch benutzen“ und „Patch komponieren“. Diese Use-Cases haben wir dann in neuen weiteren Use-Cases genauer dargestellt.


Patch benutzen

Wie auf dem Bild links zu sehen ist, kann „Patch benutzen“ von beiden Akteuren ausgeführt werden. „Patch benutzen“ beinhaltet weitere Funktionen. Möchte man also einen Patch ausführen, kann man das System starten und natürlich auch beenden, den Patch laden und ausführen sowie anhalten und schließen, wenn man mit der Ausführung fertig ist.


Patch ausführen

Der dazugehörige Use-Case ist auf dem rechten Bild zu sehen. Wählt man die Funktion „Patch ausführen“, hat man als weitere Funktionalität die Veränderung der einzelnen Parameter zur Auswahl, um zum Beispiel nur einen bestimmten Frequenzbereich von einem Audiosignal zu erhalten.


Patch komponieren

Einen Patch erstellen kann nur der Komponist-Akteur, somit haben wir bei „Patch komponieren“ nur einen User. Wer einen neuen Patch baut, hat viele verschiedene weitere Möglichkeiten in dem Sys-tem. Man hat zum Beispiel die Möglichkeit, einen Patch zu erstellen und zu speichern.


Patch editieren

Möchte man einen vorhandenen Patch editieren, hat man weitere Funktionen zur Auswahl, wie einen neuen Block zu erstellen, zu löschen oder seine Eigenschaften zu ändern.


Blockeigenschaften ändern

Solche Eigenschaften sind unter anderem die Änderung der Größe des Blockes, seiner Position sowie der Ein- und Ausgangsverbindungen. Des Weiteren kann ein Komponist einen Block an- und abwählen ebenso wie die Arbeitsfläche zoomen oder auf der Arbeitsfläche scrollen.


Aktivitätsdiagramme

Um die Funktionen noch weiter verfeinern zu können und somit eine Schnittstellendefinition zwi-schen der View- und der Kern-Komponente zu finden, beschlossen wir in Absprache mit Prof. Dr. Mahr zusätzlich Aktivitätsdiagramme zu erstellen. Grund hierfür war, dass bei Use-Cases keine de-taillierte Darstellung möglich ist, diese aber bei Aktivitätsdiagrammen gegeben ist. Ein solches Dia-gramm ist ein Verhaltensdiagramm. Es beschreibt grafisch den Ablauf eines Anwendungsfalles und bezieht Daten- und Kontrollflüsse mit ein.

Auf dem obigen Bild ist beispielhaft das Aktivitätsdiagramm für „Patch ausführen“ zu sehen. Das Diagramm ist von oben nach unten zu lesen und zeigt die unterschiedlichen zeitlichen Abläufe und alle Eventualitäten einer Handlung. Die Abläufe haben dasselbe Ziel trotz der unterschiedlichen Handlungswege.

Begriffsmodell und Klassendiagramm

Neben der funktionalen Analyse (Use Cases, Aktivitätsdiagramme) wurde parallel ein zweiter Ansatz zur Architekturmodellierung über ein Begriffsmodell versucht.

Definition

Ein Begriffsmodell besteht aus den fachlichen Begriffen des Anwendungsbereiches. Diese werden in Generalisierungs- und Kompositionsbeziehungen zueinander gesetzt. Diese Begriffe und Beziehungen werden dann in einem Klassendiagramm veranschaulicht. Mithilfe der oben genannten Methoden wurden Begriffszuweisungen erzielt, um ein gemeinsames Verständnis der Benennungen zu gewährleisten.

Brainstorming

Wir setzten uns im Team zusammen und schrieben alle Begriffe auf, die uns für die Klassen und Methoden in unserer Software einfielen und welche wir bisher auch schon benutzten. In diesem Schritt konnten so die Begriffe eindeutig Klassen oder Methoden zugeordnet werden. Eine Aufteilung in View und Kern wurde erst in den Klassendiagrammen umgesetzt.

Klassendiagramm

Die gesammelten Begriffe aus dem Begriffsmodell wurden nun den zwei Systemkomponenten zugewiesen.
Die View-Komponente beinhaltete alle Begriffe, die Elemente beschrieben, die auf der Oberfläche zu sehen sein sollten. Beispiele hierfür sind die Navigationsleiste und die Dialogfenster.
Alle Begriffe, die der Funktionalität der Software dienen oder von der Software gebraucht werden, wurden dem Kern der Software zugewiesen. Begriffe wie Patch, Subpatch oder Blockeigenschaften wurden in das Klassendiagramm des Kerns übernommen.

Systemarchitektur

Der erste Ansatz einer Implementierung namens „Interacitve Environment V1 (und „Interactive Environment V1_1“) scheiterte daran, dass versucht wurde Verbindungen zwischen den Blöcken als eigene Klasse zu realisieren.
Nach einer weiteren Überarbeitung wurde ein neuer Ansatz verfolgt:
Von den Bausteinen (Blöcken), welche der User später verwendet um seine Idee zu realisieren, gibt es drei verschiedene Arten:
Eingangsblöcke sind mit Inputs außerhalb der Systemgrenzen verknüpft. Meist sind das Sensoren wie zum Beispiel eine Kamera oder ein Mikrofon. Sie bilden den Anfang einer Verbindungskette.
Ausgangsblöcke sind mit Outputs außerhalb der Systemgrenzen verknüpft. Dies sind meist Aktoren wie zum Beispiel ein Bildschirm oder Lautsprecher. Sie bilden das Ende einer Verbindungskette.

Verarbeitungsblöcke werden nur innerhalb der Systemgrenzen mit Blöcken jeder Art verbunden. Sie werten den eingehenden Datenstrom aus oder manipulieren ihn und stellen das Ergebnis für weitere Blöcke wieder zur Verfügung. Sie bilden so den Mittelteil einer Verbindungskette.
Jeder Block besteht aus Ports und einem Logikteil.

Block - Aufbau

Ein Port kann einen Eingang oder einen Ausgang darstellen.
Je nach Art besitzt ein Block nur Ausgänge (Eingangsblock), nur Eingänge (Ausgangsblock), oder bei-des (Verarbeitungsblock).
Wird ein Block erstellt, so erstellt der Block seine zugehörigen Ports. Durch die Verwendung von Templates ist es möglich jedem Port seinen Datentyp mitzuteilen. Ein Ausgang vom Typ FLOAT liefert entsprechend Daten vom Typ FLOAT und sollte nur mit einem Eingang vom gleichen Typ verbunden werden, da sonst Laufzeitfehler entstehen. Dies wird sichergestellt, indem bei der Herstellung einer Verbindung auf Datentypgleichheit überprüft wird. Sollte es sich um unterschiedliche Datentypen handeln wird der Verbindungsvorgang abgebrochen.
Der Logikteil eines Blockes holt sich alle notwendigen Daten an seinen Eingängen ab, verarbeitet diese, und stellt die Ergebnisse an den Ausgängen wieder zur Verfügung.

Software-Prototyp-Programmierung

Bereits in der ersten Projekthälfte wurde sich für die Programmiersprache C++ entschieden, damit das frei verfügbare Framework openFrameworks zur einfachen Ansteuerung von Sensoren und Aktoren verwendet werden kann.
Die ersten Versuche „Interactive Environment V1“ und „Interactive Environment V1_1“ enthielten eine Klasse zur Darstellung einer Verbindung. Dieser Ansatz wurde recht bald verworfen, da auffiel, dass es auch ohne extra Klasse sondern einfach mit den Pointern und Nullpointern aus C++ realisierbar war. Außerdem wurde versucht die Programmierarbeit auf mehrere Personen aufzuteilen. Das Ergebnis waren mehrere schwer kombinierbare Codefragmente. Für die weiteren Versionen wurde gemeinsam in einer Gruppe gearbeitet. Die Entwicklungsumgebung wurde dazu meist über einen Beamer für alle sichtbar projiziert damit jeder mitbekommt was genau gemacht wird. Ideen wurden auf Tafeln, Overheads oder Flipcharts gesammelt. Eine Person saß an der Tastatur und baute die in der Gruppe überlegten Codezeilen ein. Bei größeren Problemen wurde von allen Teilnehmern über weitere Geräte nach Lösungen recherchiert. Auf diese Weise wurden nur sehr wenige Fehler gemacht und ein sehr stabiles Ergebnis erzielt. Hierbei wurde das von Herrn Prof. Dr. Mahr vorgeschlagene Konzept für eine Architektur (siehe Klassendiagramm) implementiert.

BETA

Die erste funktionsfähige Version von „Interactive Environment“ wurde „BETA“ genannt. Hierbei handelt es sich um eine Implementierung, mit der man mathematische Berechnungen mit Blöcken realisieren kann. Dabei wurde Herrn Prof. Dr. Mahrs Architektur-Vorschlag als Grundlage genommen.
Die Klassen „Eingang“ und „Ausgang“ erben jeweils von der Klasse „Port“. Da aus diese Klassen die konkreten Ein- und Ausgängen entstehen, steht zu diesem Zeitpunkt noch nicht fest, welchen Datentyp der Eingang empfangen und der Ausgang weitergeben kann. Herr Prof. Dr. Mahr gab uns den Tipp als Hilfe templates zu verwenden. Dieses template kann dann bei dem konkreten Ein- oder Ausgang durch einen Datentyp ersetzt werden. Dadurch ist es auch möglich, später noch weitere Blöcke problemlos hinzuzufügen.
Die BETA-Version beinhaltet vier Blöcke, die Zahlen miteinander addieren.
Jeder einzelne Block erbt von der Block-Klasse. Diese Klasse besitzt die Funktion „update()“, die regelmäßig die Werte verarbeitet und den Wert im Ausgang aktualisiert. Sie ruft die dazu nötigen Funktionen auf. Die „update()-Funktion“ wird wiederum in der „update()-Funktion“ von openFramworks aufgerufen, da damit garantiert wird, dass sie regelmäßig ausgeführt wird.
Die Eingangsblöcke stellen jeweils einen oder mehrere Werte in ihrem Ausgang bereit. Diese werden vom Eingang des nächsten Blockes geholt.
Der erste Block ist der „EingangsBlock_Zufallszahl“. Dieser generiert eine zufällige Zahl.
Der zweite Block ist der „EingangsBlock_Hochzaehler“. Er zählt die Zahl, die an seinem Eingang liegt, um eins hoch.
Der dritte Block ist der „AusgabeBlock_Konsole“. Er schreibt den endgültigen Wert auf die Konsole.
Der vierte Block ist der „VerarbeitungsBlock_Addierer“. Er ruft an allen seinen Eingängen die Funktion „gebeWert()“ auf. Diese Funktion ist in der Klasse „Eingang“ implementiert und ruft die Funktion „aktualisiereWert()“ auf. Diese Funktion wiederum ruft die Funktion „gebeWert()“ des mit dem Eingang verbundenen Ausgangs auf. Der Ausgang übergibt dann dem Eingang den Wert, der in der Variable „wert“ gespeichert ist. Dieser gibt ihn über die Funktion „gebeWert()“ an den „VerarbeitungsBlock_Addierer“. So werden auch in allen anderen Blöcken die Werte geholt.
Der „VerarbeitungsBlock_Addierer“ addiert die beiden Werte („EingangsBlock_Zufallszahl“ + „EingangsBlock_Hochzaehler“) und speichert sie in seinem Ausgang.
Dieser Wert wird dann vom „AusgabeBlock_Konsole“ geholt und auf der Konsole ausgegeben.

GAMMA

Die endgültige Interactive Environment-Version in diesem Projekt wurde „GAMMA“ genannt.
In dieser Version gibt es, wie schon in der BETA-Version, ebenfalls eine Block-Klasse, von der die konkreten Blöcke erben. Diese Klasse hat die Funktionen „eingangHinzufuegen(Eingang* e)“ und „ausgangHinzufuegen(Ausgang* a)“ mit der jeweils die Ein- und Ausgänge zu einem konkreten Block hinzugefügt werden können. Außerdem gibt es die „update()-Funktion“, die jeder konkrete Block implementieren muss und die in der openFramworks-Funktion „testApp::update()“ aufgerufen wird. Diese Funktion kümmert sich um alle Berechnungen. Die Funktion „draw()“ wird in der openFrameworks-Funktion „testApp::draw()“ aufgerufen. Die „draw()-Funktion“ ist für alles zuständig, was gezeichnet werden muss, jedoch dürfen in ihr keine Werteberechnungen stattfinden. Die Funktion „trigger(int key)“ wird aufgerufen, wenn eine bestimmte Taste gedrückt wurde. Die Funktion „verbinde (int eingangsIndex, Block *block, int ausgangsIndex)“ verbindet den Eingang dieses Blocks mit einem Ausgang des vorherigen Blocks. Die Klasse „Block“ enthält zudem noch die Vektoren mit den Ein- und Ausgängen eines Blocks, die mit Getter-Funktionen abgefragt werden können, und eine Bezeichnung des Blocks.
Die Klasse „PortImpl“ ist die Elternklasse für die Klassen „Eingang“ und „Ausgang“ und definiert ein template, das den Datentyp, der vom Port bereitgestellt oder empfangen wird, repräsentiert. Dadurch muss erst beim konkreten Block festgelegt werden, welche Datentypen die jeweiligen Ein- und Ausgänge empfangen und weitergeben können.
Die Klasse „AusgangImpl“ erbt von „PortImpl“ und hat als Datentyp, den der Ausgang weitergeben kann ein template. Sie besitzt einen Vektor, in dem alle Eingänge, mit dem der Ausgang verbunden ist, gespeichert sind. Dies ist wichtig, um, falls ein Ausgang gelöscht wird, vorher alle Verbindungen mit diesem Ausgang zu trennen. Die Funktion „daten()“ gibt einen Pointer auf die bereitgestellten Daten zurück. Die Funktion „verbinden()“ speichert einen Eingang im Vektor und die Funktion „trennen()“ löscht einen Eingang aus dem Vektor.
Die Klasse „EingangImpl“ erbt ebenfalls von „PortImpl“ und hat als Datentyp, den der Eingang empfangen kann, ebenfalls ein template. Jeder Eingang kennt einen Ausgang, mit dem er verbunden ist. Ist er mit keinem Ausgang verbunden, ist der Ausgang ein Nullpointer. Die Funktion „istKompatibel(const Ausgang& ausgang) überprüft, ob der Ausgang, mit dem verbunden werden soll, mit diesem Eingang kompatibel ist.
Die Klassen „Eingang“ und „Ausgang“ sind jeweils das Interface für die Klassen „EingangImpl“ und „AusgangImpl“.
Die Blöcke werden in der „testApp-Klasse“ von openFramworks deklariert und die Blöcke untereinander werden ebenfalls in dieser Klasse verbunden.
Dabei wird von einem Block die „verbinde-Funktion“ aufgerufen und als Parameter wird der Index des Eingangs (Bezeichnung für den Datentyp), der Block, mit dessen Ausgang verbunden wird, und der Index des Ausgangs mit dem der Eingang verbunden wird übergeben. Diese Funktion ruft die „verbinden-Funktion“ des Eingangs auf und übergibt ihr den zu verbindenden Ausgang. Die Funktion „verbinden(AusgangsImpl<T>& _ausgang) speichert den Ausgang und ruft wiederum die „verbinden-Funktion“ des Ausgangs, mit dem verbunden wird, auf. Diese Funktion speichert den Eingang, mit dem der Ausgang verbunden wird, in dem „Eingaenge-Vektor“.
Wenn das Programm geschlossen wird, wird für jeden Block der Destruktor aufgerufen. Dieser löscht alle Ein- und Ausgänge, die er besitzt. Dadurch werden die Destruktoren der Ein- und Ausgänge aufgerufen. Der Destruktor der Klasse „EingangImpl“ ruft die „trennen-Funktion“ auf. Dort wird überprüft, ob der Eingang mit einem Ausgang verbunden ist. Ist dies der Fall, wird die „trennen-Funktion“ des Ausgangs aufgerufen und der Ausgang auf einen Nullpointer gesetzt. Der Ausgang löscht den Eingang aus seinem Vektor. Im Destruktor der Klasse „AusgangImpl“ wird über alle Eingänge iteriert und für jeden Eingang ebenfalls die „trennen-Funktion“ des Eingangs aufgerufen.

Codedokumentation

Alle Klassen und Methoden wurden im Doxygen Stil dokumentiert um anschließend mit Hilfe des Doxygen-Parsers eine ausführliche Dokumentation in einem einfach lesbaren Format (HTML) generieren zu können.
Die Klassendiagramme wurden in „Enterprise Architect“ erstellt, da wir nach kurzer Zeit feststellten, dass wir mit dem anfänglich verwendeten Tool „ArgoUML“ schnell an dessen Grenzen stoßen.
Diese dienten vor allem zur Kontrolle, können aber auch zur Veranschaulichung verwendet werden.
Teilweise wurde „Reverse Engineering“ angewendet, also Diagramme aus dem geschriebenem Code generiert.


Beispielanwendung

Um die erstellte Architektur zu testen und auch zu demonstrieren wurden kleine Anwendungen erstellt, welche das System auf die Art und Weise nutzen, wie es später einmal von der Benutzer-oberfläche aus geschehen soll.
Die Version „BETA“ hatte verschiedene Blöcke um Zufallszahlen zu generieren, mit einem Hochzähler zu verrechnen und in der Konsole auszugeben.
Da das Beispiel mit den Zahlen zwar zu Testzwecken ausreichte aber für eine Demonstration doch sehr unspektakulär wirkte, wurde ein interessanterer Anwendungsfall gefunden:
In einem Echtzeit Videobild, von zum Beispiel einer Webcam, wird der Hintergrund (bzw. alle sich nicht ändernden Bildbereiche) durch ein anderes, von der Festplatte geladenes Bild ersetzt. Betritt zum Beispiel eine Person das Bild, so stellt diese eine Veränderung dar, also wird der Bildbereich der Person nicht durch das neue Bild ersetzt. Es wirkt als würde die Person ausgeschnitten und auf das neue Bild gesetzt. Diese Beispielanwendung wurde in der aktuellsten Version „GAMMA“ umgesetzt.


Interface Design

Konzeption

Moodboard

Im User Interface Design spielen Moodboards eine wichtige Rolle. Sie sorgen für eine Klärung von Interaktionselementen, geben eine Übersicht über Zusammenhänge der einzelnen Komponenten und zeigen kompakt ein visuelles Konzept auf. Es werden Anmutungen vermittelt, die in verbaler oder in Textform nur unter großem Aufwand umgesetzt werden können. Auch sollen Moodboards Raum für die Findung von neuen Ideen lassen und durch die Neuanordnung oder das Austauschen von Elementen neue Ansätze entstehen lassen.
Zur Layout Entwicklung und Farbgestaltung nutzten wir ein solches Mood Board. Einige Auszüge sind im Folgenden zu finden. Wichtig erschien, viele Informationen in ein zurückhaltendes, übersichtliches und klares Layout zu integrieren. Wichtiger Bestandteil ist auch die Wahl der Bedienelemente und Controls um eine eindeutige und benutzerfreundliche Umgebung schaffen zu können.


Moodboard.png

Abbildung: Auszüge aus dem Moodboard

Storyboard

Storyboards werden in der Software- und Interfaceentwicklung verwendet, um eine Visualisierung von Benutzerschnittstellen darstellen zu können. Üblich ist es dabei eine Folge von Bildschirminhalten zu visualisieren. Die Storyboards bilden dabei eine Vorstufe von Papierprototypen.
Für den konkreten Anwendungsfall unserer Projektarbeit war es dabei nötig, die textuell ausformulierten Use Cases in visueller Form darzustellen, um das Verständnis für die einzelnen Systemprozesse zu fördern, die für den Benutzer benötigten Materialien und Tools der Interaktion zu klären und um zu verifizieren, dass die gesamte Programmfunktionalität auch von der Oberfläche unterstützt und angezeigt beziehungsweise steuerbar ist.
Ein Auszug der erstellten Dokumente ist anschließend aufgeführt.

Storyboard1.png

Abbildung: Klärung der Oberflächeneinteilung durch Storyboards



Storyboard2.png

Abbildung: Klärung der möglichen Bereitstellung von Interaktionselementen zur Erstellung von Projekten



Storyboard neu2.png


Abbildung: Teil der späteren Überarbeitung des Steuermodus anhand der erkenntnisse aus dem Usability Test



Storyboard neu.png

Abbildung: Mögliche Umsetzung eines Steuermodus Vorschau- und steuerungsbereich für Audioverarbeitungen

Klickbarer Prototyp

Um unsere Storyboards und Konzeptvorschläge an Probanden testen zu können, musste ein klickbarer Prototyp erstellt werden. Essentielle Funktionen, Elemente und Ansichten sollten hier dargestellt werden, um ein ausdrucksstarkes Ergebnis erhalten zu können. Umso realistischer sich ein Prototyp darstellt, desto intuitiver arbeitet der Tester mit der Software. Auf dem Markt gibt es die unterschiedlichsten Tools, die es nun zum Vergleichen und Testen gab. Schlussendlich fiel die Entscheidung auf Balsamiq Mockups.

Balsamiq.png

Abbildung: Balsamiq Mockups


Das schnelle Erstellen von Konzeptskizzen für Benutzerinterfaces (GUI Mockups) ist hier kein Problem. Per Drag and Drop lassen sich verschiedene skalierbare Vorlagen typischer Interface-Elemente auf der Arbeitsfläche anordnen und begrenzt in ihrem Aussehen anpassen. Beispielhaft sind Navigationsleisten und Tabs. Auch externe Bibliotheken aus der Balsamiq-Community lassen sich kostenlos aus dem Internet herunterladen und problemlos einbinden. Eigene Bilder und Graphiken können ebenso verwendet werden. Die handgemalte Anmutung der Bedienelemente fällt sofort auf und ist typisch für Balsamiq Mockups. Der Eindruck einer ausgestalteten Oberfläche wird somit nicht vermittelt. Die Logik des Aufbaus rückt somit in den Vordergrund, die visuellen Feinheiten des Designs werden hinten angestellt. Der Editor ermöglicht das Erstellen verschiedener Seiten, die durch die einzelnen Elemente miteinander verlinkt werden können. An diesen Stellen kann man dann im Vollbildmodus klicken und gelangt zur verbundenen Seite. Durch diese Möglichkeit entsteht der Eindruck echter Funktionalität. Ein aussagekräftiger Test ist somit möglich und durchführbar.
Der Balsamiq- Prototyp bestand letztendlich aus 34 Seiten, die die verschiedenen Modi und Elementarprozessphasen zeigen. Der erste Screen zeigt den sehr reduzierten Startbildschirm. Ein Orientierungsfenster ist neben drei Buttons zu sehen. Es ermöglicht dem Nutzer seinen aktuellen Orientierungspunkt auf dem Screen wieder- und sich somit zurechtzufinden.

Prototyp3.png

Abbildung: Prototyp - Startbildschirm


Alle vier Elemente sind in einer Reihe am oberen Bildschirmrand angeordnet. Ein weiterer Screen zeigt die Hilfe, die durch den Button mit dem Fragezeichen erreicht werden kann. Die Reiter auf der linken Seite unterteilen die Themen in einzelne Kategorien.

Prototyp2.png

Abbildung: Prototyp - Hilfe


Über das Dokument-Symbol ist es möglich ein neues Projekt zu starten, zu laden, zu speichern oder auch zu schließen. Der Play-Knopf wird erst zu einem späteren Zeitpunkt benötigt. Mit einem Klick auf ein neues Projekt erscheint in der Mitte des Bildschirms ein Kreis mit Kreisschalen. Durch nebenstehendes Plus bzw. Minus können Schalen hinzugefügt oder entfernt werden.

Prototyp1.png

Abbildung: Prototyp – Neues Projekt


Prototyp4.png

Abbildung: Prototyp - Bibliothek


Um die Schalen mit Inhalt zu füllen, benötigt man eine entsprechende Bibliothek. Mit einem Klick auf die linke Lasche, erscheint sie wiederum in verschiedene Kategorien gegliedert und unterteilt. Die Farben verdeutlichen die Abgrenzung zwischen den Bereichen.

Ein Beispiel ist das erste Fach, das für die Kategorie der Inputs jeglicher Art steht (Audioeingang, Videoeingang usw.) Per Drag and Drop kann man nun den gewünschten Block auf der ebenso gewünschten Schale platzieren. Balsamiq unterstützt dieses interaktive Bedienelement allerdings nicht. Wir mussten dies also mithilfe eines Klicks umsetzen. Der platzierte Block passt sich nun der Kreisschale direkt an. Man kann im Falle eines Videoinputs nun einen blauen Block sehen. Auf ihm erkennt man zudem ein Video- und ein Informations- Icon. Mit einem erneuten Mausklick auf letzteres Symbol, erscheint ein zusätzliches Menü auf der rechten Seite des Bildschirms. Hier kann der User gewünschte Einstellungen tätigen. Typische Optionen zum gewählten Beispiel sind hier die Wahl des Farbraums oder der Interpolation.

Prototyp5.png

Abbildung: Prototyp - Verbindungen

Nun sollte ein zweiter Block platziert werden, um das Verbindungskonzept testen zu können. Wir wählten folgendes Beispiel. Zwischen zwei Blöcken liegt eine leere Schale. Um diese nun verbinden zu können, benötigen wir wieder unsere Bibliothek. An unterster Stelle entdeckt man den Verbindungsblock mit dem "Link"-Symbol in schwarzer Farbe. Per Drag and Drop muss dieser auf die leere Schale gezogen werden um anschließend abermals unter dem Informations- Icon das rechte Menü zu öffnen.


Dort kann man die gewünschten Blöcke nun auswählen und verbinden. Ein rotes Kreuz erscheint so lange, bis zwei mögliche Verbindungen ausgewählt sind. Erst dann leuchtet ein grüner Haken auf und man kann die Auswahl bestätigen. Um diesen Patch nun starten und abspielen zu können, benötigen wir nun den Play-Button aus der oberen Leiste. Mit einem Mausklick an besagter Stelle, wechselt nun der Editormodus zum Steuermodus. Statt eines Popup-Fensters wird allerdings die ganze Oberfläche ausgetauscht.

Prototyp6.png

Abbildung: Prototyp - Steuermodus


Die obere Leiste besteht auch hier aus drei Buttons, die in einem Bereich mit dem Namen Kontrolle eingegrenzt sind. Darunter folgt der Parameter-Bereich und eine Live-Ansicht. Der Steuermodus erinnert an einen normalen virtuellen Audioplayer. Beim genaueren Hinsehen erkennt man, dass der erste Knopf bereits angewählt ist. Visualisiert ist das durch das schwarz ausgefüllte Dreieck. Der Player ist also gestartet.
Weiter rechts findet man noch jeweils einen Pause und einen Stop-Knopf. Die Parameter sollen dem User die Möglichkeit geben in zeitgleicher Ausgabe und Feedback das Ergebnis ändern zu können. Mit einem Mausklick auf den Stop-Button erscheint auf der linken Seite in der Kontrolle ein Zurück-Pfeil, der es dem User ermöglicht zurück zum Editormodus zu wechseln. Dort kann man sein fertiges Projekt dann beispielsweise speichern, schließen oder ein neues laden. Diverse Pop-Up Fenster öffnen sich, die zum Beispiel die Pfadeingabe ermöglichen.

Usability Test

Nach der Fertigstellung des Prototyp wurde mit dem hochschulinternen Usability Engineering Center ein Termin für einen Usability Test und ein geeignetes Testmodell gesucht.

Durchführung

Der Test bestand aus mehreren, voneinander unabhängigen Teilen, die folgend beschrieben werden.


Eingeleitet wurde die Durchführung des Tests mit dem Vorlegen eines Instruktionsbogens. Dieser sollte die Probanden über das System informieren und auch einige, für die anschließende Bearbeitung der Aufgaben benötigte, eventuell unverständliche Fachbegriffe genauer erläuterten. Im an-schließenden ersten Teil des Tests wurden die Probanden gebeten, eine kurze Aufgabenstrecke zur Navigation durch das durch interaktive PDF-Seiten gestaltete Programm zu navigieren. Die Probanden sollten dabei stets kommentieren, welche Erwartungen, Eindrücke oder eventuell auch Wünsche während der Benutzung entstehen. Die Äußerungen der Probanden wurden entsprechend während des Testdurchlaufs protokolliert. Die Navigation durch den Programmablauf handelte dabei sämtliche wichtigen und zentralen Prozesse ab, die von Systemseite dem Benutzer zur Verfügung gestellt werden. So sollten die Benutzer die Programmhilfe öffnen, ein neues Projekt anlegen, die Anzahl der zur Bearbeitung zur Verfügung stehenden Kreisschalen verändern, Funktionselemente aus der Bibliothek auswählen und zum Kreis hinzufügen, eine Verbindung zwischen den aus der Bibliothek aus-gewählten Elementen herstellen, die Parameter der ausgewählten Elemente verändern, die erstellte Anwendung starten und anschließend wieder beenden und das gesamte Projekt speichern und schließen.


Im zweiten Teil des Tests sollten die Probanden einen Fragebogen ausfüllen, der Aufschluss über das subjektive Empfinden der Benutzer hinsichtlich des Look and Feel der Programmoberfläche ermöglichen sollte. 

Der dritte Testteil sollte Rückschlüsse auf die Verständlichkeit des Kreiskonzeptes geben. Man ent-#schied sich dafür, den Probanden dabei eine Projektdarstellung nach dem Kreiskonzept sowie drei klassische, mit Kabelverbindungen dargestellte Schaltskizzen vorzulegen. Von den drei Schaltskizzen waren zwei mit verschiedenen Fehlern versehen worden, so dass nur eine dieser Skizzen deckungs-gleich mit der Darstellung in Kreisform war. Dieses Paar sollte von den Probanden gefunden werden.

Usetest1.png

Abbildung: Die für den Usability Test ausgewählte Darstellung nach dem Kreiskonzept mit der korrekten Schaltskizze


Usetest2.png

Abbildung: Eine der während des Tests vorgelegten, fehlerhaften Schaltskizzen


Während der erste Testteil von dem Eyetracking System des Usability Labors aufgezeichnet wurde, hielt das Projektteam mangels Alternativen den dritten Teil durch Videoaufnahmen fest.

Auswertung

Im Anschluss an den Test galt es, die gewonnen Daten und Erkenntnisse zu sortieren und zu analysieren, Trends zu erkennen und Schlüsse für die weitere Entwicklung der Oberfläche zu ziehen.


Die Aufgabenstrecke hat aufgezeigt, dass die allgemeine Orientierung an der Oberfläche gut funktioniert hat. Den Benutzern war im Regelfall schnell bewusst, welche Navigationselemente für ihr Vor-haben relevant waren und wie diese Elemente korrekt eingesetzt werden mussten. Verbesserungs-potential wurde an manchen Stellen erkannt, da Symbole und deren Anordnungen, in erster Linie die Lasche zur Öffnung der Bibliothek, teilweise nicht oder erst sehr spät wahrgenommen wurden und daher eine Störung im Workflow bedeuteten. Der Steuermodus hatte ebenfalls Schwachstellen. Die Probanden konnten nicht immer genau feststellen, in welchem Stadium – gerade ausgeführt oder gestoppt – sich ihre Anwendung momentan befand. Des Weiteren wurde teilweise nicht verstanden, wie man aus dem Steuermodus zurück in die Editoransicht gelangt. Auch wurde der Wunsch geäußert, im Editormodus Verbindungen durch das Ziehen von Elementen auf andere Elemente im Kreis erstellen zu können. Diese Erkenntnisse und Verbesserungsvorschläge wurden vom Projektteam in weiteren Arbeitsschritten berücksichtigt und entsprechend dokumentiert.

Usetest3.png

Abbildung: Exportierte Eyetracking Auswertung eines Probanden während der ersten Orientierung an den Navigationselementen


Usetest4.png

Abbildung: Exportierte Eyetracking Auswertung eines Probanden während des Auswählens von Funktionalität aus der Bibliothek

Die generellen Aussagen, die aus den Befragungsbögen gewonnen werden konnten, waren zunächst, dass der Test in Umfang und Schwierigkeitsgrad als angemessen empfunden wurde, somit also ein repräsentatives Testergebnis erreicht werden konnte. Außerdem wurde von den Probanden die Orientierung und Verständlichkeit des Programmaufbaus als allgemein zufriedenstellend, an manchen Stellen aber verbesserungswürdig, bewertet. In Verbindung mit den Aussagen der Probanden während der Bearbeitung der Befragungsstrecke wird klar, dass das Programm den Nutzer während des Arbeitsprozesses noch mehr unterstützen könnte, etwa durch optische Hervorhebungen oder textuelle Einblendungen beziehungsweise Rückmeldungen. Auch weitere Farbsignale für das Festlegen von gültigen oder ungültigen Eingabe, etwa für die Parametereinstellungen von Verbindungen, sind als Neueinführungen an dieser Stelle denkbar.

Auswertung.png

Abbildung: Auswertung der Bewertungsbögen in Tabellenform


Die Auswertung der Videoaufnahmen lieferte ein durchweg positives Ergebnis. Jeder der sechs Pro-banden war in der Lage, die Darstellung in Kreisform lesen und interpretieren zu können. Dabei gelang es allen Testteilnehmern, das gesuchte Paar innerhalb einer akzeptablen Zeit zu finden. Eine Probandin konnte dieses gar innerhalb von zwölf Sekunden ausfindig machen. Insgesamt war dieses Testergebnis sehr zufriedenstellend, da bis zu dem Zeitpunkt des Testes noch nicht abschließend beurteilt werden konnte, in wie fern neue, unbedarfte Benutzer mit der Darstellung im Kreiskonzept zurechtkommen würden und ob es sie eventuell in ihrem Arbeitsprozess behindern könnte. So kann man aber davon ausgehen, dass diese Bedenken unbegründet waren und die Grundlage für eine weitere Ausarbeitung der Oberfläche gelegt worden ist.

Design

Layoutentwürfe

Nach den gewonnen Erkenntnissen der vorangegangen Arbeitsschritte ging es schließlich daran, sich mit dem zukünftigen Layout und Interface-Design auseinander zu setzen. Neben der Funktionalität und Anordnung der Elemente geht es natürlich auch darum, dem User ein freundliches und angenehmes Umfeld zu schaffen. Bedienbarkeit und Benutzerfreundlichkeit werden hier direkt integriert und nochmals in den Fokus des Nutzers gesetzt. Auch die Ergebnisse der letzten Konzeptionsanhänge wurden hier berücksichtigt. Wir entschieden uns für Keynote und PowerPoint als Tool der Entwicklung. Einzelne Elemente wurden allerdings mit Adobe Photoshop und Illustrator entwickelt und in das Gesamtbild eingefügt. Als erstes entstand im Hintergrund ein Farbverlauf von links oben nach rechts unten in den Tönen weiß und grau. Als weitere Möglichkeit die gleiche Oberfläche mit konstantem Hintergrund.

Layout1.png

Abbildung: Entwurf mit Farbverlauf


Bei den Buttons entschieden wir uns zunächst für eine metallisch glänzende Oberfläche, die wir mit Photoshop herstellten. Ein eingedrückter Button ist ganz links zu sehen, um auch diesen Fall zu berücksichtigen. Bei der Bibliothek fiel die Entscheidung auf eine runde Form, um unser innovatives Kreissystem aufzugreifen. Die Library an sich wurde um ein Suchfeld mit einer kleinen Lupe erweitert. Links daneben entstand ein Scrollbalken. Des Weiteren entschieden wir uns für eine eindeutige Kennung und setzten den Schriftzug "Bibliothek an die obere Grenze des Bogens". Der Kreis für den Patch wurde zunächst in Blau gehalten, da ein Farbklecks im tristen Grau wünschenswert erschien. Nach mehreren unterschiedlichen Farben fiel die Entscheidung letztendlich doch auf eine einheitliche Farbgebung. Auch die Bibliothek für die Parametereinstellung ist nun von Beginn an sichtbar und vertikal beschriftet. Nur kleine Anpassungen bekamen das Orientierungsfenster und das Submenü der Controls. Auch für diese Problematik der Lesbarkeit und Benutzerfreundlichkeit wurden unterschiedliche Lösungen erstellt.

Layout2.png

Abbildung: Lösungsvorschläge für geschlossene Fenster

Da die Buttons mit der metallisch glänzende Ummantelung sehr herausstachen und nicht zum matten Rest passten, folgte eine erneute Überarbeitung der Buttons. Statt den Buttons entschied ich mich für viereckige größere Platten, die sich im gedrückten Zustand in ein dunkles Grau einfärben.

Layout3.png

Abbildung: Lösungsvorschläge für Buttons

Der User erlangt hiermit sein gewünschtes Feedback. Um das Zusammenspiel der neuen Buttons mit den anderen Elementen zu sehen, gibt es auch hier verschiedene Versionen. Als zweiter Teil folgte nun der Steuermodus. Hier war es zunächst sehr schwer, die einzelnen Elemente in ein harmonisches Gesamtbild zu integrieren. Dementsprechend entstanden hier wieder mehrere Versionen, um diese mit dem restlichen Team besprechen und verbessern zu können. Im nächsten Bild ist die Umsetzung der Echtzeit-Bildausgabe zu sehen.

Layout4.png

Abbildung: Steuermodus - Video


Links ist der Miniaturkreis zu sehen, der direkt die Parameteranzeige überlappt. Auch dort ist ein Scrollbalken zu finden, um somit alle möglichen Eigenschaften unter einen Hut zu bekommen. Direkt neben der Kontrolle am oberen Bildschirmrand ist der Editorpfeil zu finden, durch den man problemlos in zum anderen Modus zurückgelangt. Kontrolle und Bildausgabe sind beschriftet. Als Platzhalter ist die Silhouette eines Menschen zu sehen.
Da das bestehende Konzept aus dem letzten Semester die Option der austauschbaren Oberflächen beinhaltet, wurde nun auch noch in die Richtung verschiedener Farbschemata gedacht. Je nach Geschmack kann der User nun zum Beispiel auch die hellblaue Oberfläche wählen und mit dieser arbeiten.

Layout5.png

Abbildung: Hellblaues Farbschema

Icons

Um das Gesamtbild zu vervollständigen, mussten verschiedene Piktogramme entwickelt werden. Adobe Illustrator bietet entsprechende Werkzeuge. Es ist sehr wichtig, dass die Zeichen selbsterklärend sind und intuitiv verstanden werden. Des Weiteren sollten Sie nicht zu sehr von dem abweichen, was der Mensch kennt und gewöhnt ist. Auch dies fördert die Benutzerfreundlichkeit und Bedienbarkeit einer Software und Oberfläche.

Neben einer dezenten Oberfläche sollte noch ein passendes Logo entwickeln werden. Im Anbetracht des schlichten Programms wurde auf verspielte Details verzichtet und ein Logo mit dezentem Kreissymbol erstellt. Der ausgeschriebene Name erklärt die Abkürzung IE. Ein hellgrauer Kreis um das Logo greift harmonisch die runde Welt des Interactive Environment auf.

Bildschirmfoto 2013-08-02 um 19.30.59.png

Abbildung: Logoentwurf

Interaktive Anwendung

Konzept

Geplant war eine kleinere Gruppe, die sich parallel zum Hauptprojekt mit einer kleinen Anwendung beschäftigen sollte, die das repräsentiert was am Ende mit unserem Hauptprogramm gemacht werden könnte. Die Anwendung war schon zu Beginn sehr ideenreich auch von Seiten der anderen Gruppenmitgliedern und des Projektbetreuers. Zu Beginn wurden Mindmaps erstellt, die dann zu einer gesamten Mindmap zusammengeführt wurden. Die Mindmap war als Überblick gedacht, in der Ideen und Vorstellungen zu beispielsweise benötigtem Technischen Equipment zusammengeführt waren. Das Konzept war eine interaktive Anwendung, die mit der Kinect realisiert werden sollte. Diese liest und verarbeitet eine Bewegung und verarbeitet diese und gibt einen interaktiven Output, der mittels Beamer an die Wand projiziert werden soll. So war anfangs die Idee. Zu diesem Output wurden Storyboards gezeichnet. Die Ideen der Anwendungsgruppe waren Schattenspiele, die Special Effects auslösen, aber auch Töne, Farben und Linien können z.B. durch eine Bewegung interessante Eindrücke hervorrufen.
Eine Tänzerin die interaktiv mit unserer Anwendung eine Art Show auf die Bühne bringen sollte, bot sich durch den Kontakt mit den Projektbetreuern an.
Durch sie kam die Idee, mit einer Abdeckplane zu arbeiten, da es sicher interessant aussehen würde, auf darauf verschiedene Effekte zu projizieren.
Im Anschluss an die Konzeptfindung war es Ziel einerseits die Ideen mit kleinen Testversionen auf ihre Tauglichkeit zu überprüfen und gleichzeitig eine gute Lösung zu finden, wie die Anwendung entwickelt werden sollte.

Mindmap














Tools

EyesWeb

Für die Umsetzung der Anwendung galt es nun ein Tool auszuwählen mit dem das Vorhaben realisiert werden kann. Es wurde das Anwendungsprogramm „Eyes-Web“ zu Beginn ausgewählt. Es war bereits durch die frühere Vertiefungsrichtung im 3. Semester bekannt.
Es besteht aus Inputs und Outputs und die verschiedenen Komponenten werden mit Kabeln verbunden.
Allerdings hat EyesWeb auch seine Macken und Grenzen. Nachdem mit bestehenden EyesWeb Patches, wie beispielsweise „Sandwelten“, experimentiert wurde, stellte sich raus, dass bei komplexeren Ideen schnell die Grenzen erreicht waren. Somit musste ein anderes Tool her, mit dem unsere Wünsche realisiert werden konnten.

Touchdesigner

TouchDesigner wurde empfohlen. Also hieß es erst mal, sich in TouchDesigner einzuarbeiten. Bevor allerdings viel Einarbeitung betrieben werden konnte, wurde diese Idee verworfen, da nicht sicher war, ob TouchDesigner EyesWeb komplett ersetzen kann.

Openframeworks

Letzten endlich wurde beschlossen, die Anwendung mit Hilfe der Bibliothek von OpenFrameworks zu programmieren. Da letztes Semester bereits Einarbeitungen stattgefunden hatten und die beiden anderen Teilgruppen ebenfalls mit OpenFrameworks arbeiteten, wurde diese Idee als die plausibelste befunden. Auf unserem Leihrechner konnte nach mehreren Versuchen die OpenFrameworks Bibliothek mit Hilfe der Entwicklungsumgebung „Code Blocks“ verwendet werden. Allerdings wurde die Kinect nicht erkannt. Nach vielen Bemühungen wurde zwar erreicht, die Kinect mit dem Rechner zu verbinden, allerdings funktionierte das Ganze nicht im Zusammenspiel mit Code Blocks. Da dies alles problemlos an Bahar Ertems MacBook funktionierte, beschlossen wir direkt darauf zu programmieren, mit der Entwicklungsumgebung XCode in Verbindung mit den Addons der OpenFrameworks Bibliothek.

Vom Konzept zum Code

Die Konzeptionsphase nahm mehr Zeit in Anspruch als ursprünglich erwartet. Viele Ideen waren vorhanden aber die Einarbeitung in die Tools kostete viel Zeit. Die Technischen Schwierigkeiten, die anfangs mit der Installation der Kinect Kamera auf dem Windows Rechner waren, warfen den Zeitplan etwas zurück. Nachdem diese behoben waren, stand die Einarbeitung in die Tools an. Das größte Problem war mit OpenFrameworks einen Einstieg zu finden. Um nicht mehr Zeit zu verlieren, half Johannes Brendel beim Start. Hierbei lief leider auch nicht alles glatt, da es mehrere Fehler im Code unmöglich machten, das Partikelsystem anzuwenden.
Gelöst wurde dieses Problem, indem mit einzelnen Pixeln gearbeitet wurde, die um eine Kontur wanderten. Es sollte eine Person vor einer weißen Wand stehen und von der Kinect erfasst werden. Auf die Wand werden nun die Pixel projiziert die um diese Person gebildet werden. Diese Einstellungen haben nicht so geklappt, wie geplant, die Projektion war meist kleiner als die Person und der Schatten der Person vor der Kinect wurde ebenfalls auf die Wand geworfen. Ein mobiler Beamer sollte Abhilfe schaffen. Die Projektion sollte so angepasst werden, dass der Schatten der Person direkt auf die Kontur der Projektion fällt. Dies hatte leider nicht funktioniert. Die Funktionen, die im Code eingebaut waren, um den Output so zu modifizieren, um Einstellungen leichter vorzunehmen, klappte in der Anwendung nur unzureichend.
Am Ende des Semesters filmten wir bei der Videoaufnahme nur den Output, da auch die Person in der Dunkelheit kaum zu erkennen war.

Programmierung

Die finale Version des Codes funktioniert, indem die Kinect den Input liefert. Dieses Bild wird bearbeitet und am Ende als Output wieder ausgegeben diesmal allerdings mit den Pixeln um die Kontur der aufgenommenen Person.
Nachdem das Programm startet, erscheint zunächst der Debug-Modus. Dieser Modus zeigt vier Graustufenbilder die anfangs identisch sind. Diese Bilder lassen sich mit Hilfe verschiedener Operationen bearbeiten und ergeben einen Output, der dann im Anzeige-Modus als Kontur mit Pixel wiedergegeben werden kann.
Für die weitere Verarbeitung sind vier Graustufenbilder nötig, das erste Bild links oben zeigt die reale Aufnahme, also den Input.
Das zweite Bild rechts oben ist der „Threshold Far“. Es zeigt den höchsten Schwellwert der Tiefenferne der Kinect.
Das dritte Bild links unten ist das Gegenstück zum zweiten Bild und stellt den „Threshold Near“ dar, der den Grenzbereich der Nähe der Kinect aufnimmt.
Das letzte Bild rechts unten vereint den „Threshold Far“ und den „Threshold Near“, um dann die Kontur ermitteln zu können.
Zu Beginn sind alle Bearbeitungsschritte, wie das Aktivieren des Weichzeichners oder des Schwellwertes auf false gesetzt, also nicht aktiv.

Startbild

Im Code wurden verschiedene Tasten definiert um die Einstellungen vornehmen zu können. Die Taste ‚b’ aktiviert den Weichzeichner (Blur) um die Kontur geschmeidiger zu machen. Mit der Taste „t“ wird der Threshold aktiviert, also die Schwellwerte in denen die Kinect aufnimmt. Um den Winkel der Kinect per Tastendruck verändern zu können, wurden die Tasten „w“ und „s“ belegt um die Kinect nach oben und nach unten steuern zu können. Des Weiteren war eine Vollbildfunktion nötig um vor allem den Anzeige-Modus übersichtlicher darstellen zu können. Diese Funktion wird durch die Taste „f“ ausgelöst. Darüber hinaus können die Blobs, die gefunden werden durch Drücken der Taste „c“ angezeigt werden. Die Blobs werden mit einem pinken Kasten umrandet. Auf dem unteren Foto sieht man wie die Kontur als Ganzes als Blob erkannt wurde und türkis umrandet ist. Um die Kontur herum ist ein pinker Kasten der dynamisch mitgeht je nachdem wie groß der ermittelte Blob ist.
Im Anzeigemodus kann dann mit den Tasten „+“ und „-“ die Kontur vergrößert werden um sie bei- spielsweise bei der Projektion besser an die real aufgenommene Person anpassen zu können. Die Pfeiltasten werden für das Verschieben der Output Anzeige verwendet. Bewegungen nach links und rechts, sowie nach oben und unten sind möglich. Durch Drücken der Taste „a“ werden die Verschiebungsschritte vergrößert, um eine schnellere Anpassung möglich zu machen.
Diese Funktionen, die den Tasten zugewiesen wurden, befinden sich im Quellcode in der „testApp.cpp“ bei der Methode für „keyReleased“. Diese Funktionen werden also ausgeführt, sobald die Taste losgelassen wird. Dies stellt eine bessere Möglichkeit dar, als „keyPressed“.
Der Quellcode teilt sich auf in die Files „main.cpp“, „testApp.h“ und „testApp.cpp“. Die beiden zusätzlichen Files „Partikel.h“ und „Partikel.cpp“ waren für das ursprüngliche Partikelsystem vorgesehen, finden allerdings in der finalen Version keine Verwendung. Aus den OpenFrameworks Addons verwendeten wir „ofxOpenCV“ und „ofxKinect“. „ofxKinect“ sorgt für die Erkennung der Kinect.

Main.cpp

Die „main.cpp“ ist ein vorgegebenes File von OpenFrameworks, in dem wir nicht viel hinzufügen mussten. Die Bildschirmgröße unseres Output Windows wird hier definiert und angepasst.

#include "ofMain.h"
#include "testApp.h"
#include "ofAppGlutWindow.h"
 
int main( ){
 
    ofAppGlutWindow window;
	ofSetupOpenGL(&window, 1024,750, OF_WINDOW);			// <-------- setup the GL context
 
	// this kicks off the running of my app
	// can be OF_WINDOW or OF_FULLSCREEN
	// pass in width and height too:
	ofRunApp( new testApp());
 
}

Testapp.h

Auch das Header File ist von OpenFrameworks vorgegeben und muss nur angepasst und ergänzt werden. Hier werden alle Variablen deklariert, die im Code benötigt werden. In unserem Code sind Breite und Höhe des Kinect Bildes Graustufenbilder. Der ContourFinder dient dazu, um die Silhouette zu ermitteln. Schwellwerte, Variablen verstellen den Winkel der Kinect. Ein Weichzeichner und die entsprechenden Variablen definieren den Output Bildes.

#pragma once
 
#include "ofMain.h"
#include "ofxKinect.h"
#include "ofxOpenCv.h"
#include "Partikel.h"
#define MAXPARTICLES 1000
 
class testApp : public ofBaseApp{
 
	public:
		void setup();
		void update();
		void draw();
 
		void keyPressed  (int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
 
        int w; // Breite des Kinect Bildes
        int h; // Höhe des Kinect Bildes
 
        void exit();
 
private:
    ofxKinect kinect;
    ofxCvGrayscaleImage grayscaleImgInput;
    ofxCvGrayscaleImage grayscaleImgFar;
    ofxCvGrayscaleImage grayscaleImgNear;
    ofxCvGrayscaleImage grayscaleImgOutput;
    ofxCvContourFinder contourFinder;
 
 
    int thresholdFar, thresholdNear; //Schwellwerte
 
    int angle;                  //Winkel Kinect
    bool isThreshold;           //Schwellwert
    bool isBlur;                //Weichzeichner
    bool isContour;             //Silhoutte 
    bool isDebug;               //Umschalten in Debug Modus
 
    vector<Partikel*> PartikelSystem;           //PartikelSystem ist Vektor mit Pointer auf Partikel
 
    int numParticles;                           //Anzahl Partikel
    std::vector<Partikel*>::iterator itP;
 
    int screenH, screenW;           //Variablen um Screen vergrößern/verkleinern zu können
 
    float scale;                    //Variable zur Skalierung
    int transX, transY;             //Variablen für Verschiebung
    bool bigger;                    //Nötig um Verschiebungsschritte vergrößern zu können bei Bedarf
    int step;                       //Verschiebungsschritte
 
    int maxNewParticles;            //Anzahl Partikel die maximal erzeugt werden können
    int numNewParticles;            //Anzahl Partikel die wir erzeugen möchten
    int stepSize;                   //Abtastschritt an Kontur
 
};

Testapp.cpp

Der Code startet mit der Setup Methode. Diese wird nur einmal zu Beginn des Programmes aufgerufen. Sie ist dazu da, die vom Header deklarierten Variablen zu initialisieren. Durch „kinect.init()“ und „kinect.open() wird die Kinect initialisiert, das Programm erkennt daran, ob die Kinect angeschlossen und funktionsfähig ist und verbindet sich mit ihr.

#include "testApp.h"
 
void testApp::setup(){
 
    //Kinect initialisieren
    kinect.init();
    kinect.open();


Da der Winkel der Kinect dynamisch per Tastendruck veränderlich sein soll, wurde eine Abfrage des Kinect Winkels eingebaut.

    angle = kinect.getCurrentCameraTiltAngle();

Die von der Kinect vorgegebenen Werte „kinect.width“ und „kinect.height“ werden in die vom Header deklarierten Variablen „w“ und „h“ gespeichert.
Das Startbild nach dem Kompilieren sind vier einzelne Bilder in einem Anzeigefenster die ohne Farbe als Graustufenbilder wiedergegeben werden.

// Initialisierung des Graustufenbilds
    w = kinect.width;
    h = kinect.height;
    grayscaleImgInput.allocate(w, h);
    grayscaleImgFar.allocate(w, h);
    grayscaleImgNear.allocate(w, h);
    grayscaleImgOutput.allocate(w, h);

In diesem AnfangsModus, DebugModus getauft, können per Tastendruck nun verschiedene oben erwähnten Modi aktiviert werden, die die Anzeigebilder verändern.
Das vierte Bild stellt eine Zusammenfassung des zweiten und dritten Bildes dar, somit sieht man vorab was von der aufgenommenen Person durch die Schwellwerte durchkommt und als Kontur erkannt werden kann. Im Code wurde der Schwellwert für die Nähe auf 200 gesetzt und der Schwellwert für die Ferne auf 255, was die maximale Tiefe für die Kinect Aufnahme darstellt. Alles was vor 200 oder hinter 255 liegt wird nicht mehr berücksichtigt.

//Schwellwert setzen
    thresholdFar = 255;             //maximale Tiefe der Kinect
    thresholdNear = 200;

Um die Kontur ermitteln zu können, werden die Bilder invertiert und für den Output voneinander abgezogen. Dieser Debug-Modus dient zur Aktivierung der Bearbeitungen, danach wird durch Betätigen der Leertaste der Debug-Modus beendet und der Anzeige-Modus wird eingeschaltet.
Ebenso wie im Debug-Modus kann hier auf Vollbild geschaltet werden um danach die Anzeige zu vergrößern und zu verschieben damit das Ganze während der Projektion dynamisch angepasst werden kann.
Der Hintergrund wurde schwarz gefärbt um die bunten Pixel besser hervorheben zu können.

//Hintergrund schwarz setzen
    ofBackground(0, 0, 0);

Bisher wurde dieser Code Abschnitt mit Hilfe von Johannes Brendel programmiert und stellt den Einstieg in die Anwendung dar.
Die Update Methode folgt auf die Setup Methode und wird immer wieder aufgerufen, um alle Veränderungen die durchgeführt wurden zu aktualisieren. Pro Frame wird je ein Bild von der Kinect aufgenommen. Um auf das Tiefenbild zugreifen zu können, wird es hier geladen und gespeichert. In diesem Teil wird der Schwellwert gesetzt und abgefragt, ob dieser aktiv ist.

void testApp::update(){
    // Bild Aufnahme
    kinect.update();
 
    if (kinect.isFrameNew()){
 
        // Tiefenbild laden und speichern
        grayscaleImgInput.setFromPixels(kinect.getDepthPixels(), w, h);
 
        grayscaleImgFar = grayscaleImgInput;
        grayscaleImgNear = grayscaleImgInput;
        grayscaleImgOutput = grayscaleImgInput;
 
        //Abfrage ob isThreshold true
        if (isThreshold) {                                      
            grayscaleImgNear.threshold(thresholdNear);
            grayscaleImgFar.threshold(thresholdFar, true);
            cvAnd(grayscaleImgFar.getCvImage(), grayscaleImgNear.getCvImage(), grayscaleImgOutput.getCvImage(), NULL);
            grayscaleImgOutput.flagImageChanged();
 
        }

„FlagImageChanged()“ überprüft, ob es eine Veränderung gegeben hat.
Der Weichzeichner, der per Tastendruck zugeschaltet werden kann, wird in dieser Methode abgefragt mit „isBlur“. Wenn „isBlur“ auf true gesetzt wird, bedeutet das, dass der Weichzeichner aktiv ist. Durch „dilate_3x3()“ wird die Stärke des Weichzeichners bestimmt, Blöcke von drei mal drei Pixel werden hier verarbeitet, um eine weichere Zeichnung zu erhalten - in unserem Fall wird die Funktion zweimal aufgerufen.

 //Weichzeichner anwenden
        if (isBlur) {
            grayscaleImgOutput.dilate_3x3();
            grayscaleImgOutput.dilate_3x3();
            grayscaleImgOutput.blur(5);
            grayscaleImgOutput.flagImageChanged();
        }


Blob

Zum Ermitteln der Kontur kommen sogenannte Blobs ins Spiel. Blobs sind dazu da, Bereiche zu erkennen. Beispielsweise die Fingerkuppen bei einer Hand, die in die Kamera gehalten wird. Die Blobs in unserem Code werden bei dem Bild „greyscaleImgOutput“ eingesetzt, die ganze Kontur eines Körpers bildet einen Blob. In diesem Codeabschnitt „(grayscaleImgOutput, 5, (w * h)/2, 3, false, true)“ setzen wir die kleinste mögliche Anzahl an Blobs die gefunden werden können auf 5. (w*h)/2 also Breite mal Höhe durch zwei geteilt, ist die größte Anzahl der möglichen Blobs, die gefunden werden können. Der Wert 3 stellt die maximale Anzahl an Blobs, die in Betracht gezogen werden sollen dar, das heißt, es könnten beispielsweise 3 Personen gleichzeitig mit ihrer Kontur erkannt werden. Der Wert false wird hier für „bfindHoles“ gesetzt, der „contourFinder“ wird gefragt, ob sich innerhalb der ermittelten Blobs Lücken befinden. „bUseApproximation“ setzen wir auf true. Damit wird dem „contourFinder“ mitgeteilt, dass er eine Annäherung benutzen soll um die kleinste Anzahl an benötigten Punkten anzeigen um einen Blob darzustellen.

//Kontur finden
        if (isContour) {    
            contourFinder.findContours(grayscaleImgOutput, 5, (w * h)/2, 3, false, true);
        }

Diese Prozedur wurde soeben für den Debug-Modus angewendet. Dasselbe wird auch für den Anzeige-Modus durchgeführt, jedoch mit leicht veränderten Werten. Beispielsweise wurde die maximale Anzahl an Blobs, die in Betracht gezogen werden, auf 1 gesetzt und nicht wie zuvor auf 3.

if (!isDebug) {
            contourFinder.findContours(grayscaleImgOutput, 0, (w*h), 1, false, true);

In der nun folgenden Draw Methode führen wir die Anordnung der Graustufenbilder im Debug- Modus durch. „greyscaleImgOutput“ und „contourFinder“ werden übereinander gezeichnet. Hier fügten wir auch Beschriftungen für die einzelnen Bilder im Debug-Modus hinzu um die Arbeit zu erleichtern, sowie die Belegung der wichtigsten Tasten. Mit „ofDrawBitmapString()“ wird der Text ausgegeben.

void testApp::draw(){
 
    if(isDebug) {
 
        ofSetColor(255, 255, 255);
        grayscaleImgInput.draw(0, 0, 320, 240);
        grayscaleImgFar.draw(321, 0, 320, 240);
        grayscaleImgNear.draw(0, 241, 320, 240);
        grayscaleImgOutput.draw(321, 241, 320, 240);
        contourFinder.draw(321, 241, 320, 240);
 
 
        ofSetColor(255, 0, 255);
        ofDrawBitmapString("Standard Bild", 10, 10);
        ofDrawBitmapString("ThresholdFar", 331, 10);
        ofDrawBitmapString("ThresholdNear", 10, 251);
        ofDrawBitmapString("Output", 331, 251);
 
        ofDrawBitmapString("Winkel der Kinect: " + ofToString(angle), 10, 20);
        ofDrawBitmapString("f = fullscreen, Pfeiltasten = verschieben", 10, 500);
        ofDrawBitmapString("+/- = groeßer/kleiner, a = +/- Schritt hoeher", 10, 510);
 
    }

Damit im Anzeige-Modus der gewünschte Effekt entsteht müssen die Pixel an der Kontur angeordnet werden. Dazu werden der „contourFinder“ und die Blobs kombiniert. Es wird ein Intervall festgelegt – in unserem Fall „step“ entspricht dem Wert 5 – dieser Intervall sind die Abstände zwischen den Pixeln die an der Kontur angeordnet werden. Die Kontur wird sozusagen abgetastet und nach jedem „step“ werden Pixel eingesetzt. Mit „ofRandom“ setzten wir die Entfernung der Pixel zur Kontur auf einen Zufallswert, bis zu dem Höchstwert von 5. Die Pixelgröße setzten wir auf 2, da uns diese Größe am besten zugesagt hat.

//Pixelwolke statt Partikelsystem
        for(int i = 0; i < contourFinder.nBlobs; i++) {
 
            ofBeginShape();
            for (int j = 0; j < contourFinder.blobs.at(i).nPts; j++){
 
                ofSetColor(ofRandom(0, 255), ofRandom(0, 255), ofRandom(0, 255));
                //ofSphere((contourFinder.blobs.at(i).pts[j].x * scale) + transX, (contourFinder.blobs.at(i).pts[j].y * scale) - transY, 5);
                ofSphere((contourFinder.blobs.at(i).pts[j].x + ofRandom(0, 5) * scale) + transX, (contourFinder.blobs.at(i).pts[j].y + ofRandom(0, 20) * scale) - transY, 2);
                //Pixel zeichnen und anzeigen
 
            }
            ofEndShape(true);
 
        }

In der Methode keyReleased werden die schon erwähnten Tasten gesetzt.

void testApp::keyReleased(int key){
    switch (key) {
        // Winkel der Kinect nach oben ändern
        case 'w':
			angle++;
			if(angle>30) angle=30;
			kinect.setCameraTiltAngle(angle);
			break;
 
        // Winkel der Kinect nach unten ändern
		case 's':
			angle--;
			if(angle<-30) angle=-30;
			kinect.setCameraTiltAngle(angle);
			break;
 
        //Threshold aktivieren
        case 't':                           
            isThreshold = !isThreshold;
            break;
 
        //Weichzeichner aktivieren
        case 'b':                          
            isBlur = !isBlur;
            break;
 
        //Blobs ermitteln
        case 'c':                           
            isContour = !isContour;
            break;
 
        //zu Anzeigefenster wechseln 
        case ' ':
            isDebug = !isDebug;
            break;
 
        //Vollbildmodus aktivieren
        case 'f':
            ofToggleFullscreen();
            screenW = ofGetScreenWidth();
            screenH = ofGetScreenHeight();
            cout << screenW ;
            break;
 
        //Vergrößern
        case '+':
            scale += 0.01;
            break;
 
        //Verkleinern
        case '-':
            scale -= 0.01;
            break;
 
        //Verschieben nach links
        case OF_KEY_LEFT:
            transX -= step;
            break;
 
        //Verschieben nach rechts
        case OF_KEY_RIGHT:
            transX += step;
            break;
 
        //Verschieben nach oben
        case OF_KEY_UP:
            transY += step;
            break;
 
        //Verschieben nach unten
        case OF_KEY_DOWN:
            transY -= step;
            break;
 
        //Verschieben mit größeren Schritten aktiviert
        case 'a':
            bigger = !bigger;
            if (bigger) {
                step = 20;
            } else
                step = 5;
            break;
 
        default:
            break;
    }
}


Endergebnis

Die Anwendung war nun interaktiv und zeigte im Output die Silhouette der Person, die sich vor der Kinect bewegte. Um diese Kontur bewegten sich kleine, bunte Pixel die in einem bestimmten Radius um die Kontur flimmerten. Dies konnte bei der Abschlusspräsentation auch getestet werden und wurde ebenfalls vorgeführt. Hinzu kam noch ein Video das mit der Tänzerin zusammen aufgenommen und geschnitten wurde.
Für den Videodreh des Endvideos wurde ein Treffen mit der Tänzerin ausgemacht. Hierfür wurde ein dunkler Raum benötigt und ein aufgebauter Beamer. Die Kinect erfasste jedoch nur den Oberkörper der Tänzerin, deswegen setzten wir sie auf einen Tisch. Der Output zeigte aber die Beine des Tisches nicht an, nur die Tischfläche. Dies sah nun so aus, als würde unsere Tänzerin auf einem fliegenden Teppich sitzen, dies war auch der Anreiz für unsere Endidee „Aladin und die Pixelwolke“.


Endergebnis

Abschlusspräsentation

Präsentation

Inhalt des ersten Präsentationsteiles war die Funktionsweise des aktuellsten Prototypen GAMMA und die Beispielanwendung, welche mit Hilfe der Prototypen realisiert wurde. Für die Präsentation wurde die Beispielanwendung in mehrere Teilschritte zerlegt um während der Vorstellung dynamisch zusammengebaut werden zu können. Im zweiten Teil war dabei die Vorstellung der Entwicklung der Programmoberfläche über den Zeitraum beider Semester von dem ersten Brainstorming bis zu den abschließenden Layout Entwürfen das Thema. Zusammenfassend aufgegriffen wurden dabei die zentralen Motive Konzeptionierung, Prototypentwicklung, Usability Test und finales Layout. Der dritte Teil der Präsentation war für die Vorstellung der realisierten Anwendung bestimmt. Die verschiedenen Tools wurden vorgestellt und erläutert warum letztendlich auf Basis von OpenFrameworks programmiert wurde. Das im voraus erstellte Anwendungsvideo wurde abgespielt und auch ein Livetest mit der Anwendung wurde angeboten.


Plakate und Flyer

Es wurden für die Präsentation zwei Plakate erstellt. Diese Plakate zeigen die Arbeitsschritte, die im Sommersemester 2013 an dem Projekt gemacht wurden. Zur Veranschaulichung wurden kleine Grafiken verwendet. Des Weiteren wurde ein Flyer erstellt, der einen kurzen Überblick über die Software und die Anwendung gibt.


Ausblick

Da sich das Projekt-Ergebnis in keinem finalen Stadium befindet, und selbst dann noch erweiterbar bleibt, wäre es sinnvoll das Projekt einem neuen Team zur Fortsetzung zu übergeben. Die nächsten Schritte zur Fortsetzung wären die Implementierung einer Benutzeroberfläche und die Erweiterung der Basisarchitektur um mehr konkrete Blöcke um vielseitige Anwendungen zu schaffen.

Auch bietet es sich an, das Programm der Anwendungsgruppe zu erweitern. Das Programm ist offen, um noch andere Effekte miteinzubauen. Man könnte noch das geplante Partikelsystem programmieren. Das sind Partikel, die einer Bewegung, wie einem Schweif folgen. Von daher ist dieses Programm ein Grundgerüst für weitere kreative Ideen.


Ist / Soll Vergleich

Quellen- und Literaturverzeichnis

Weblinks

Interner Bereich: