Декодирование азбуки Морзе — нетривиальная задача. Узнайте, как отличать точки от тире и буквы от слов. Попробуйте свой код прямо сейчас!
Когда я закончил генератор текста в азбуку Морзе, я думал, что декодирование будет той же задачей, но в обратную сторону. Как же я ошибался. Генерация сигнала означает, что вы контролируете каждую границу времени точно. Декодирование — это поиск этих границ в чужом несовершенном сигнале, и «несовершенный» — это норма, а не исключение. В этой статье я покажу, как решить эту задачу на Python, и объясню, почему тестирование на собственных данных может вас обмануть.
Когда вы генерируете азбуку Морзе, каждая точка, тире и пауза создаются из одной чистой базовой единицы. Нет никакой двусмысленности: тире — это всегда ровно 3 единицы, потому что вы так задали. При декодировании вы работаете с сырым сигналом (амплитуда звука во времени или позиции пикселей в изображении) и должны ответить на два отдельных вопроса для каждого импульса:
Решение, которое действительно сработало: вместо жёстко заданных абсолютных длительностей я классифицирую сигналы относительно самого короткого импульса в сообщении, принимая его за приблизительную единицу точки, а затем группирую все остальные импульсы и паузы относительно этого эталона. Реальная азбука Морзе неточна, поэтому в захваченном аудио нет точных соотношений 1:3:3:7, но даже слегка «дрожащая» рука человека всё равно группируется вокруг этих пропорций.
def classify_durations(pulses):
"""Классифицирует длительности импульсов как точки или тире.
pulses: список длительностей в миллисекундах.
"""
shortest = min(pulses) # аппроксимация единицы точки
unit = shortest
result = []
for d in pulses:
ratio = d / unit
if ratio < 2:
result.append('dot')
elif ratio < 5:
result.append('dash')
else:
result.append('dash') # запасной вариант для шумного входа
return resultЭто упрощённая версия — реальная реализация также должна фильтровать фоновый шум, обрабатывать дрейф скорости в длинном сообщении и решать, что делать, когда сигнал не группируется чётко (что случается чаще, чем вы думаете, если новичок стучит рукой).
В итоге я создал два отдельных инструмента, а не один, потому что входные данные принципиально различаются:
Аудио — это непрерывная амплитуда во времени. Нужно определить, где начинается и заканчивается тон относительно уровня шума. Это отдельная небольшая задача обработки сигнала, которая возникает ещё до классификации длительностей.
Изображение — это пространственная, а не временная структура: точки и тире как отметки на странице, где «длительность» — это ширина в пикселях, а паузы измеряются в пикселях, а не в миллисекундах. Логика соотношений та же, но конвейер обработки совершенно другой.
Попытка объединить оба случая в один общий код в начале сделала код сложнее для понимания, а не проще. Разделение было правильным решением, хотя базовая логика классификации (точка vs тире vs тип паузы) концептуально идентична.
Сначала я протестировал аудиодекодер на своих собственных WAV-файлах — он работал мгновенно, потому что мой генератор создаёт математически идеальные тайминги. Затем я попробовал его на реальной записи любительского радио, и точность заметно упала. В реальном сигнале есть дрейф скорости, неровные тире и фоновый шум — ничего из этого нет в синтезированном сигнале.
Этот разрыв между «работает на моих чистых тестовых данных» и «работает на реальных грязных входных данных» оказался самой сутью проекта, даже больше, чем сам алгоритм классификации. Это хорошее напоминание: тестирование на собственном генераторе — это просто тестирование собственных предположений.
Если вы работаете с декодированием импульсных сигналов — Морзе или любым бинарным ритмом — попробуйте такой подход: возьмите реальные данные (например, записи с радио) и посмотрите, как ваш алгоритм справляется с шумом. Не ограничивайтесь идеальными тестами. Начните с простой классификации по относительным длительностям, как в примере выше, а затем добавьте фильтрацию шума и обработку дрейфа. И помните: если ваш код работает на синтетике, это только первый шаг.
Хочешь закрепить знания на практике?
Решай задачи на Algolit — интерактивная платформа для обучения
Начать бесплатно →