[Python] Change images in a window via real time MIDI messages

Discussão em 'Python' iniciado por Stack, Março 4, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to create a program that will

    • read in images from a dir and store in a list
    • display first image in list in a window
    • MIDI notes from USB MIDI Controller triggers a new image in the same window
      • the new image is retrieved using the note value and matching index from list of images

    I've seen plenty of examples of being able to do the above separately, but am stuck on how to combine them all in one. I have not been able to find any examples of bindings to MIDI messages -- only for key and button presses.

    Currently my code can open up a matplotlib window and display first image, but the code is stuck until the window is closed. After closing window, I can see MIDI notes in streaming output but no window for images is visible.

    When I tried to use show(block=False) a window with no image would open, but I can at least see MIDI input stream. An image never shows up in window.

    I'm open to trying other libraries (TKinter, PyQT5, etc) but I couldn't find any examples that they would be any different.

    Here is my code so far

    import matplotlib
    import os, sys
    import mido
    import cv2

    def get_images(path: str) -> list:
    """
    Recursively crawl through dir and load in all images
    """
    images = []
    image_files = glob.glob(os.path.join(path, '*'))
    print(image_files)

    for i in image_files:
    images.append(cv2.imread(i))

    return images


    def get_midi_port():
    # Get a list of available input port names
    input_ports = mido.get_input_names()

    # Get first port that is not a Through type
    for p in input_ports:
    if "Midi Through" not in p:
    print(p)
    port = p
    return p

    if not input_ports or not p:
    raise Exception("No MIDI input ports found.")

    class MIDI_Images():
    def __init__(
    self,
    path="."
    ):
    self.path = path
    self.loaded_images = get_images(self.path)
    self.curr = 0
    if auto_start:
    self.fig, self.ax = plt.subplots()
    self.display()
    plt.show(block=False) ## opens window but no image
    plt.pause(0.1)
    ### plt.show() ## shows image but code doesn't continue for MIDI notes

    ### Ingest MIDI messages
    try:
    p = get_midi_port()

    with mido.open_input(p) as inport:
    inport.poll()
    print(f"Listening for MIDI messages on port: {inport.name}")
    while True:
    for msg in inport.iter_pending():
    print(msg)
    self.curr = msg.note - 24 ## lowest note on my controller is 24
    self.update_image()

    except Exception as e:
    print(f"Error: {e}")

    def update_image(self):
    """
    Load in next image
    """

    # advance to next image
    try:
    self.im.set_array(self.loaded_images[self.curr])
    self.display()
    ## self.fig.canvas.draw_idle() ## waits for image window to close if uncommented
    except IndexError:
    print("Sorry no image in index: ", n)

    def display(self):
    """
    Orchestrating function to run
    """

    image = self.loaded_images[self.curr]

    self.im = self.ax.imshow(image)

    ### Examples of key bindings working just fine
    # self.fig.canvas.mpl_connect("key_press_event", self.next_image)


    if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description='')

    parser.add_argument('--imagedir', action="store", dest='imagedir', default='')

    args = parser.parse_args()

    MIDI_Images(args.imagedir)

    Continue reading...

Compartilhe esta Página