Denis Cera

Notes recognition

Описание проекта

Recognition of music sheet and transcribing it into MIDI

Подход к распознаванию нот

После определённого количества безуспешных попыток написания проекта с нуля и проверки разных подходов, наткнулся на следующую статью:  В ней описан подход к распознаванию нот с помощью связки Convolutional и Recurrent сетей. Этот подход используется, в частности, для распознавания текста. Поэтому я решил взять одну из реализаций Optical Character Recognition и обучить сеть на базе нот. 

Была выбрана эта tensorflow модель. Научная статья, объясняющая принцип её работы. 

Датасет

Наиболее полная информация касательно датасетов по распознаванию нот находится здесь. Однако, датасетов с размеченной высотой нот, подходящих для моих задач не нашлось. Единственный доступный датасет со звуковысотным маппингом был взят отсюда, у ребят написавших оригинальную статью, ссылка на которую представлена выше. Он представляет из себя сгенерированные в Lilypond изображения с соответствующими лейблами для каждой ноты и знака.

Характеристики датасета

94,984 случайных монофонических последовательностей, состоящих из 52 символов: музыкальных нот от С4 до Е5, 4 длительности (половина, четверь, восьмая, шестнадцатая), 4 паузы тех же длительностей, символы размеров (3/4, 4/4, 6/8), знаки альтерации (диез, бемоль, бекар), скрипичный ключ, тактовая черта.

Поскольку датасет составлен из сгенерированных изображений, распознавание не будет адекватно работать с фотографиями. Также, с нотами, чья структура отличается от характеристик датасета.

Датасет был обработан, чтобы соответстовать требованиям сети для обучения (созданы лейблы, изображения уменьшены и т.д.). 95% - обучающая выборка 5% - тестовая. 

Обучение

Сеть обучалась в течение около 8 часов на  NVIDIA Tesla K80. 16 эпох. 

Сложности

1. Сейчас модель может распознавать небольшие последовательности. Ей нельзя скормить весь лист с нотами. Однако, эта проблема решаема. Я пытался сделать сегментацию листа (вычленение тактов) силами OpenCV и добился определённых результатов. Но код очень по-разному работает для изображений разного качества. Поэтому, в долгосрочной перспективе, тут нужно тренировать отдельный слой сети. Для этого нужны данные с разметкой тактов, систем и прочих высокоуровневых элементов системы нотного листа.

2. Не успел сделать конвертацию в MIDI. К сожалению, вопрос в лоб не решить. Думал просто конвертировать обратно в Lilypond но сделать это оказалось не так легко из-за того, что программа сама проставляет знаки альтерации в зависимости от тональности и ещё пары тонкостей. Возможно, тут лучше подойдёт OpenXML, на изучение формата которого, однако, у меня не хватило времени. Если успею и всё получится, реализую в ближайшие дни. Следите за гитхабом.

3. Также не хватило времени на "выкат в продакшен" версии для удобного тестирования без каких-либо установок. Поэтому, чтобы поиграться с распознаванием, нужно поставить https://github.com/emedvedev/attention-ocr и запустить функцию тестирования, это опишу ниже.

4. Также не успел, как следует протестить и собрать статистику. Единичный прогон по тестовой выборке показал результат в 99,5%. 

Как запустить

Устанавливаем https://www.tensorflow.org/install/

Устанавливаем https://github.com/emedvedev/attention-ocr

Качаем тестовую выборку: https://github.com/Dene33/notes-recognition/blob/master/notesTest.tfrecords?raw=true

Качаем чекпоинты (это и есть обученная модель) и распаковываем: https://github.com/Dene33/notes-recognition/blob/master/checkpoints.zip?raw=true

Запускаем: 

aocr test --visualize ПУТЬ/К/notesTest.tfrecords --log-path ./log/log.log --max-width 1000 --max-height 61 --max-prediction 36 --full-ascii --model-dir ПУТЬ/К/checkpoints

Небольшое примечание. Распакованные checkpoints.zip содержат папку checkpointsDL - путь нужно указывать к ней.

Наблюдаем за процессом. А потом смотрим на результат в папке log. Там будут находиться папки для каждой картинки, для которой было проведено распознавание. В каждой папке файл word.txt где первая строка - предсказанный результат, вторая - ground-truth Также в папке находится гифка, показывающая процесс работы нейросети.

Для перевода результата в читаемый формат (переименование папок и файлов), кидаем питоновский скрипт в папку out и запускаем.

Быстрая установка и запуск на Линуксе

sudo pip install aocr
pip install tensorflow

git clone https://github.com/Dene33/notes-recognition
cd notes-recognition
unzip checkpoints.zip -d checkpoints

aocr test --visualize notesTest.tfrecords --max-width 1000 --max-height 61 --max-prediction 36 --full-ascii --model-dir ./checkpoints/checkpointsDL

Тест на своём датасете

Чтобы протестировать на своих картинках, создаём папку с картинками. Максимальная высота картинок - 60, ширина - 1000. Создаём текстовый файл (например labels.txt) с лейблами такого формата:

./datasets/images/hello.jpg hello
./datasets/images/world.jpg world

где ./datasets/images/hello.jpg - путь до картинки, hello - её лейбл. Какому символу какая нота соответствует можно посмотреть тут, где 1 столбец - лейблы, 2 - соответствующая нота или знак.

Затем, чтобы создать tfrecord из картинок выполняем:

aocr dataset ПУТЬ/К/labels.txt ПУТЬ/К/МОДЕЛИ/testing.tfrecords

Запускаем: 

aocr test --visualize ПУТЬ/К/testing.tfrecords --log-path ./log/log.log --max-width 1000 --max-height 61 --max-prediction 36 --full-ascii --model-dir ПУТЬ/К/checkpoints

Примеры картинок из обучаемой выборки и соответствующих лейблов:

 MRRRROT:3+)R*

 MRRN;RK+3R"QR<L+6

 MSSO6S4'

Ссылка на .tfrecord который использовался для обучения модели: https://drive.google.com/file/d/1wd716Lg6Uz5Vxr6x-vEeoLKMb09YapPL/view?usp=sharing

TODO

1. Экспорт SaveModel для Tensorflow

2. Конвертация в MIDI. Этим я занимаюсь в настоящий момент, можно ожидать в ближайшие дни.

3. Сегментация листа на такты и обратная сборка всей структуры после прохода распознаванием по каждому сегменту

4. Поднять Tensorflow Serving

5. Разметка датасета под распознавание фотографий и более широкого спектра символов

 

ETH-wallet: 0x136f0a3d6f3Db9db3b742153a396B8b47721Bb24

Состав команды:

  • Denis Cera, code

Комментарии

Ivan Panin

А не сравнивали качество с традиционными программами распознавания нот без нейросетей? https://en.wikipedia.org/wiki/Optical_music_recognition

Denis Cera

Традиционные подходы работают более-менее, но 1. требовательны к качеству входного изображения - нужны отсканированные листы. 2. Не работают/работают плохо с рукописными нотами. Ну и конечно же, 3. большая часть подобного софта - проприетарные продукты. Нейронные же сети можно обучить распознавать ноты и на обычных фотографиях с телефона (был бы датасет подходящий).

Pavel Mochalov

В обратную сторону музыку в ноты переводить тоже можно? Не в рамках этого проекта, а вообще в принципе. Импровизируешь, потом читаешь.

Denis Cera

Насколько я знаю, распознавание звука - более тривиальная задача, решаемая без использования нейронных сетей. Особенно, если говорить о монофонических мелодиях. С полифоническими уже сложнее, но тоже реально, особенно если играет один инструмент. Что касается записей с большим количеством инструментов - тут нейронные сети уже могли бы найти применение, да. Не уверен, что есть какие-то прям хорошие реализации для подобного, но могу ошибаться.

Иван Федоров

По поводу символов - было  бы круто, если бы проект  в будущем научился распознавать ноты для барабанщиков. Прикол в том, что если есть слух, то прослушать и повторить проще, чем разбирать ноты и считать длительности)
А на будущее, можно было бы еще  подумать насчет интеграции с каким-нибудь существующим музыкальным ПО, тот же guitar pro, например...
Или вообще уйти в другую сторону и по нотам генерировать какую-нибудь игру, типа tap-tap:)

Denis Cera

Распознавание нот для барабанщиков во многом даже легче реализовать (за счёт меньшего количества нотационных символов). Всё дело сводится лишь к размеченному дата сету, сама сеть работает отлично.

То, что слушать и повторять легче, чем копаться в нотах - это прям то, из-за чего я решил взяться за этот проект. Я пою в хоре и иногда хочется просто прослушать, как звучит партия. :) Надеюсь, со временем получится довести проект до уровня "сфотографировал партию, прослушал".

Гитар про умеет импортировать MIDI файлы. Тут главное найти наиболее удобный способ для работы с выходными данными, да. Сейчас они генерируются в MIDI посредством питоновской библиотеки mido.

Denis Cera

Буквально нескольких часов не хватило, чтобы закончить конвертацию в MIDI. На гитхабе добавлено пояснение того, как работает. В папку out кидаем этот скрипт: https://github.com/Dene33/notes-recognition/blob/master/python-util-scripts/toMidiRenamer.py и запускаем. Он создаст .py файл для каждого распознанного изображения. Запустив файл, проиграется MIDI и создастся .mid файл для соответствующего распознанного изображения.