midiアートをpng画像から生成する
Tsukuba DTM Lab. Advent Calendar 2019 9日目の記事です。
画像ファイルから直接midiファイルに変換する方法を考えていたらpythonでmidiを簡単に扱えるパッケージ(pretty_midi)を発見したので試してみました。とりあえず音楽理論は考慮していないので演奏してもめちゃくちゃです。
あと画像処理のためにOpenCVを使います。
pretty_midiの導入で参考にさせていただいた記事です↓
<実行環境>
python 3.7.3
OpenCV 4.1.1
<手順>
1.OpenCVで画像をnumpy配列に取り込み
2.ピクセルを走査してそこが黒っぽかったら、velocity=100、16分音符でmidiを設置
つまり画像の縦1ピクセルがmidiの音階、画像の横1ピクセルがmidiの16分音符(休符)に値します。黒いピクセルの分だけmidiを設置するので音符は大量になります。
コードです(python)
import numpy as np
import cv2 #OpenCV import pretty_midi
#midiノート番号は0~127らしい。
#準備
img = cv2.imread("./G002.png") #入力画像
h, w, c = img.shape #画像サイズを取得
pm = pretty_midi.PrettyMIDI(resolution=960, initial_tempo=120)
instrument = pretty_midi.Instrument(0) #トラックのようなものらしい
for j in range(h): #縦
for i in range(w): #横
luminance = img.item(j, i, 0) + img.item(j, i, 1) + img.item(j, i, 2) #RGBそれぞれを足す(てきとう)
if luminance < 450: #黒いところ
note = pretty_midi.Note(velocity=100, pitch=h-j, start=i*0.25, end=i*0.25+0.25) #NoteOn->start、NoteOffE->end
instrument.notes.append(note) #ノート(音符)を追加
pm.instruments.append(instrument) #トラックを追加
pm.write('test03.mid') #midiファイルを書き込み
ピクセルは上から走査しているのでpitchに代入するときは数値的には上下逆転します。
入力画像がこれです。音階(縦の目盛り)に限りがあるので、少なくとも縦が128px以下じゃないと見切れちゃいます。白黒画像でやりましたが普通にカラー画像でできます。
>出力結果(test03.mid)
pretty_midiについてはまだわからないことだらけですが、なんかとりあえずできました。
トラックを複数作れば色分けができるので、カラー対応も頑張ればできるかなと思います。コード進行とかも考慮できるようにしたいと思ったのですがpythonにはswitch文がないんですね・・・。
ほんとはC++でやろうと思ってたんですが、XcodeでOpenCVライブラリの設定がうまくいかず挫折しました。
この記事が気に入ったらサポートをしてみませんか?