def init_piano(self): keymap_filename = 'pianoeletronico.kmp' notes_manager = NotesManager() notes_manager.load_file(util.app_file_path(os.path.join('keymaps', keymap_filename))) self.midi = midi.Midi() self.midi_output = midi.Output(self.midi.get_default_output_id(), 0) self.piano = Piano(notes_manager, self.midi_output) self.piano.set_instrument(0, 0)
def __init__(self, ui=None, track=None, width=None, height=None, x=0, y=0): self.ui = ui # Offset on left side, leaving space for timestamps self.offset = len("00:00.000 ") if self.ui != None: logger.log("Using ui") self.height, self.width = list(map(int, self.ui.size())) self.width -= self.offset else: logger.log("Not using ui") self.height, self.width = 10, 10 self.cursorY = self.height / 2 self.cursorX = 44 self.track = track self.bpm = self.track.beatsPerMinute self.tpb = self.track.ticksPerBeat self.seconds = 60.0 / self.tpb / self.bpm #Begin and end using real time #self.length = self.track.getLengthInSec() #self.begin = 0.0 #self.end = (self.height-1) * 60.0 / self.bpm #self.step = 60.0 / self.bpm #Begin and end using beats self.length = self.track.getLengthInBeats() self.begin = 0 self.end = self.height - 1 self.step = 1 logger.log("Track's length: %.2f beats" % self.length) self.beats = [] for i in range(int(self.track.getLengthInBeats() + 1)): self.beats.append([]) logger.log("width = %d" % self.width) ## Create display window if self.width > KEYS: displayWidth = KEYS + self.offset else: displayWidth = self.width + self.offset MIN = (KEYS - self.width) / 2 MAX = (KEYS - self.width) / 2 + self.width if self.ui != None: self.display = self.ui.newWindow(self.height, displayWidth, "display", x, y) self.ui.setWindow(self.display) ## Connect to Piano self.piano = Piano() self.player = Player() self.player.start() self.player.setPiano(self.piano) self.piano.autoconnect() self.playing = False ## Create metronome beatLength = 60.0 / self.bpm self.metronome = Metronome(self.down, beatLength)
def __init__(self): self.screen_size = (1366, 768) # (width, height) self.camera_size = (640, 480) # (width, height) self.key_quit = 'q' self.aruco_dict = cv2.aruco.getPredefinedDictionary( cv2.aruco.DICT_ARUCO_ORIGINAL) self.update_piano_corners_freq = 5 # Number of frames to update piano corners self.img_to_project = np.zeros( (self.camera_size[1], self.camera_size[0], 3), np.uint8) # self.display = Display(screen_width=self.screen_size[0]) self.piano = Piano() self.cam_to_proj = None # Transformation from camera to projector coordinates self.song = [ "C#4", "C4", "F#5", "B4", "G5", "E5", "E5", "br", "F5", "D5", "D5", "br", "C5", "D5", "E5", "F5", "G5", "G5", "G5", "br", "G5", "E5", "E5", "br", "F5", "D5", "D5", "br", "C5", "E5", "G5", "G5", "C5" ]
def __init__(self): pygame.init() self.screen = glblit.initializeDisplay(*WINSIZE) self.screen_rect = self.screen.get_rect() pygame.display.set_caption('Piano Center') screen = pygame.Surface(WINSIZE) # menu MenuSystem.init(screen) MenuSystem.BGCOLOR = Color(200,200,200, 255) MenuSystem.FGCOLOR = Color(0, 0, 0, 0) MenuSystem.BGHIGHTLIGHT = Color(40,40,40,40) MenuSystem.BORDER_HL = Color(200,200,200,200) self.track_button_height = 20 self.track_button_width = 30 self.piano_info_bar_gap = 2 self.menu_bar = MenuSystem.MenuBar(top=5) menus_in_bar, self.midi_filename_data = get_menu_data() self.menu_bar.set(menus_in_bar) self.menu_bar_info = MenuSystem.MenuBar(top=self.screen_rect.height - self.menu_bar.lineheigth) self.piano = Piano(screen, WINSIZE, top=self.menu_bar_info.top - self.piano_info_bar_gap) self.piano.init_piano() self.piano.draw_vertical_staff_lines(self.screen_rect.height * 0.618) self.staff_top = self.menu_bar.top + self.menu_bar.lineheigth + self.track_button_height self.sounds = {} self.enabled_tracks_switch = {} self.midi_filename_idx = 0 if len(self.midi_filename_data) > 0: self.midi_filename = self.midi_filename_data[self.midi_filename_idx] self.load_resource(self.midi_filename)
def init_piano(self): self.create_midi_driver() self.piano = Piano(self.config.get_keymap_file_path('pianoeletronico.kmp'), self.midi_output) self.active_channels.append(0) self.piano.set_instrument(0, 0)
class PianoApp(wx.App): config = None functions_keymap = {} multi_voice = False active_channels = [] current_channel = 0 def OnInit(self): try: self.load_config() self.init_piano() self.init_ui() return True except UserError as user_error: wx.MessageBox(str(user_error), 'Erro', wx.OK | wx.ICON_ERROR) return False def load_config(self): self.config = Config(app.config_file_path()) def init_piano(self): self.create_midi_driver() self.piano = Piano(self.config.get_keymap_file_path('pianoeletronico.kmp'), self.midi_output) self.active_channels.append(0) self.piano.set_instrument(0, 0) def create_midi_driver(self): midi_output_factory = MidiOutputFactory() midi_output_driver = self.config.get_midi_output_driver(constants.MIDI_OUTPUT_DEFAULT_DRIVER) if midi_output_driver >= constants.MIDI_OUTPUT_DEFAULT_DRIVER: self.midi_output = midi_output_factory.factory_pygame(midi_output_driver ) elif midi_output_driver == constants.MIDI_OUTPUT_FLUIDSYNTH_DRIVER: self.midi_output = midi_output_factory.factory_fluidsynth(self.config.get_soundfont_file_path()) else: raise UserError('Erro de configuração: MIDI driver inexistente') def init_ui(self): self.mainFrame = wx.Frame(parent = None, id = -1, title = 'Virtual Piano') self.mainFrame.Bind(wx.EVT_KEY_DOWN, self.on_key_down) self.mainFrame.Bind(wx.EVT_KEY_UP, self.on_key_up) self.functions_keymap = { wx.WXK_RIGHT: lambda evt: self.piano.next_instrument(self.current_channel), wx.WXK_LEFT: lambda evt: self.piano.previous_instrument(self.current_channel), wx.WXK_UP: lambda evt: self.tone_change_up(evt), wx.WXK_DOWN: lambda evt: self.tone_change_down(evt), wx.WXK_PAGEUP: lambda evt: self.next_channel(), wx.WXK_PAGEDOWN: lambda evt: self.previous_channel(), wx.WXK_DELETE: lambda evt: self.delete_current_channel(), wx.WXK_F2: lambda evt: self.select_instrument_by_number(self.current_channel), wx.WXK_F8: lambda evt: self.piano.volume_down(self.current_channel), wx.WXK_F9: lambda evt: self.piano.volume_up(self.current_channel), wx.WXK_BACK: self.toggle_multi_voice, wx.WXK_TAB: self.pan, } self.mainFrame.Show(True) def on_key_down(self, evt): key = evt.GetKeyCode() if key in self.functions_keymap: self.functions_keymap[key](evt) if self.multi_voice: for channel_number in self.active_channels: note = self.get_note_from_key_event(evt, channel_number) if note is not None: self.piano.note_on(note, channel_number) else: note = self.get_note_from_key_event(evt, self.current_channel) if note is not None: self.piano.note_on(note, self.current_channel) def on_key_up(self, evt): if self.multi_voice: for channel_number in self.active_channels: note = self.get_note_from_key_event(evt, channel_number) if note is not None: self.piano.note_off(note, channel_number) else: note = self.get_note_from_key_event(evt, self.current_channel) if note is not None: self.piano.note_off(note, self.current_channel) def get_note_from_key_event(self, evt, channel_number): key = evt.GetUnicodeKey() if key != wx.WXK_NONE: if key > 127: key = char.unicode_workaround(chr(key).encode('utf-8')) return self.piano.get_note(key, channel_number) def toggle_multi_voice(self, evt): self.piano.all_notes_off() self.multi_voice = not self.multi_voice def pan(self, evt): back = True if evt.GetModifiers() == wx.MOD_SHIFT else False self.piano.pan(back, self.current_channel) def next_channel(self): if self.current_channel == 15: return self.piano.all_notes_off() self.current_channel += 1 if not self.current_channel in self.active_channels: self.active_channels.append(self.current_channel) self.piano.get_channel(self.current_channel) def previous_channel(self): if self.current_channel == 0: return self.piano.all_notes_off() self.current_channel -= 1 def delete_current_channel(self): self.piano.delete_channel(self.current_channel) self.active_channels.remove(self.current_channel) self.current_channel -= 1 def tone_change_up(self, evt): key_modifier = evt.GetModifiers() if key_modifier == wx.MOD_SHIFT: self.piano.semitone_up(1, self.current_channel) else: self.piano.octave_up(self.current_channel) def tone_change_down(self, evt): key_modifier = evt.GetModifiers() if key_modifier == wx.MOD_SHIFT: self.piano.semitone_down(1, self.current_channel) else: self.piano.octave_down(self.current_channel) def select_instrument_by_number(self, target_channel): current_instrument = str(self.piano.get_instrument_for_channel(target_channel) + 1) pressed_ok, selected_instrument = edit_dialog(self.mainFrame, "Instrument", "Enter instrument number for channel %d (from 1 to 128):" % target_channel, current_instrument) if pressed_ok: try: instrument_number = int(selected_instrument) - 1 except ValueError: message_dialog(self.mainFrame, "Error", "Instrument not a number") return if instrument_number < 0 or instrument_number > 127: message_dialog(self.mainFrame, "Error", "Instrument number not in range from 1 to 128") return self.piano.set_instrument(instrument_number, target_channel)
from sys import argv import mido from piano import Piano from recorder import Recorder from player import Player from button import Button ## Setup Piano piano = Piano() [ins, outs] = piano.listDevices() if "-i" in argv: print("[+] List of input devices") for i in range(len(ins)): print("%d: %s" % (i + 1, ins[i])) inDev = ins[int(input("Select input device: ")) - 1] else: inDev = mido.get_input_names()[0] if "-o" in argv: print("[+] List of output devices") for i in range(len(outs)): print("%d: %s" % (i + 1, outs[i])) outDev = ins[int(input("Select output device: ")) - 1] else: outDev = mido.get_output_names()[0] piano.connect(inDev, outDev) ## Setup Recorder rec = Recorder() if not rec.setPiano(piano):
""" Generates wav file using PySynth: https://mdoege.github.io/PySynth/#s """ import os import pysynth from piano import Piano output_folder = "wav" key_list = Piano().key_list if not os.path.exists(output_folder): os.makedirs(output_folder) for key in key_list: print("Generating %s" % key['note']) note_str = key['note'].lower() pysynth.make_wav([[note_str, 4]], fn=os.path.join(output_folder, "%s.wav" % key['note']))
import cv2 from piano import Piano from threading import Thread piano = Piano() def playMusic(event, x, y, flags, params): if event == cv2.EVENT_MOUSEMOVE: Thread(target=piano.press, args=(x,y,)).start() # key = piano.press(x, y) # if key is not None: # print(key+1) def main(): vid = cv2.VideoCapture(0) while True: cv2.namedWindow("Piano") ret, frame = vid.read() piano.display(frame) frame = cv2.flip(frame, 1) cv2.setMouseCallback("Piano", playMusic) cv2.imshow("Piano", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break vid.release() cv2.destroyAllWindows()
from piano import Piano from time import sleep p = Piano() [ins,outs] = p.listDevices() print("[+] List of input devices") for i in range(len(ins)): print("%d: %s"%(i+1,ins[i])) inDev = ins[int(input("Select input device: "))-1] print("[+] List of output devices") for i in range(len(ins)): print("%d: %s"%(i+1,outs[i])) outDev = ins[int(input("Select output device: "))-1] print("Testing Send()") if p.connect(inDev,outDev): p.send(50,80) print("Testing Receive(). Press a key on the piano") print(p.receive()) called = lambda x:exit() p.setCallback(called) print("Testing callback. Press a key on the piano") while 1: sleep(0.1) pass
class Display: def __init__(self, ui=None, track=None, width=None, height=None, x=0, y=0): self.ui = ui # Offset on left side, leaving space for timestamps self.offset = len("00:00.000 ") if self.ui != None: logger.log("Using ui") self.height, self.width = list(map(int, self.ui.size())) self.width -= self.offset else: logger.log("Not using ui") self.height, self.width = 10, 10 self.cursorY = self.height / 2 self.cursorX = 44 self.track = track self.bpm = self.track.beatsPerMinute self.tpb = self.track.ticksPerBeat self.seconds = 60.0 / self.tpb / self.bpm #Begin and end using real time #self.length = self.track.getLengthInSec() #self.begin = 0.0 #self.end = (self.height-1) * 60.0 / self.bpm #self.step = 60.0 / self.bpm #Begin and end using beats self.length = self.track.getLengthInBeats() self.begin = 0 self.end = self.height - 1 self.step = 1 logger.log("Track's length: %.2f beats" % self.length) self.beats = [] for i in range(int(self.track.getLengthInBeats() + 1)): self.beats.append([]) logger.log("width = %d" % self.width) ## Create display window if self.width > KEYS: displayWidth = KEYS + self.offset else: displayWidth = self.width + self.offset MIN = (KEYS - self.width) / 2 MAX = (KEYS - self.width) / 2 + self.width if self.ui != None: self.display = self.ui.newWindow(self.height, displayWidth, "display", x, y) self.ui.setWindow(self.display) ## Connect to Piano self.piano = Piano() self.player = Player() self.player.start() self.player.setPiano(self.piano) self.piano.autoconnect() self.playing = False ## Create metronome beatLength = 60.0 / self.bpm self.metronome = Metronome(self.down, beatLength) def createList(self): skip = [] t = 0.0 n = 0 for i in range(len(self.track.track)): t += self.track.track[i].time * self.seconds if self.track.track[i].type == "note_on": if i in skip: skip.remove(i) else: msg = self.track.track[i] note = msg.note length = 0 j = i + 1 ## Find closing msg while j != len(self.track.track): ## accumulate times length += self.track.track[j].time if self.track.track[j].type == "note_on": if self.track.track[j].note == note: ## put on list to skip skip.append(j) break j += 1 length *= self.seconds beats = length * self.bpm / 60.0 beatZero = int(round(t / 60.0 * self.bpm)) for k in range(int(beats + 1)): # Append a list [note, first beat of the note self.beats[beatZero + k].append([i, k == 0]) if self.ui == None: for beat in beats: print(list(map(beat, note2char))) ## Display notes with length def putStrXY(self, x, y, txt, colorPair=272): self.ui.setColorPair(colorPair) self.ui.putStrXY(self.offset + x, y, txt) def timeStamp(self, y, timeStamp): self.ui.setColorPair(50) self.ui.putStrXY(0, y, timeStamp) def update(self): self.putStrXY(0, self.cursorY - self.begin, " " * ((MAX - MIN) / 1)) self.putStrXY(self.cursorX, self.cursorY - self.begin, "+", 2) for beat in range(self.begin, self.end + 1): y = beat - self.begin seconds = 60.0 * beat / self.bpm minutes = int(seconds / 60) seconds = seconds % 60 milisec = int(1000 * (seconds - int(seconds))) self.timeStamp(y, "%02d:%2d.%03d" % (minutes, int(seconds), milisec)) for [idx, first] in self.beats[beat]: note = self.track.track[idx].note x = MIN if note < MIN else MAX if note > MAX else note x -= MIN if self.ui != None: color = 262 if self.cursorY == y + self.begin and self.cursorX == x: logger.log("update() - beat = %d" % beat) logger.log("update() - cursorY = %d" % self.cursorY) color = 282 if first: self.putStrXY(x, y, "O", color) else: self.putStrXY(x, y, "|", color) self.ui.refresh() def quit(self): self.player.stop() self.metronome.stop() def enter(self): self.playing = self.playing == False ## Play if self.playing: logger.log("enter() - Play") beat = self.cursorY first = False while not first: for idx, first in self.beats[beat]: if first: break beat += 1 track = self.track.subTrack(idx) self.player.setTrack(track) self.player.play() self.metronome.play() ## Stop else: logger.log("enter() - Pause") self.player.pause() self.metronome.pause() self.player.clearTrack() note = self.cursorX def up(self): self.cursorY = max(0, self.cursorY - 1) logger.log("Up. cursorY = %d" % self.cursorY) if self.cursorY < self.height / 2 + self.begin: self.begin -= self.step if self.begin < 0: self.begin += self.step else: self.end -= self.step def down(self): self.cursorY = min(self.length - 2, self.cursorY + 1) logger.log("Down. cursorY = %d" % self.cursorY) if self.cursorY > self.height / 2 + self.begin: self.end += self.step if self.end > self.length: self.end -= self.step else: self.begin += self.step def left(self): self.cursorX = max(0, self.cursorX - 1) def right(self): self.cursorX = min(87, self.cursorX + 1) def pgup(self): for i in range(10): self.up() def pgdown(self): for i in range(10): self.down()
def __init__(self, midi_brain): Piano.__init__(self, midi_brain) size = (200,200) self.screen = pygame.display.set_mode(size) self.screen.fill(black)
class PlayCenter(): def __init__(self): pygame.init() self.screen = glblit.initializeDisplay(*WINSIZE) self.screen_rect = self.screen.get_rect() pygame.display.set_caption('Piano Center') screen = pygame.Surface(WINSIZE) # menu MenuSystem.init(screen) MenuSystem.BGCOLOR = Color(200,200,200, 255) MenuSystem.FGCOLOR = Color(0, 0, 0, 0) MenuSystem.BGHIGHTLIGHT = Color(40,40,40,40) MenuSystem.BORDER_HL = Color(200,200,200,200) self.track_button_height = 20 self.track_button_width = 30 self.piano_info_bar_gap = 2 self.menu_bar = MenuSystem.MenuBar(top=5) menus_in_bar, self.midi_filename_data = get_menu_data() self.menu_bar.set(menus_in_bar) self.menu_bar_info = MenuSystem.MenuBar(top=self.screen_rect.height - self.menu_bar.lineheigth) self.piano = Piano(screen, WINSIZE, top=self.menu_bar_info.top - self.piano_info_bar_gap) self.piano.init_piano() self.piano.draw_vertical_staff_lines(self.screen_rect.height * 0.618) self.staff_top = self.menu_bar.top + self.menu_bar.lineheigth + self.track_button_height self.sounds = {} self.enabled_tracks_switch = {} self.midi_filename_idx = 0 if len(self.midi_filename_data) > 0: self.midi_filename = self.midi_filename_data[self.midi_filename_idx] self.load_resource(self.midi_filename) def get_menus_info_bar(self): gen_menu_data = [] # gen_menu_data += ["Metro: %.1f" % player.g_metronome_volume] gen_menu_data += ["Time: %d/%d" % (parse_midi.g_time_signature_n, parse_midi.g_time_signature_note)] gen_menu_data += ["Temp: %d" % (60000 / parse_midi.g_mseconds_per_quarter)] gen_menu_data += ["Playing: %s" % self.midi_filename.replace(".midi", "").replace(".mid", "")] return [MenuSystem.Menu(m, ()) for m in gen_menu_data] def load_resource(self, midi_filename): print midi_filename try: self.all_midi_lines, self.notes_in_all_staff, self.enabled_tracks, self.tracks_order_idx = parse_midi.load_midi(midi_filename) self.all_midi_lines_length = len(self.all_midi_lines) except Exception, e: print "midi error:", e if midi_filename in self.midi_filename_data: self.midi_filename_data.remove(midi_filename) return self.piano.timestamp_range = TIMESTAMP_RANGE * parse_midi.g_ticks_per_quarter / parse_midi.g_mseconds_per_quarter self.piano.timestamp_range = self.piano.timestamp_range * self.piano.staff_space_height_base / self.piano.staff_space_height if midi_filename in self.midi_filename_data: self.midi_filename_idx = self.midi_filename_data.index(midi_filename) self.midi_filename = midi_filename else: print "impossible: file not in menu list" return # draw track pick self.piano.screen.fill(self.piano.color_backgroud, pygame.Rect(0, self.menu_bar.top + self.menu_bar.lineheigth, self.screen_rect.width, self.track_button_height-1)) for track_idx, idx in self.tracks_order_idx.items(): if track_idx in self.enabled_tracks_switch: sw = self.enabled_tracks_switch[track_idx] sw.left = idx * self.track_button_width else: sw = pygame.Rect(idx * self.track_button_width, self.menu_bar.top + self.menu_bar.lineheigth, self.track_button_width - 1, self.track_button_height-1) self.enabled_tracks_switch[track_idx] = sw note_color = self.piano.TRACK_COLORS[idx % len(self.piano.TRACK_COLORS)] self.piano.screen.fill(note_color, sw) # finish missing sounds player.load_sounds([(midi_data[1], midi_data[2]) for midi_data in self.all_midi_lines], self.sounds) self.piano.reset_piano() self.chord_keys_bound = [] self.play_commands = [] self.midi_cmd_idx = 0 self.staff_offset_x = 0 self.midi_repeat_count = 0 self.last_timestamp = -1 self.is_pause = True self.play_one_timestamp_while_paused = False self.menu_bar_info.set(self.get_menus_info_bar())
class PianoApp(wx.App): functions_keymap = {} multi_voice = False def OnInit(self): self.init_piano() self.init_ui() return True def init_piano(self): keymap_filename = 'pianoeletronico.kmp' notes_manager = NotesManager() notes_manager.load_file(util.app_file_path(os.path.join('keymaps', keymap_filename))) self.midi = midi.Midi() self.midi_output = midi.Output(self.midi.get_default_output_id(), 0) self.piano = Piano(notes_manager, self.midi_output) self.piano.set_instrument(0, 0) def init_ui(self): self.mainFrame = wx.Frame(parent = None, id = -1, title = 'Virtual Piano') self.Bind(wx.EVT_KEY_DOWN, self.on_key_down) self.Bind(wx.EVT_KEY_UP, self.on_key_up) self.functions_keymap = { wx.WXK_RIGHT: lambda evt: self.piano.next_instrument(), wx.WXK_LEFT: lambda evt: self.piano.previous_instrument(), wx.WXK_UP: lambda evt: self.piano.octave_up(), wx.WXK_DOWN: lambda evt: self.piano.octave_down(), wx.WXK_PAGEUP: lambda evt: self.piano.next_channel(), wx.WXK_PAGEDOWN: lambda evt: self.piano.previous_channel(), wx.WXK_DELETE: lambda evt: self.piano.delete_current_channel(), wx.WXK_F8: lambda evt: self.piano.volume_down(), wx.WXK_F9: lambda evt: self.piano.volume_up(), wx.WXK_BACK: self.toggle_multi_voice, wx.WXK_TAB: self.pan, } self.mainFrame.Show(True) def on_key_down(self, evt): note = self.get_note_from_key_event(evt) if note is None: key = evt.GetKeyCode() if key in self.functions_keymap: self.functions_keymap[key](evt) else: if self.multi_voice: self.piano.note_on_multi(note) else: self.piano.note_on(note) def on_key_up(self, evt): note = self.get_note_from_key_event(evt) if note is None: return if self.multi_voice: self.piano.note_off_multi(note) else: self.piano.note_off(note) def get_note_from_key_event(self, evt): key = evt.GetUnicodeKey() if key != wx.WXK_NONE: if key > 127: key = unicode_workaround(chr(key).encode('utf-8')) return self.piano.notes_manager[key] if key in self.piano.notes_manager else None def toggle_multi_voice(self, evt): self.piano.all_notes_off() self.multi_voice = not self.multi_voice def pan(self, evt): back = True if evt.GetModifiers() == wx.MOD_SHIFT else False self.piano.pan(back)
import cv2 import time import numpy as np from piano import Piano from threading import Thread piano = Piano() protoFile = "hand/pose_deploy.prototxt" weightsFile = "hand/pose_iter_102000.caffemodel" nPoints = 22 threshold = 0.2 input_source = "input.mp4" def playMusic(x, y): Thread(target=piano.press, args=( x, y, )).start() if __name__ == "__main__": cap = cv2.VideoCapture(input_source, cv2.CAP_FFMPEG) hasFrame, frame = cap.read() frameWidth = frame.shape[1] frameHeight = frame.shape[0]
from piano import Piano from recorder import Recorder from logger import Logger from sys import argv import mido ### Call python test_recorder.py ## ## Options: ## -i Select input device ## -o Select output device ### Create instance of Piano and Recorder p = Piano() rec = Recorder() log = Logger(p, rec) ### Options verbose = "-v" in argv ### Select input and output devices if "-i" in argv: [ins, outs] = p.listDevices() print("[+] List of input devices") for i in range(len(ins)): print("%d: %s" % (i + 1, ins[i])) inDev = ins[int(input("Select input device: ")) - 1] else: inDev = mido.get_input_names()[0] if "-o" in argv: print("[+] List of output devices")
class Manager(object): def __init__(self): self.screen_size = (1366, 768) # (width, height) self.camera_size = (640, 480) # (width, height) self.key_quit = 'q' self.aruco_dict = cv2.aruco.getPredefinedDictionary( cv2.aruco.DICT_ARUCO_ORIGINAL) self.update_piano_corners_freq = 5 # Number of frames to update piano corners self.img_to_project = np.zeros( (self.camera_size[1], self.camera_size[0], 3), np.uint8) # self.display = Display(screen_width=self.screen_size[0]) self.piano = Piano() self.cam_to_proj = None # Transformation from camera to projector coordinates self.song = [ "C#4", "C4", "F#5", "B4", "G5", "E5", "E5", "br", "F5", "D5", "D5", "br", "C5", "D5", "E5", "F5", "G5", "G5", "G5", "br", "G5", "E5", "E5", "br", "F5", "D5", "D5", "br", "C5", "E5", "G5", "G5", "C5" ] def calibrate_cam_to_proj(self): self.cam_to_proj = calibrate_projector(screen_size=self.screen_size, aruco_dict=self.aruco_dict) def run(self): self.calibrate_cam_to_proj() display = Display(screen_width=self.screen_size[0]) sound = Sound(wav_directory="wav") cap = cv2.VideoCapture(1) frame_num = 0 note_num = 0 # note index in the song is_initial_song_played = True # Flag which indicate if we did first play of the song is_clicked = False # Flag which indicate if user pressed on key history_frame_num = 10 erode_kernel = np.ones((5, 5), np.uint8) history_pts = None aruco_detect_params = cv2.aruco.DetectorParameters_create() aruco_detect_params.doCornerRefinement = True fgbg = cv2.createBackgroundSubtractorMOG2(history=4, varThreshold=50.0, detectShadows=False) while True: # Get an image from camera img = self._get_image(cap_obj=cap) frame_num += 1 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) fgmask = fgbg.apply(gray) # Add to background subtraction model # Find the piano board AruCo markers corners, ids, rejectedImgPoints = cv2.aruco.detectMarkers( gray, self.aruco_dict, parameters=aruco_detect_params) cv2.aruco.drawDetectedMarkers(img, corners, ids) # Display image for debug img_debug = img.copy() cv2.putText(img_debug, "%d" % frame_num, (8, 25), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0)) cv2.imshow('camera', img_debug) # If no markers were found continue to next frame if ids is None: continue # If we found the piano markers if len(ids) > 0: if frame_num % self.update_piano_corners_freq == 0: self.piano.update_coordinates(corners, ids) # Project a key self.img_to_project.fill(0) if self.piano.is_initialize(): if self.song[note_num] != 'br': # If note is not break piano_key_ind = self.piano.get_key_index_by_name( self.song[note_num]) pts = self.piano.get_key_polygon(piano_key_ind) if not (is_initial_song_played): color = self.piano.get_key_color(piano_key_ind) else: color = (0, 0, 255) cv2.fillPoly(self.img_to_project, [pts], color, cv2.LINE_AA) x = int((pts[0, 0, 0] + pts[1, 0, 0]) / 2.0 - 5) y = int((pts[0, 0, 1] + pts[1, 0, 1]) / 2.0 - 10) cv2.putText(self.img_to_project, "%s" % self.song[note_num], (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 255, 0)) # cv2.putText(self.img_to_project, "%d" % piano_key_ind, tuple(pts[3, 0, :]), # cv2.FONT_HERSHEY_PLAIN, 1.5, (255, 0, 0)) else: if is_initial_song_played: is_clicked = True # Play sound if not (is_initial_song_played): # Play note sound sound.play_note_sound(self.song[note_num]) # Advance to the next note time.sleep(0.5) note_num += 1 history_frame_num = frame_num else: if is_clicked: sound.play_note_sound(self.song[note_num]) time.sleep(0.5) note_num += 1 is_clicked = False history_frame_num = frame_num # history_pts = pts # Check if song has ended if note_num >= len(self.song): print("Song Finished!") time.sleep(0.5) if not (is_initial_song_played): is_initial_song_played = True note_num = 0 else: break # Plot debug image # cv2.imshow('img_to_project', self.img_to_project) # Detect key press if frame_num > history_frame_num + 7: key_mask = cv2.cvtColor(self.img_to_project, cv2.COLOR_BGR2GRAY) > 5 key_mask = np.uint8(key_mask) * 255 key_mask = cv2.erode(key_mask, erode_kernel) key_mask = key_mask.astype(bool) fgmask[~key_mask] = 0 num_pixels_in_key = np.sum(key_mask) num_pixels_changed = np.sum(fgmask > 0) frac_pixels_changed = float(num_pixels_changed) / float( num_pixels_in_key) if frac_pixels_changed > 0.05: print("Key clicked | Num pixels = %d | fraction = %.3f" % (num_pixels_changed, frac_pixels_changed)) is_clicked = True cv2.imshow('background_mask', fgmask) else: if history_pts is not None: cv2.fillPoly(self.img_to_project, [history_pts], (0, 255, 0), cv2.LINE_AA) # Transform image to projector coordinates dst = cv2.warpPerspective(self.img_to_project, self.cam_to_proj, self.screen_size) dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB) display.show_array(dst) # Wait for key from user key = cv2.waitKey(1) if key & 0xFF == ord(self.key_quit): break # When everything done, release the capture cap.release() cv2.destroyAllWindows() display.close() def _get_image(self, cap_obj, debug_transformation=False): """ Get image from camera :param cap_obj: OpenCV's VideoCapture object :return: Image as NumPy array """ # Capture frame-by-frame # This is a workaround to clean the buffer of the camera # We skip the first 5 frames # for w in range(1): # cap_obj.grab() ret, img = cap_obj.read() # Test camera-to-projector transformation by projecting camera image # back through projector if debug_transformation: # Transform image to projector for debug dst = cv2.warpPerspective(img, self.cam_to_proj, self.screen_size) self.display.show_array(dst) cv2.imshow('debug', img) return img