
Здравствуйте! Меня зовут Ада Ло́пес, я студентка первого курса факультета «Креативные технологии и ИИ» в Университете Хауэст в Кортрейке.
Этот проект — моя первая полностью самостоятельная работа по интеграции искусственного интеллекта с «железом». Фортепианный тренер на базе ИИ — интерактивный комплекс для помощи начинающим в обучении игре на фортепиано. Система предоставляет обратную связь в реальном времени и отслеживает исполнение заранее заданной мелодии.
Под катом — весь путь создания проекта. Мы пройдем от обучения ИИ-модели и создания корпуса — до построения контура обратной связи и решения проблем с потоковой передачей данных в реальном времени. Опыт получился отличным! Он был наполнен отладкой, открытиями и множеством ночных тестов.
В основе лежит простая идея: пользователь играет на клавиатуре мелодию «Twinkle, Twinkle, Little Star». В это время USB‑камера, подключенная к Raspberry Pi и установленная над клавишами, фиксирует каждое нажатие. Видеопоток в реальном времени передается на ноутбук. Там обученная мною модель для распознавания объектов YOLOv8 определяет, какая же клавиша нажата.
Далее распознанная нота отправляется обратно на Raspberry Pi. Устройство сравнивает ее с ожидаемой нотой в последовательности и выводит результат на ЖК-дисплей, подключенный через интерфейс I2C. В конце песни тренажер показывает итоговую оценку точности и даже проигрывает мелодию с помощью зуммера, сигнализируя об окончании сеанса.
Оборудование, материалы и ПО
Ниже представлен полный перечень всего, что потребовалось. Что‑то уже было, что‑то пришлось позаимствовать из учебных наборов, поэтому итоговая стоимость может оказаться и ниже — тут все зависит от ваших запасов.
Категория |
Компонент |
Примечание / Стоимость |
Электроника и оборудование |
Raspberry Pi 8GB |
€88.95 |
USB-камера |
€23.39 |
|
Набор для проектов Freenove |
€52.59 |
|
Ноутбук |
Из личных запасов |
|
MIDI-клавиатура |
Из личных запасов |
|
Материалы для корпуса |
Листы мультиплексной фанеры толщиной 4 мм |
4 шт., €18 |
Услуги лазерной резки |
Выполнено в университете, €5 |
|
Светодиодная лента |
€7 |
|
Программное обеспечение и библиотеки |
MakerCase + Inkscape |
Для проектирования и кастомизации корпуса |
Roboflow |
Бесплатный аккаунт для создания и обучения набора данных |
|
YOLOv8 (через библиотеку ultralytics) |
Легковесная модель для распознавания объектов |
|
Python-библиотеки: |
||
opencv-python |
Для захвата и визуализации видео |
|
socket |
Для обмена данными между Pi и ноутбуком |
|
smbus |
Для управления ЖК-дисплеем по I2C |
|
csv, os, datetime |
Для логирования и работы с файлами |
|
playsound |
Для воспроизведения превью мелодии |
Шаг 1. Создание пользовательского набора данных
Чтобы наша модель детекции работала в конкретных условиях, не получится полагаться на существующие наборы данных. Большинство общедоступных датасетов либо содержат изображения целых клавиатур, либо обучены для распознавания объектов общего назначения. Нам же нужны были качественные, сфокусированные изображения именно нашей клавиатуры.

Работа начинается с фотографирования нажатий клавиш. Важно охватить все восемь меток: c_pressed
, d_pressed
, e_pressed
, f_pressed
, g_pressed
, a_pressed
, b_pressed
и одну для состояния без нажатия. Загружаем снимки в Roboflow и приступаем к их разметке.
Всего вручную с помощью инструмента аннотирования в Roboflow было размечено около 200 изображений. Пришлось позаботиться о том, чтобы включить в выборку руки разных размеров, различные условия освещения и небольшие изменения угла съемки. Такой подход помогает модели лучше обобщать данные и эффективнее работать в реальных условиях. Этот этап подчеркивает фундаментальный принцип прикладного машинного обучения: успех алгоритма напрямую зависит от качества и релевантности исходных данных.

Игровой сервер с криперами и порталом в Незер. Добывайте ресурсы, стройте объекты, исследуйте мир Selectel в Minecraft и получайте призы.
Шаг 2. Обучение модели
После разметки и загрузки набора данных переходим к обучению модели. Для этого используем веб-интерфейс Roboflow. Сама модель распознавания объектов — YOLOv8. Выбор пал именно на нее из-за оптимального баланса между скоростью и точностью — ключевого фактора для детекции в реальном времени.
Начинаем с базовой аугментации данных: отражение, коррекция яркости и кадрирования. Такие небольшие хитрости дополнительно улучшают способность модели к обобщению, что особенно важно при работе с относительно небольшим набором данных. Модель обучалась на протяжении 100 эпох с использованием встроенных инструментов Roboflow. В ходе процесса отслеживались такие метрики, как mAP@50
, precision
(точность) и recall
(полнота).

Последняя версия v4 нашей модели достигла показателя mAP@50
в 99,5%, при точности 90,4% и полноте 100%. Далее модель экспортировалась в формате Python с помощью inference_sdk
от Roboflow и началась ее подготовка для локального запуска на ноутбуке. Поскольку Raspberry Pi не справляется с обработкой YOLOv8, он будет отвечать только за трансляцию видео и управление обратной связью, в то время как ноутбук возьмет на себя все вычисления для распознавания.
Шаг 3. Построение контура обратной связи в реальном времени
Контур обратной связи — сердце всего проекта. Raspberry Pi захватывает видео с USB‑камеры и отправляет кадры на ноутбук через сокет-соединение. Там кадры принимаются и передаются в обученную модель YOLOv8 для анализа. Результат — метка вроде c_pressed
— отправляется обратно на Raspberry Pi через второй сокет.

Такое разделение задач — яркий пример прагматичного инженерного подхода. Ограниченные вычислительные ресурсы Raspberry Pi не позволяют запускать на нем ресурсоемкую нейросеть. Поэтому создается распределенная система: маломощное устройство на краю сети (edge device) собирает данные, а более производительный компьютер выполняет сложные вычисления. Такая архитектура является миниатюрной моделью многих современных систем интернета вещей (IoT) и периферийных вычислений.
На Pi другой скрипт получает предсказанную метку и сравнивает ее с текущей ожидаемой нотой в мелодии. Для этого используется простой список из 14 нот, составляющих «Twinkle, Twinkle, Little Star». Каждое верное совпадение засчитывается. В конце песни Pi вычисляет процент точности и отображает итоговый результат на ЖК-дисплее.
Шаг 4. Отображение результатов на ЖК-дисплее
Обратная связь на ЖК‑дисплее была необходима, чтобы сделать взаимодействие с тренажером по-настоящему интерактивным и завершенным. Был взят ЖК‑экран размером 16×2 с интерфейсом I2C, подключенный к Raspberry Pi через выводы GPIO.

Для управления экраном пришлось написать собственный класс на Python — LCD.py. Он отвечает за побитовую передачу данных с помощью библиотеки smbus
. На первой строке дисплея в реальном времени отображается каждая распознанная клавиша, а на второй — сообщения вроде «Song Finished!» и итоговая оценка точности. Класс включает низкоуровневые функции для отправки символов, строк и специальных команд, таких как очистка экрана или установка курсора. Написание модуля «с нуля» оказалось и увлекательно, и познавательно. Его разработка позволила глубже понять принципы I2C‑адресации и битовых манипуляций.
from smbus import SMBus
import time
class LCD:
I2C_ADDR = 0x27
LCD_CHR = 1
LCD_CMD = 0
LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0
LCD_BACKLIGHT = 0x08
ENABLE = 0b00000100
E_DELAY = 0.0005
def __init__(self):
self.bus = SMBus(1)
self.lcd_init()
def lcd_init(self):
self.send_byte(0x33, self.LCD_CMD)
self.send_byte(0x32, self.LCD_CMD)
self.send_byte(0x06, self.LCD_CMD)
self.send_byte(0x0C, self.LCD_CMD)
self.send_byte(0x28, self.LCD_CMD)
self.send_byte(0x01, self.LCD_CMD)
time.sleep(0.05)
def send_byte(self, bits, mode):
bits_high = mode | (bits & 0xF0) | self.LCD_BACKLIGHT
bits_low = mode | ((bits << 4) & 0xF0) | self.LCD_BACKLIGHT
self.bus.write_byte(self.I2C_ADDR, bits_high)
self.send_byte_with_e_toggle(bits_high)
self.bus.write_byte(self.I2C_ADDR, bits_low)
self.send_byte_with_e_toggle(bits_low)
def send_byte_with_e_toggle(self, bits):
time.sleep(self.E_DELAY)
self.bus.write_byte(self.I2C_ADDR, (bits | self.ENABLE))
time.sleep(self.E_DELAY)
self.bus.write_byte(self.I2C_ADDR, (bits & ~self.ENABLE))
time.sleep(self.E_DELAY)
def send_instruction(self, instruction):
self.send_byte(instruction, self.LCD_CMD)
def send_character(self, char):
self.send_byte(ord(char), self.LCD_CHR)
def send_string(self, message, line=LCD_LINE_1):
self.send_instruction(line)
for char in message:
self.send_character(char)
def clear(self):
self.send_instruction(0x01)
def display_on(self):
self.send_instruction(0x0C)
def display_off(self):
self.send_instruction(0x08)
def cursor_on(self):
self.send_instruction(0x0E)
def cursor_off(self):
self.send_instruction(0x0C)
Шаг 5. Воспроизведение превью мелодии
Чтобы помочь пользователям освежить в памяти мелодию перед началом игры, была добавлена возможность прослушать превью «Twinkle, Twinkle, Little Star». При запуске программа задает вопрос: «Do you want to hear the song first? (y/n)». Если пользователь отвечает утвердительно, с помощью пакета playsound
о для Python воспроизводится короткий mp3-файл. Такой небольшой приятный музыкальный штрих способствует лучшему запоминанию.

Аудиофайл хранится в каталоге assets/
и проигрывается на ноутбуке до начала трансляции видео. Казалось бы, такая небольшая функция, а инструмент стал дружелюбнее и увлекательнее, особенно для начинающих музыкантов.
Шаг 6. Сигнал об окончании с помощью зуммера
Поскольку корпус закрытый и не позволяет видеть внешние светодиоды, для оповещения об окончании сеанса использовался зуммер. Подключаем его к выводу GPIO18 и проигрываем какую‑нибудь незатейливую композицию с помощью ШИМ (PWM). Звуковой сигнал не просто информирует о завершении песни — весь процесс становится динамичнее. Зуммер срабатывает после обработки всех 14 нот и отображения результатов на дисплее.
Шаг 7. Визуализация предсказаний и инструменты отладки
Окно на стороне ноутбука открывает функция cv2.imshow()
. В нем отображается видео с веб-камеры и наложенные результатами распознавания. Также показывается текущая клавиша, которую удалось определить, ограничивающие рамки (bounding boxes) и счетчик кадров в секунду (FPS).

Подход показал себя чрезвычайно полезным. Он помог отлаживать низкую частоту кадров и быть уверенным, что модель ведет себя корректно в реальном времени. Кроме того, позволил протестировать производительность алгоритма при слабом освещении, различном положении рук и на разных фонах. Создание таких инструментов визуализации считается признаком зрелого подхода к разработке: программист не просто пишет код, а создает средства для его анализа и проверки.
Шаг 8. Логирование и отслеживание точности
Каждый сеанс игры журналируется в CSV-файл. Строки содержат временну́ю метку, ожидаемую клавишу, распознанную клавишу и отметку о совпадении. Подробная запись чрезвычайно полезна для выявления ошибок модели и отслеживания улучшений от версии к версии.

Raspberry Pi сохраняет логи в папку logs/
внутри каталога RPi/
. Пришлось написать вспомогательные функции для очистки буфера сокета перед каждым сеансом, чтобы избежать «фантомных» предсказаний из предыдущих запусков. Такой систематический сбор данных и внимание к деталям, как очистка буфера, отличают надежный прототип от простого эксперимента.
Шаг 9. Функция повтора и сброс
После завершения последовательности из 14 нот Raspberry Pi вычисляет итоговую точность и выводит ее на ЖК-дисплей. В этот момент зуммер проигрывает свою мелодию, а пользователю предлагается сыграть еще раз. Если ввести «y», сеанс сбрасывается: ЖК-дисплей очищается, буфер сокета опустошается, и все начинается сначала. Так, легко практиковаться несколько раз подряд и отслеживать свой прогресс.
Шаг 10. Структура проекта и GitHub
Кодовая база разделена на папки с понятными названиями:
AI/
— содержит скрипт для инференса на ноутбуке и код для превью мелодии;RPi/
— включает класс для LCD, сокет-клиент, логику логирования и скрипт-запускатор run_all_pi.py, который для удобства запускает оба скрипта на стороне Pi параллельно;assets/
— хранит аудиофайл для превью;drafts/
— неиспользуемый экспериментальный код.

Проект также включает файл README.md с общими инструкциями и feedforward.md с размышлениями о процессе работы. Хорошая организация кода и наличие документации — не менее важная часть, чем сама функционирующая система. Забота о справочных материалах не только показывает уважение к другим разработчикам, но и превращает личный проект в ресурс, которым может воспользоваться сообщество.
Репозиторий: GitHub.
Шаг 11. Проектирование деревянного корпуса
Прежде чем что-либо собирать, хорошо бы убедиться, что камера будет расположена на правильной высоте и под нужным углом. Измерения показали, что оптимальная высота для съемки клавиатуры составляет от 40 до 45 см от основания. С учетом расчетов 3D‑модель корпуса с шиповыми соединениями создали с помощью MakerCase. Затем импортировали дизайн в Inkscape для дальнейшей доработки.

Добавили точные вырезы для USB‑камеры (4.5x2 см) и ЖК‑дисплея (8x3.6 см), а также внесли несколько творческих дополнений. Нижняя передняя панель была удлинена, чтобы на ней можно было разместить ноты, а верхняя — чтобы было место для приклеивания светодиодной ленты. Эти дополнения сделали конструкцию более функциональной и визуально интересной.
Шаг 12. Сборка деревянного корпуса
Когда дизайн был закончен, мы экспортировали его и вырезали все необходимое на лазерном станке в университете. Материал — листы 4‑миллиметровой мультиплексной фанеры. После того как все детали изготовлены, единственное, что остается, — собрать их с помощью столярного клея. Несколько нарисованных от руки элементов добавили корпусу индивидуальность. Шиповые соединения облегчили сборку, а конечная конструкция получилась прочной и устойчивой.

Сбоку есть отверстие для вывода кабелей, а расширенные панели мы использовали точно по назначению: одна — для размещения нот во время игры, другая — для крепления светодиодной ленты, освещающей эти ноты. Современные технологии действительно объединяют проектирование, код и работу с материалами в единый творческий процесс.
Заключительные мысли и выводы
Этот проект помог мне вырасти и как разработчику, и как мейкеру. Я научилась собирать и размечать наборы данных, обучать модель, отлаживать системы реального времени, использовать побитовые операции для управления ЖК-дисплеем и создавать физический прототип.

Система не безупречна — иногда быстрые или слишком мягкие нажатия остаются незамеченными, но она надежно работает при игре в стабильном темпе. Самое главное — это увлекательный и мотивирующий способ практиковаться в игре на фортепиано и исследовать пересечение музыки, искусственного интеллекта ПО и «железо». Честный взгляд на недостатки не умаляет достигнутого, а наоборот, подчеркивает главную ценность — полученный опыт и знания.
Я невероятно горжусь этим первым самостоятельным проектом и с нетерпением жду возможности учиться дальше.
Комментарии (5)
Prohard
19.07.2025 13:08Так кто автор-то? Ада Лопес или Зорин? И страну, где этот университет, тоже надо писать. А так на манию величия смахивает.
oneastok Автор
19.07.2025 13:08Данные об авторе есть (вверху, второе предложение после приветствия):
автор оригинального текста: Ада Ло́пес;
место учебы автора: Факультет «Креативные технологии и ИИ» в Университете Хауэст в Кортрейке.
Ссылка на оригинальную публикацию (под названием статьи): https://www.instructables.com/AI-Powered-Piano-Trainer-Learn-Songs-With-Real-Tim/
Johan_Palych
19.07.2025 13:08Из перевода непонятно, что за железо использовалось. Открыл первоисточник.
Raspberry Pi 5 - 8GB
Logitech C270 - 720p HD Webcam - 3MP - Grijs
Freenove Projects Kit for Raspberry Pi 5 / 400 / 4B / 3B+ / 3B
You can check out my GitHub here - уже убралиoneastok Автор
19.07.2025 13:08Про GitHub автора действительно пропала строчка. Искренне благодарю за внимательность! Вернул пропажу в конец 10‑го шага.
Tyusha
Как известно, научиться играть на фортепиано очень просто — надо всего лишь нажимать нужные клавиши в нужное время.