Benutzer-Werkzeuge

Webseiten-Werkzeuge


ss16:dirigieren_protokolle

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
ss16:dirigieren_protokolle [2016/07/14 14:44]
hrilling [Protokoll]
ss16:dirigieren_protokolle [2016/09/02 17:29] (aktuell)
robinkrueger
Zeile 384: Zeile 384:
 cv2.destroyAllWindows() cv2.destroyAllWindows()
 </​code>​ </​code>​
-''​+
  
 ===== Fortschritt außerhalb des Labors ===== ===== Fortschritt außerhalb des Labors =====
Zeile 721: Zeile 721:
  
  
-====== 30.06. Weiter gehts ======+===== 30.06. Weiter gehts =====
  
-===== Ziele =====+==== Ziele ====
  
   * Oberziel: Takterkennung,​ notwendige Schritte hierfür:   * Oberziel: Takterkennung,​ notwendige Schritte hierfür:
Zeile 740: Zeile 740:
 Für die Programmierarbeit teilten wir uns wieder in zwei Teilgruppen auf. Leider stellten sich diese Mal die technischen Probleme als größte Herausforderung heraus, sodass ein Teil der Gruppe leider aufgrund von fehlenden Netzkabeln, nicht funktionierender Webcam und nicht installiertem CV2Programm auf den Laborrechnern relativ wenig arbeiten konnte. Für die Programmierarbeit teilten wir uns wieder in zwei Teilgruppen auf. Leider stellten sich diese Mal die technischen Probleme als größte Herausforderung heraus, sodass ein Teil der Gruppe leider aufgrund von fehlenden Netzkabeln, nicht funktionierender Webcam und nicht installiertem CV2Programm auf den Laborrechnern relativ wenig arbeiten konnte.
  
-====== Außerhalb des Labors ​======+===== Außerhalb des Labors =====
  
 Nach der letzten Laborsitzung hat unser Programm einen großen Fortschritt erziehlt. Robin hat sich zu Hause hingesetzt und einige tolle Erweiterungen hinzugefügt. ​ Nach der letzten Laborsitzung hat unser Programm einen großen Fortschritt erziehlt. Robin hat sich zu Hause hingesetzt und einige tolle Erweiterungen hinzugefügt. ​
 So wird zu Beginn jetzt eine Kalibrierung des Dirigentenstabes vorgenommen, ​ So wird zu Beginn jetzt eine Kalibrierung des Dirigentenstabes vorgenommen, ​
  
-====== 07.07. Erfassung weiterer Dirigierparameter ​======+===== 07.07. Erfassung weiterer Dirigierparameter =====
  
-===== Ziele =====+==== Ziele ====
  
   * Robins geniales Programm verstehen   * Robins geniales Programm verstehen
Zeile 755: Zeile 755:
   * weitere Taktarten erkennen ​   * weitere Taktarten erkennen ​
  
-====== 14.07. Musik? Musik! ​======+===== 14.07. Musik? Musik! =====
  
-===== Ziele =====+==== Ziele ====
  
   *Dirigieren mit Musik verbinden. Hierfür ist nötig:   *Dirigieren mit Musik verbinden. Hierfür ist nötig:
Zeile 765: Zeile 765:
   *Vorbereitung der Präsentation fürs Wissenschaftsfenster am 18.07.   *Vorbereitung der Präsentation fürs Wissenschaftsfenster am 18.07.
  
-===== Protokoll ​=====+==== Protokoll ====
  
-Nach der Festlegung der Zeile teilten wir uns in Gruppen auf. Max nahm sich der Tempoerkennung an. Der Rest, Jette, Robin und Henriette, beschäftigten sich mit den MIDI-Dateien. ​+Nach der Festlegung der Zeile teilten wir uns in Gruppen auf. Max nahm sich der Tempoerkennung an. Der Rest, Jette, Robin und Henriette, beschäftigten sich mit den MIDI-Dateien. ​Als Quelle für unsere Musikdateien fanden wir relativ schnell die Seite [[www.midiworld.com]],​ welche MIDI-Dateien bekannter Musikstücke gratis zum download zur Verfügung stellt. Im folgenden versuchten wir mehr über den Aufbau und die Manipulation von MIDI-Dateien herauszufinden. Leider findet an hierzur nur sehr wenige Informationen online. Da am Montag die Präsentation unseres Projektes im Wissenschaftsfenster bevor stand, begannen Robin und Henriette schließlich mit der Ausarbeitung der Präsentation. 
 +Jette schrieb weiter am Programm und erreichte, dass dieses nun die einzelnen Taktschläge von eins bis vier zählen kann.  
 + 
 +===== 18.07. Projektpräsentation im Wissenschaftsfenster ===== 
 + 
 +Am Montag war im Wissenschaftsfenster die Präsentation der Projekte aus den Laboren. Robin, Max und Henriette stellten unser Projekt "Das Orchester ist Programm"​ den anderen MINTgrünlern vor. In der Präsentation stellten wir die Entstehung unseres Programmes dar von unseren ersten Versuchen bis zur aktuellsten Version.  
 +Dabei kam die Präsentation und unsere Idee gut an. Nur dem Triport mussten wir uns in der Endabstimmung geschlagen geben und bekamen den zweiten Platz in der Abstimmung über das beste Projekt.  
 + 
 +===== 21.07. endlich Musik! ===== 
 + 
 +Heute war wieder eine eher technische Sitzung. Stefan hatte uns ein Programm zur Verfügung gestellt, mit Hilfe dessen man MIDI-Dateien abspielen und verändern kann. Jedoch musste hierfür zunächst auf allen Rechnern die notwendigen Pythonpakete geladen werden. Erforderlich waren pyaudio, pygame, python midi und music21. Leider verlief die Installation wie meist nicht s reibungslos und brauchte Zeit. Aber jetzt können wir mit allen Laptops Midi-Dateien abspielen und auch bearbeiten. Ab der nächsten Sitzung kommen wir also unserem Ziel näher: Das Anpassen der Musik nach den Dirigierbewegungen.  
 + 
 +====== Der Block in der Vorlesungsfreien Zeit ====== 
 + 
 +===== 31.08. Tag 1 ===== 
 + 
 + 
 + 
 +===== 01.09. Tag 2 ===== 
 + 
 + 
 + 
 +===== 02.09. Tag 3 ===== 
 + 
 +Heute war nun der letzte Tag des Labors. Zu Beginn des Tages stellten wir fest, das die gestrigen Erweiterungen im Bereich der Umrechnung von der Dirigierfrequenz (Beats per Minute) in die Dauer der Miditicks und deren Weiterverarbeitung in ein regelmäßiges Signal zur Ansteuerung der Musik. Die Ansteuerung funktionierte nun ebenfalls. Probleme sind augetreten im Bereich der Beendigung von Stücken während des Stücks unter Windows. 
 + 
 +Max hat die Benutzeroberfläche entsprechend angepasst, so dass diese deutlich beutzerfreundlicher ist und besser aussieht. 
 + 
 +{{ :​ss16:​gui_dirigieren.png?​400 | Neue Benutzeroberfläche}} 
 + 
 +Zusätzlich zur Optimierung der Ringe und der Ausgabe von Frequenz, Taktart und Taktposition ist nun auch ein Hinweismenü integriert, welches bei Berührung einer Schaltfläche mit dem Taktstock erscheint. Die Ringe werden in diesem Fall ausgeblendet. 
 + 
 +{{ :​ss16:​menue_dirigieren.png?​400 |Neues Informationsmenü}} 
 + 
 +Henriette hat unter anderem verschiedene Midi-Stücke für diverse Taktarten herausgesucht und es wurde eine Funktion geschrieben,​ welche automatisch per Zufall ein Stück zur entprechenden Taktart auswählt. Dies //funzt// soweit. Die letze Version des Programms innerhalb der offiziellen Projektarbeit ist im folgenden zu sehen.: 
 + 
 +<code python>​ 
 +# -*- coding: utf-8 -*- 
 + 
 +from __future__ import division 
 +from scipy import misc, ndimage 
 +from mpl_toolkits.mplot3d import Axes3D 
 +import math as m 
 +import random 
 +import time 
 +import matplotlib.pyplot as plt 
 +import numpy as np 
 +import cv2 
 +import sys 
 +from copy import deepcopy 
 +import pickle 
 +import midi 
 +import fluidsynth 
 +import threading 
 +import os 
 + 
 + 
 +#​=====Object from Stefan=====#​ 
 + 
 +def test1(): 
 + fs = fluidsynth.Synth()  
 + fs.start(driver="​alsa"​) 
 + 
 + sfid = fs.sfload("​FluidR3_GM.sf2"​)  
 + fs.program_select(0,​ sfid, 0, 0) 
 + 
 + fs.noteon(0,​ 60, 50)  
 + fs.noteon(0,​ 67, 30)  
 + fs.noteon(0,​ 76, 30) 
 + 
 + time.sleep(1.0) 
 + 
 + fs.noteoff(0,​ 60)  
 + fs.noteoff(0,​ 67)  
 + fs.noteoff(0,​ 76) 
 + 
 + time.sleep(1.0) 
 + 
 + fs.delete()  
 + 
 +class Player(object):​ 
 +  
 + def __init__(self):​ 
 + self.d=[] 
 + self.fs = fluidsynth.Synth()  
 + self.fs.start(driver="​alsa"​) 
 + 
 + self.sfid = self.fs.sfload("​FluidR3_GM.sf2"​)  
 + self.fs.program_select(0,​ self.sfid, 0, 0) 
 +  
 + self.tick_duration = 0.01 
 +  
 +  
 + def load(self, filename):​ 
 + '''​lädt ein Midi-File mit Namen filename.'''​ 
 + with open(filename,'​rb'​) as f: 
 + self.d=midi.fileio.read_midifile(f) 
 + self.d.make_ticks_abs() 
 +  
 + def play(self):​ 
 + '''​spielt die Datei in Echtzeit ab, die zugrundeliegende 
 + Zeiteinheit self.tick_duration lässt sich während des Abspielens 
 + ändern.'''​ 
 + self.stop = False 
 + for voice in self.d: 
 + voice_thread = threading.Thread(target=self.play_voice,​ args=(voice,​)) 
 + voice_thread.start() 
 +  
 + def stopit(self):​ 
 + self.stop = True 
 +  
 + def play_voice(self,​voice):​ 
 + voice.sort(key=lambda e: -e.tick) 
 + 
 + tick_now = 0 
 +  
 + time_now = time.time() 
 +  
 + while len(voice)>​0 and not self.stop : 
 + event=voice.pop() 
 + while event.tick>​tick_now:​ 
 + #print event 
 + n_ticks= max(int((time.time()-time_now)//​self.tick_duration)+1,​event.tick-tick_now) 
 + #print n_ticks, n_ticks*self.tick_duration-time.time()+time_now 
 + time.sleep(n_ticks*self.tick_duration-time.time()+time_now) 
 + tick_now +=n_ticks 
 + time_now=time.time() 
 +  
 + self.send(event)  
 +  
 + def send(self, event): 
 + '''​Diese Methode kommuniziert mit dem Synthesizer. Bisher sind 
 + nur drei Ereignistypen implementiert.'''​ 
 + if type(event) is midi.NoteOnEvent:​ 
 + self.fs.noteon(event.channel,​event.data[0],​event.data[1]) 
 + elif type(event) is midi.NoteOffEvent:​ 
 + self.fs.noteoff(event.channel,​ event.data[0]) 
 + elif type(event) is midi.ProgramChangeEvent:​ 
 + self.fs.program_change(event.channel,​ event.data[0]) 
 + elif type(event) is midi.ControlChangeEvent:​ 
 + self.fs.cc(event.channel,​ event.data[0],​event.data[1]) 
 +  
 +#​=====Functions=====#​ 
 + 
 + 
 +def waehle_stueck(taktart,​ lager_verzeichnis):​ 
 + if taktart == "​4_4":​ 
 + stuecke = os.listdir(lager_verzeichnis + "/​4_4"​) 
 + elif taktart == "​2_2":​  
 + stuecke = os.listdir(lager_verzeichnis + "/​2_2"​) 
 + elif taktart == "​3_4":​ 
 + stuecke = os.listdir(lager_verzeichnis + "/​3_4"​) 
 + else: 
 + print "​Ungueltige Taktart"​ 
 + auswahl = random.choice(stuecke) 
 + return "/"​+ lager_verzeichnis +  "/"​ + taktart + "/"​ + auswahl 
 + 
 +def detect_color(frame):​ #Funktion, welche eine nach Farbe definierte Stelle ermittelt 
 + 
 + hsv = cv2.cvtColor(frame,​ cv2.COLOR_BGR2HSV) ​  #​konvertiert frame in hsv 
 + lower = np.array([hue_min,​ sat_min, val_min]) ​ #legt untere schranke fest 
 + upper = np.array([hue_max,​ sat_max, val_max]) ​ #legt obere schranke fest 
 + 
 + #Die Wert aus den Schranken werden aus globalen Variablen gezogen 
 + 
 + mask =  cv2.inRange(hsv,​ lower, upper) #​erstellt maske, welche für werte innerhalb des intervalls 
 + #​den wert 1 annimmt, sonst 0 
 + y_werte, x_werte = np.where(mask == 255) #​Es werden die x- und y-Werte ausgelesen, welche ein True (255) bekomen haben 
 + if len(x_werte) > 20:​ ###​es reicht eine bedingung zu erfüllen + schwellenwert 
 + y_mittel = int(np.mean(y_werte)) #​Es wird der Mittelwert aus allen y-Werten gebildet 
 + x_mittel = int(np.mean(x_werte)) #​Es wird der Mittelwert aus allen x-Werten gebildet 
 + position = (x_mittel, y_mittel) #​Die Mittlere Position aller Trues entspricht dem Tupel beider Mittelwerte 
 + 
 + else:​ ###​if-bedingung unnötig, mittelpunkt erhält man durch tausch von x und y 
 + y_shape, x_shape, _ = frame.shape #​Es werden die Bildmaße ausgelesen 
 + position = (int(x_shape//​2),​int(y_shape//​2)) #​Als Position wird der Bildmittelpunkt gewählt 
 +  
 + return position #​Ergebnis wird zurückgegeben 
 + 
 +def get_values(cap):​ 
 + while(True):​  
 + _, frame = cap.read() 
 + y_shape, x_shape, _ = frame.shape 
 + cv2.circle(frame,​(x_shape//​2,​ y_shape//​2),​25,​(0,​0,​255),​4) 
 + frame = cv2.flip(frame,​1) #Spiegelung des frames an der Horizontalen 
 + cv2.putText(frame,​ "​Bereit?​ [B]", (200,450), 2, 1, (255,​255,​255),​ 0) 
 + cv2.imshow('​frame',​ frame) 
 + if cv2.waitKey(1) & 0xFF == ord('​b'​):​ #Signal, dass in Position, über das Drücken von k 
 + break 
 + if cv2.waitKey(1) & 0xFF == ord(' '):  
 + cap.release() 
 + sys.exit() 
 + 
 + ret, frame = cap.read() #frame ohne Kreis wird geholt 
 + hsv = cv2.cvtColor(frame,​ cv2.COLOR_BGR2HSV) #​Konvertierung in hsv 
 + radius = 25 #Radius des zu untersuchenden Kreises 
 + kreisliste = [] #diese Liste soll alle Pixel enthalten, die innerhalb des Kreises liegen 
 + for i in range(x_shape):​ #das Bild wird pixelweise durchgegangen. Wenn der Pixel im Bild liegt, wir dieser registriert 
 + for j in range(y_shape):​ 
 + if np.sqrt((x_shape//​2-i)**2+(y_shape//​2-j)**2) < radius: #Hier Satz des Pythagoras zur Entfernungsbestimmung Pixel--Kreismittelpunkt 
 + kreisliste.append(hsv[j][i]) 
 + npkreisliste = np.array(kreisliste) #​Konvertierung in Array zur weiteren Verarbeitung 
 + 
 + hue = npkreisliste[:,​0] #Array mit allen hue-Werten wird angelegt 
 + sat = npkreisliste[:,​1] #Array mit allen sat-Werten wird angelegt 
 + val = npkreisliste[:,​2] #Array mit allen val-Werten wird angelegt 
 + 
 + #​Berechung der Grenzen erfolgt, wie folgt. Zuerst wird der Mittelwert aller Werte einer Eigenschaft gebildet. 
 + #Als nächstes wird jeweils die Standartabweichung ermittelt. 
 + #Die untere Schranke ist dann einfach der Mittelwert - die Standartabweichun 
 + #Die obere Schranke ist einfach der Mittelwert + die Standartabweichung. 
 + 
 + #Die Ergebnisse werden zur direkten Weiterverwendung in globale Variablen geschrieben. 
 + #Zur verwendung nach einem Programmneustart werden sie in eine datei ausgelagert. 
 + 
 + global hue_min #globale Variable wird angelegt 
 + hue_min = int(np.mean(hue) - np.std(hue)) #Wert wird ermittelt 
 + global hue_max 
 + hue_max = int(np.mean(hue) + np.std(hue)) 
 + global sat_min 
 + sat_min = int(np.mean(sat) - np.std(sat)) 
 + global sat_max 
 + sat_max = int(np.mean(sat) + np.std(sat)) 
 + global val_min 
 + val_min = int(np.mean(val) - np.std(val)) 
 + global val_max 
 + val_max = int(np.mean(val) + np.std(val)) 
 +  
 + sicherung = (hue_min,​hue_max,​sat_min,​sat_max,​val_min,​val_max) #erzeuge Datensatztupel zur Abspeicherung für Pickle 
 + output = open('​hsv_werte.pkl',​ '​w'​) #die Ausgabedatei wird vorbereitet 
 + pickle.dump(sicherung,​ output) #die Daten werden geschrieben 
 + output.close() #der Output wird geschlossen 
 +  
 +def schwellenwerte_einlesen():​ 
 + global hue_min #die Schwellenwerte werden als global definiert 
 + global hue_max 
 + global sat_min 
 + global sat_max 
 + global val_min 
 + global val_max 
 + 
 + try: #es wird versucht / festgestellt,​ ob es bereits eine Datei mit gespeicherten Schwellenwerten gibt 
 + f = open("​hsv_werte.pkl"​) #falls ja wird diese geoeffnet 
 + sicherung = pickle.load(f) 
 + hue_min, hue_max, sat_min, sat_max, val_min, val_max = sicherung #und die Daten entpackt 
 + 
 + except: #falls nein, werden sehr komische Werte festgelegt, damit der Benutzter das Programm kalibriert 
 + val_max = 1 
 + val_min = 0 
 + sat_max = 1 
 + sat_min = 0 
 + hue_max = 1 
 + hue_min = 0 
 + 
 +def detect_gesture(zu_untersuchen,​ figur): 
 + figurlaenge = len(figur) 
 +  
 + zu_untersuchen_kurz = [] #Diese Liste soll die letzten dirigierten Vektoren enthalten, die wichtig sind 
 + for i in range(figurlaenge,​0,​-1):​ #​von index -1 bis index 0 
 + zu_untersuchen_kurz.append(zu_untersuchen[-i]) #letzten Eintraege werden ermittelt 
 + zu_untersuchen_kurz = np.array(zu_untersuchen_kurz) #zur weiteren Verarbeitung Konvertierung in Array 
 +  
 + figurensammlung = [] #​verschiedene Kombinationen werden angelegt, schwierig sich das ohne zeichnung vorzustellen. Bsp.: aus [1,2,3] wird [[1,​2,​3],​[2,​3,​1],​[3,​2,​1]] 
 + tmp = figur 
 + for i in range(figurlaenge):​ 
 + tmp.append(tmp[0]) 
 + del(tmp[0]) 
 + anhaengen = deepcopy(tmp) 
 + figurensammlung.append(anhaengen) 
 + figurensammlung = np.array(figurensammlung) #zur weiteren Verarbeitung Konvertierung in Array 
 + 
 + for i in range(figurlaenge):​ #Der Vergleich findet statt 
 + if np.array_equiv(figurensammlung[i],​zu_untersuchen_kurz):​ #​elementweises Vergleichen von letztem Dirigat und verschiedenen Figur-Kombinationen 
 + return True #falls Figur gefunden 
 +  
 + return False #falls Figur nicht gefunden 
 +  
 +def detect_bpm(l):​ 
 + global a 
 + global b 
 + global bpm 
 + if l > 2: 
 + b = time.clock() 
 + bpm = 60/(b-a) 
 + a = b 
 + else: 
 + a = time.clock() 
 + 
 +def get_vec(old,​ new): 
 + if new == None: 
 + return None 
 + elif old == new: 
 + return None 
 + elif old == 1: 
 + if new == 2: 
 + return (1,0) 
 + elif new == 3: 
 + return (1,-1) 
 + elif new == 4: 
 + return (0,-1) 
 + elif old == 2: 
 + if new == 1: 
 + return (-1,0) 
 + elif new == 3: 
 + return ​ (0,-1) 
 + elif new == 4: 
 + return (-1,-1) 
 + elif old == 3: 
 + if new == 1: 
 + return (-1,1) 
 + elif new == 2: 
 + return (0,1) 
 + elif new == 4:  
 + return (-1,0) 
 + elif old == 4: 
 + if new == 1: 
 + return (0,1) 
 + elif new == 2: 
 + return (1,1) 
 + elif new == 3: 
 + return (1,0) 
 + 
 +def get_visual(pos):​ 
 + if new == 1: 
 + cv2.circle(frame,​ c1, cthresh, color, 3) 
 + cv2.circle(clean,​ c1, cthresh, color, 3) 
 + if new == 2: 
 + cv2.circle(frame,​ c2, cthresh, color, 3) 
 + cv2.circle(clean,​ c2, cthresh, color, 3) 
 + if new == 3: 
 + cv2.circle(frame,​ c3, cthresh, color, 3) 
 + cv2.circle(clean,​ c3, cthresh, color, 3) 
 + if new == 4: 
 + cv2.circle(frame,​ c4, cthresh, color, 3) 
 + cv2.circle(clean,​ c4, cthresh, color, 3) 
 +  
 + cv2.circle(frame,​ c1, cthresh, color, 3) 
 + cv2.circle(frame,​ c2, cthresh, color, 3) 
 + cv2.circle(frame,​ c3, cthresh, color, 3) 
 + cv2.circle(frame,​ c4, cthresh, color, 3) 
 + cv2.circle(frame,​ pos, 4, (0,0,255), -1)  
 + cv2.circle(clean,​ pos, 4, (0,0,255), -1) 
 + cv2.circle(frame,​ (640,480), cthresh, (0,​255,​255),​ -1)  
 +  
 +def get_length(a,​b):​ #​berechnet länge eines vektors von 2 punkten 
 + ax, ay = a 
 + bx, by = b 
 + cx = ax - bx 
 + cy = ay - by 
 + l = np.sqrt(cx**2+cy**2) 
 + return l 
 +  
 +def in_circle(pos):​ 
 +  
 + vec1 = get_length(c1,​ pos) #​sammlung der längen der vektoren von den mittelpunkten zur position 
 + vec2 = get_length(c2,​ pos) 
 + vec3 = get_length(c3,​ pos) 
 + vec4 = get_length(c4,​ pos) 
 + vecmenu = get_length(cmenu,​ pos) 
 +  
 + lengths = [cthresh+1, vec1, vec2, vec3, vec4, vecmenu] 
 +  
 + for x in lengths: 
 + if x < cthresh: 
 + ret = lengths.index(x) 
 + if ret == 5: 
 + return "​menu"​ 
 + return ret 
 +  
 +def detect_gesture(zu_untersuchen,​ figur): #diese Funktion versucht Figuren im Dirigat zu erkennen. Dafuer bekommt sie die Figurvektoren in richtiger Reihenfolge,​ sowie die Liste mit den dirigierten Vektoren uebergeben 
 + figurlaenge = len(figur) 
 +  
 + zu_untersuchen_kurz = [] #Diese Liste soll die letzten dirigierten Vektoren enthalten, die wichtig sind 
 + for i in range(figurlaenge,​0,​-1):​ 
 + zu_untersuchen_kurz.append(zu_untersuchen[-i]) #letzten Eintraege werden ermittelt 
 + zu_untersuchen_kurz = np.array(zu_untersuchen_kurz) #zur weiteren Verarbeitung Konvertierung in Array 
 +  
 + figurensammlung = [] #​verschiedene Kombinationen werden angelegt, schwierig sich das ohne zeichnung vorzustellen. Bsp.: aus [1,2,3] wird [[1,​2,​3],​[2,​3,​1],​[3,​2,​1]] 
 + tmp = figur 
 + for i in range(figurlaenge):​ 
 + tmp.append(tmp[0]) 
 + del(tmp[0]) 
 + anhaengen = deepcopy(tmp) 
 + figurensammlung.append(anhaengen) 
 + figurensammlung = np.array(figurensammlung) #zur weiteren Verarbeitung Konvertierung in Array 
 + 
 + for i in range(figurlaenge):​ #Der Vergleich findet statt 
 + if np.array_equiv(figurensammlung[i],​zu_untersuchen_kurz):​ #​elementweises Vergleichen von letztem Dirigat und verschiedenen Figur-Kombinationen 
 + return True #falls Figur gefunden 
 +  
 + return False #falls Figur nicht gefunden 
 + 
 +def beat_number(vec,​figure):​ 
 + a,b = vec 
 +  
 + if figure == '​triangleA':​ 
 + if vec == (0,-1): 
 + return 1 
 + if vec == (-1,0): 
 + return 2  
 + else: 
 + return 3 
 + if figure == '​triangleB':​ 
 + if vec == (1,0): 
 + return 1 
 + if vec == (0,1): 
 + return 2  
 + else: 
 + return 3 
 + if figure == '​triangleC':​ 
 + if vec == (-1,0): 
 + return 1 
 + if vec == (0,1): 
 + return 2  
 + else: 
 + return 3 
 + if figure == '​triangleD':​ 
 + if vec == (0,-1): 
 + return 1 
 + if vec == (1,0): 
 + return 2  
 + else: 
 + return 3 
 + 
 + if figure == '​rectangleCCW':​ 
 + if vec == (0,-1): 
 + return 1 
 + if vec == (1,0): 
 + return 2 
 + if vec == (0,1): 
 + return 3 
 + if vec == (-1,0): 
 + return 4 
 + if figure == '​rectangleCW':​ 
 + if vec == (0,-1): 
 + return 4 
 + if vec == (1,0): 
 + return 3 
 + if vec == (0,1): 
 + return 2 
 + if vec == (-1,0): 
 + return 1 
 + 
 + if figure == '​line':​ 
 + if vec == (0,-1): 
 + return 1 
 + else: 
 + return 2 
 + else: 
 + return False  
 +  
 +def check_gestures():​ 
 + global figure 
 + if len(veclist) > 4: 
 + if detect_gesture(veclist,​ rectangleCW):​ 
 + figure = "​rectangleCW"​ 
 + counter() 
 + if detect_gesture(veclist,​ rectangleCCW):​ 
 + figure = "​rectangleCCW"​ 
 + counter() 
 + if detect_gesture(veclist,​ triangleA):​ 
 + figure = "​triangleA"​ 
 + counter() 
 + if detect_gesture(veclist,​ triangleB):​ 
 + figure = "​triangleB"​ 
 + counter() 
 + if detect_gesture(veclist,​ triangleC):​ 
 + figure = "​triangleC"​ 
 + counter() 
 + if detect_gesture(veclist,​ triangleD):​ 
 + figure = "​triangleD"​ 
 + counter() 
 + if detect_gesture(veclist,​ line): 
 + figure = "​line"​ 
 + counter() 
 +  
 +def counter():​ 
 + f = len(figure) #​bescheuertes verfahren, nötig da detect_gesture die länge der figurenliste ändert 
 + if f > 10: 
 + r = 4  
 + else: 
 + r = int(np.sqrt(f)) 
 +  
 + cv2.putText(mirror,​ str(beat_number(veclist[-1],​figure)) + "/"​ + str(r), (40,40), 2, 1, (255,​255,​255),​ 0) 
 + return r 
 + 
 +def bpm_mean(bpm):​ 
 + if bpm > 40: 
 + bpmlist.append(bpm) 
 + if len(bpmlist) < 10: 
 + npbpm = np.array(bpmlist) 
 + mean = int(np.mean(npbpm))/​10 
 + mean = int(mean)*20 
 +  
 + else: 
 + rel = bpmlist[-10:​] 
 + npbpm = np.array(rel) 
 + mean = int(np.mean(npbpm))/​10 
 + mean = int(mean)*10 
 + return mean 
 + return bpm 
 +  
 +def tick_laenge_ermitteln(bpm):​ 
 + if (60/ bpm)/192 > 0: #1 tick 0,1s# 1 viertel 19,2s# 
 + l=(60/ bpm)/192 
 + return l 
 +  
 +def menu_visual(cap):​ 
 + while(True):​  
 + _, frame = cap.read() 
 + position = detect_color(frame) 
 +  
 + new = in_circle(position) 
 + 
 + if new != "​menu":​ 
 + break 
 +  
 + frame = cv2.flip(frame,​1)  
 +  
 + #​===Menü===#​ 
 + cv2.circle(frame,​ (0,480), cthresh, (0,​255,​255),​ -1)  
 + cv2.putText(frame,​ "​INFO",​ (200,80), 2, 1, (255,​255,​255),​ 0) 
 + cv2.putText(frame,​ "​Kalibrieren [K]", (200,130), 2, 1, (255,​255,​255),​ 0) 
 + cv2.putText(frame,​ "​Pause/​Start [P]", (200,​170 ​ ), 2, 1, (255,​255,​255),​ 0) 
 + cv2.putText(frame,​ "​Beenden [Leer]",​ (200,​210 ​ ), 2, 1, (255,​255,​255),​ 0) 
 + #​===Ende===#​ 
 +  
 + cv2.imshow('​frame',​ frame) 
 +  
 + if cv2.waitKey(1) & 0xFF == ord(' '):  
 + cap.release() 
 + sys.exit() 
 +  
 +def waehle_stueck(taktart,​ lager_verzeichnis):​ 
 + if taktart == 4: 
 + stuecke = os.listdir(lager_verzeichnis + "/​4_4"​) 
 + art = "​4_4"​ 
 + elif taktart == 2:  
 + stuecke = os.listdir(lager_verzeichnis + "/​2_2"​) 
 + art = "​2_2"​ 
 + elif taktart == 3: 
 + stuecke = os.listdir(lager_verzeichnis + "/​3_4"​) 
 + art = "​3_4"​ 
 + else: 
 + print "​Ungueltige Taktart"​ 
 + auswahl = random.choice(stuecke) 
 + return ​ lager_verzeichnis +  "/"​ + art + "/"​ + auswahl 
 + 
 +#​=======gestures=======#​ 
 + 
 +rectangleCW = [(1,​0),​(0,​-1),​(-1,​0),​(0,​1)] 
 +rectangleCCW = [(1,​0),​(0,​1),​(-1,​0),​(0,​-1)] ​  
 +triangleA = [(1,​1),​(0,​-1),​(-1,​0)] 
 +triangleB = [(-1,​-1),​(1,​0),​(0,​1)] 
 +triangleC = [(1,​-1),​(-1,​0),​(0,​1)] 
 +triangleD = [(-1,​1),​(0,​-1),​(1,​0)] 
 +line = [(0,​1),​(0,​-1)] 
 +gestures = [rectangleCW,​ rectangleCCW,​ triangleA, triangleB, triangleC, triangleD, line] 
 + 
 +#​=======circles=======#​ 
 + 
 +c1 = ((320+120),​(240-120)) 
 +c3 = ((320-120),​(240+120)) 
 +c2 = ((320-120),​(240-120)) 
 +c4 = ((320+120),​(240+120)) 
 +cmenu = (640,480) 
 +color = (10,​10,​255) 
 + 
 +#​=======variables=======#​ 
 + 
 +global fnr, bpm, new 
 + 
 +fnr = 0  
 +bpm = 0 
 +cthresh = 95  
 +ref = (320,240) 
 +old = 0  
 +new = 5 
 +pp = 0 
 +last_state = False 
 + 
 +#​=======lists=======#​ 
 + 
 +veclist = [None] #​liste beinhaltet richtungsänderungen 
 +bpmlist = [] 
 + 
 +#​=======program=======#​ 
 + 
 +cap = cv2.VideoCapture(0) 
 +schwellenwerte_einlesen() 
 + 
 +while True: 
 + _, frame = cap.read()  
 + clean = np.copy(frame) 
 + 
 + position = detect_color(frame) 
 +  
 + get_visual(position) 
 +  
 + new = in_circle(position) 
 + 
 + if new == "​menu":​ 
 + menu_visual(cap) 
 + continue 
 +  
 + vec = get_vec(old,​ new) 
 +  
 + if vec != None and vec != veclist[-1]:​ 
 + veclist.append(vec) 
 + detect_bpm(len(veclist)) 
 +  
 + if new != None and new != old: 
 + old = new 
 +  
 + bpm = bpm_mean(bpm) 
 +  
 + frame = cv2.addWeighted(frame,​ 0.5, clean, 0.5, 0) 
 + mirror = cv2.flip(frame,​1) 
 +  
 + check_gestures() 
 +  
 + cv2.putText(mirror,​ str(int(bpm)),​ (560,40), 2, 1, (255,​255,​255),​ 0) 
 +  
 + cv2.imshow("​frame",​ mirror) 
 + fnr += 1 
 + 
 + if fnr == 100: 
 + p = Player() 
 + p.load(waehle_stueck(counter(),​ "​../​Midi"​)) 
 + p.play() 
 + if fnr > 100: 
 + if bpm > 0: 
 + p.tick_duration = tick_laenge_ermitteln(bpm) 
 +  
 + 
 + if cv2.waitKey(1) & 0xFF == ord('​k'​):​ 
 + get_values(cap) 
 + """​if cv2.waitKey(1) & 0xFF == ord('​p'​) and fnr > 100 and last_state == False: 
 + if pp == 0: 
 + p.stopit() 
 + pp = 1 
 + if pp == 1: 
 + p.play() 
 + pp = 0 
 + last_state = True 
 + else: 
 + last_state = False"""​ 
 + 
 + if cv2.waitKey(1) & 0xFF == ord(' '): 
 + if fnr > 100: 
 + p.stopit() 
 + print "​herunterfahren"​ 
 + break  
 + 
 +cap.release() 
 +cv2.destroyAllWindows() 
 +</​code>​
ss16/dirigieren_protokolle.1468500258.txt.gz · Zuletzt geändert: 2016/07/14 14:44 von hrilling