You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修改midi2img库img2midi代码批量处理samples文件夹图片生成MIDI

修改后完整代码

from PIL import Image
import numpy as np
from music21 import instrument, note, chord, stream
import os
import sys

lowerBoundNote = 21
def column2notes(column):
    notes = []
    for i in range(len(column)):
        if column[i] > 255/2:
            notes.append(i+lowerBoundNote)
    return notes

resolution = 0.25
def updateNotes(newNotes,prevNotes): 
    res = {} 
    for note in newNotes:
        if note in prevNotes:
            res[note] = prev_notes[note] + resolution
        else:
            res[note] = resolution
    return res

def image2midi(image_path):
    with Image.open(image_path) as image:
        im_arr = np.fromstring(image.tobytes(), dtype=np.uint8)
        try:
            im_arr = im_arr.reshape((image.size[1], image.size[0]))
        except:
            im_arr = im_arr.reshape((image.size[1], image.size[0],3))
            im_arr = np.dot(im_arr, [0.33, 0.33, 0.33])

    """ convert the output from the prediction to notes and create a midi file
        from the notes """
    offset = 0
    output_notes = []

    # create note and chord objects based on the values generated by the model

    prev_notes = updateNotes(im_arr.T[0,:],{})
    for column in im_arr.T[1:,:]:
        notes = column2notes(column)
        # pattern is a chord
        notes_in_chord = notes
        old_notes = prev_notes.keys()
        for old_note in old_notes:
            if not old_note in notes_in_chord:
                new_note = note.Note(old_note,quarterLength=prev_notes[old_note])
                new_note.storedInstrument = instrument.Piano()
                if offset - prev_notes[old_note] >= 0:
                    new_note.offset = offset - prev_notes[old_note]
                    output_notes.append(new_note)
                elif offset == 0:
                    new_note.offset = offset
                    output_notes.append(new_note)                    
                else:
                    print(offset,prev_notes[old_note],old_note)

        prev_notes = updateNotes(notes_in_chord,prev_notes)

        # increase offset each iteration so that notes do not stack
        offset += resolution

    for old_note in prev_notes.keys():
        new_note = note.Note(old_note,quarterLength=prev_notes[old_note])
        new_note.storedInstrument = instrument.Piano()
        new_note.offset = offset - prev_notes[old_note]

        output_notes.append(new_note)

    prev_notes = updateNotes(notes_in_chord,prev_notes)

    midi_stream = stream.Stream(output_notes)
    # 优化文件名生成逻辑,适配所有常见图片后缀
    img_filename = os.path.basename(image_path)
    midi_filename = os.path.splitext(img_filename)[0] + ".mid"
    midi_stream.write('midi', fp=midi_filename)

if __name__ == "__main__":
    # 默认读取samples文件夹,也支持通过命令行参数指定其他文件夹路径
    img_dir = sys.argv[1] if len(sys.argv) > 1 else "samples"
    # 支持的图片格式
    support_ext = (".png", ".jpg", ".jpeg", ".bmp")
    # 遍历目录下所有文件
    for filename in os.listdir(img_dir):
        if filename.lower().endswith(support_ext):
            img_path = os.path.join(img_dir, filename)
            print(f"正在处理:{img_path}")
            image2midi(img_path)
    print("所有图片处理完成")

修改说明

  • 新增os模块导入,用于目录遍历和文件路径处理
  • 优化了MIDI文件名生成逻辑,不再仅支持jpeg格式,自动适配所有常见图片后缀
  • 替换原有的单文件读取逻辑,默认自动遍历samples目录下的所有符合格式的图片,也支持通过命令行参数指定其他图片文件夹路径
  • 新增处理进度提示,控制台会打印当前正在处理的文件路径,处理完成后会给出提示

使用方法

直接在终端运行以下命令即可自动处理samples文件夹下的所有图片:

python img2midi.py

如果需要指定其他图片文件夹,也可以传入文件夹路径作为参数:

python img2midi.py 你的图片文件夹路径

内容的提问来源于stack exchange,提问作者mohamed mostapha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 09:18:01