スクリーンショット_2019-12-02_13

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以下じゃないと見切れちゃいます。白黒画像でやりましたが普通にカラー画像でできます。

画像1

>出力結果(test03.mid)

スクリーンショット 2019-12-02 13.02.46


pretty_midiについてはまだわからないことだらけですが、なんかとりあえずできました。

トラックを複数作れば色分けができるので、カラー対応も頑張ればできるかなと思います。コード進行とかも考慮できるようにしたいと思ったのですがpythonにはswitch文がないんですね・・・。

ほんとはC++でやろうと思ってたんですが、XcodeでOpenCVライブラリの設定がうまくいかず挫折しました。

この記事が気に入ったらサポートをしてみませんか?