Существует ряд задач, в которых длительный по времени сигнал разбивается на сегменты, каждый из которых обрабатывается по отдельности. В частности, такой подход используется для анализа сигнала с помощью оконного преобразования Фурье, или наоборот, при синтезе; а также при спектральной обработке типа удаления шума, изменения темпа, нелинейной фильтрации и других.
Сам процесс разбиения математически представляется умножением на некоторую весовую (оконную) функцию со смещением. Для самого простого окна — прямоугольного — это может выглядеть так:
Исходный сигнал:
Разбиения:
Можно восстановить исходный сигнал, просто просуммировав их.
Однако по ряду причин прямоугольная функция — не самая лучшая оконная функция. При спектральном анализе через (обычно быстрое) дискретное преобразование Фурье анализируемый блок данных как бы «зацикливается», что приводит к разрыву на краях и искажению спектра:
Не является оно подходящим и для обратного синтеза — поскольку любое изменение также приведёт к разрывам — например, если мы попробуем реверсировать одну из частей:
Для устранения этих недостатков используется перекрытие — когда каждое следующее окно захватывает часть данных из предыдущего; а весовое окно, соответственно, плавно спадает к краям.
Наиболее часто для этого используют окно Ханна (известное также под названием «приподнятый косинус») с перекрытием в 50%:
За счёт симметричности функции косинуса при сложении они суммируются в единицу:
Теперь при обратном синтезе мы не получим разрывов — но только при условии, что на границах окна значения по-прежнему будут уходить в ноль. Например, при реверсировании одной из частей гладкость не нарушится:
Рассмотрим более подробно алгоритм для обработки сигнала с использованием быстрого преобразования Фурье (FFT):
При этом, если обработку спектра не производить, сигнал на выходе должен быть идентичен сигналу на входе (только с неизбежной задержкой во времени).
При использовании окна Ханна перекрытия в 50% уже недостаточно, так как будут возникать провалы:
Поскольку двойное наложение равносильно возведению в квадрат, то очевидным решением будет использовать корень из окна Ханна, чтобы компенсировать возведение в квадрат:
В этом случае, правда, окно перестало быть гладким на краях — появился разрыв в первой производной.
Можно пойти и другим путём — использовать перекрытие в 75%, и тогда окна также будут суммироваться в константу — только уже не в , а в :
В данном случае нам просто повезло. Если разложить квадрат на сумму — то можно увидеть, что оно представляет собой композицию из двух окон Ханна, но в разных масштабах, что и позволяет выполнять необходимые нам требования:
С другими оконными функциями такой фокус не пройдёт; также далеко не все стандартные оконные функции могут обеспечить суммирование в константу и при 50% перекрытии.
Можно рассматривать окно Ханна не как самостоятельную функцию, а как разницу двух кусочно-непрерывных функций (подробному рассмотрению которых была посвящена отдельная статья) со смещением. Например, используя следующую функцию
можно записать
Рассмотрев компоненты суммы двух таких окон, их способность суммироваться в константу станет более наглядным:
На отрезке мы получили взаимную компенсацию при сложении функций и , поскольку
Можно выбрать и другое смещение, с большим перекрытием, например:
И тогда, при смещении с шагом , они также будут суммироваться в константу:
Видно, что если перегруппировать компоненты оконной функции, то получатся всё те же окна Ханна.
Таким образом, используя разные функции ограничения, можно формировать окна необходимой формы.
Теперь осталось только задать масштаб, чтобы области определения и значения не зависели от величины перекрытия. Определив окно на интервале получим
где — кусочно-непрерывная функция вида
а — некоторая интерполирующая функция между точками и .
Параметр определяет уровень перекрытия — делитель, определяющий шаг, на который необходимо смещать каждое следующее окно, , и должен быть больше единицы, .
Процент перекрытия можно посчитать по формуле
и соответственно наоборот
Итоговый вид окна будет зависеть как от выбора уровня перекрытия, так и от выбора ограничивающей функции.
Здесь мы рассмотрим несколько готовых решений, ради которых всё и затевалось. Для простоты будем рассматривать просто интерполирующую функцию , без всякой прочей обвязки.
Являются наименее вычислительно затратными. Используя ранее выведенную формулу
получим полином с заданным количеством нулей на высших производных, обеспечивающих необходимую гладкость окна на краях.
С перекрытием в 75% окна с различными значениями n окна будут выглядеть так:
А в случае с извлечением корня — так (при использовании 75% перекрытия):
или так (при использовании 50% перекрытия):
Функция
интересна тем, что бесконечно дифференцируема и все её производные на краях равны 0 (что можно доказать, рассмотрев её производные исходя из правил дифференцирования — в каждом слагаемом будет обнуляющий его множитель). Это позволяет на её основе строить окна, все производных которых не имеют разрывов:
Необходимость такого вида окна вызвана тем, чтобы увеличить разрешение FFT, но снизить влияние эффекта «частотно-временной неопределённости» на высоких частотах за счёт увеличения их концентрации в центре.
Сначала определим желаемый вид оконной функции — например, следующим образом:
Здесь первое слагаемое определяет сам вид функции, второе — обеспечивает пересечение с осью абсцисс, третье (парабола) обнуляет производную на краях для гладкой стыковки; а параметр определяет «остроту» вершины. В таком виде она ещё не пригодна для использования — сначала из неё нужно получить функцию ограничения посредством интегрирования и масштабирования:
Для удобства настройки можно привязать параметр к уровню перекрытия — например, таким образом, чтобы 4-ая производная в центре окна была равна 0 — и тогда будет считаться как:
Здесь для наглядности все окна приведены к одному масштабу.
Представляет из себя более «агрессивный» вариант предыдущего окна. В качестве основы была выбрана гипербола, из которой путём последовательных трансформаций
и использования тех же шагов в виде интегрирования и масштабирования получили формулу
Здесь также можно привязать параметр к уровню перекрытия. Непосредственное решение уравнения 4-ой производной даёт слишком громоздкий результат, поэтому просто сделаем по образу и подобию из решения для предыдущего окна, определив как , обеспечив таким образом роль параметра как «тонкая настройка». При окна будут выглядеть следующим образом:
Оконная функция совсем не обязательно должна быть симметричной. Допустим, нам требуется окно с резкой атакой и плавным затуханием. Мы можем получить его по уже знакомой схеме — сначала определить желаемый вид функции, а затем интегрированием получить функцию ограничения. Здесь задача слегка усложняется за счёт того, что из-за асимметрии центр уже не будет проходить через начало координат, поэтому добавляется дополнительный шаг вычислений. Это также приводит к тому, что формулы в результате получаются довольно громоздкими. Для пример рассмотрим простейший вариант — параболу, умноженную на полиномиальное весовое окно:
Здесь степень при x в веcовом окне (а именно 10) определяет «резкость» атаки. Мы использовали конкретное значение, а не символьный параметр, чтобы упростить формулы для наглядности — при желании, в дальнейшем его можно пересчитать.
После интегрирования просто масштабирования уже недостаточно — нужно ещё выровнять края:
Для этого мы сначала сместим функцию наверх, чтобы выровнять левый край, а затем масштабируем к двойке по правому краю и вычтем единицу. После чего получим следующую формулу:
Для того, чтобы итоговое окно имело желаемый вид, нужно также обеспечить достаточное большой уровень перекрытия:
Аналогичным образом можно строить окна и из любых других колоколообразных функций — например, гауссианы; а также можно модифицировать уже рассмотренные для обеспечения большей гладкости или изменения формы кривой.
Вне рассмотрения остался спектральный состав таких оконных функций — этому нужно посвящать отдельные исследования.
Чуть более расширенный вариант статьи (с возможностью динамического изменения параметров в рассматриваемых окнах и скрытыми формулами) в виде документа Wolfram Mathematica можно скачать здесь.
Сам процесс разбиения математически представляется умножением на некоторую весовую (оконную) функцию со смещением. Для самого простого окна — прямоугольного — это может выглядеть так:
Исходный сигнал:
Разбиения:
Можно восстановить исходный сигнал, просто просуммировав их.
Подробнее
Однако по ряду причин прямоугольная функция — не самая лучшая оконная функция. При спектральном анализе через (обычно быстрое) дискретное преобразование Фурье анализируемый блок данных как бы «зацикливается», что приводит к разрыву на краях и искажению спектра:
Не является оно подходящим и для обратного синтеза — поскольку любое изменение также приведёт к разрывам — например, если мы попробуем реверсировать одну из частей:
Для устранения этих недостатков используется перекрытие — когда каждое следующее окно захватывает часть данных из предыдущего; а весовое окно, соответственно, плавно спадает к краям.
Перекрытие в 50%
Наиболее часто для этого используют окно Ханна (известное также под названием «приподнятый косинус») с перекрытием в 50%:
За счёт симметричности функции косинуса при сложении они суммируются в единицу:
Теперь при обратном синтезе мы не получим разрывов — но только при условии, что на границах окна значения по-прежнему будут уходить в ноль. Например, при реверсировании одной из частей гладкость не нарушится:
Обработка с двойным наложением окон
Рассмотрим более подробно алгоритм для обработки сигнала с использованием быстрого преобразования Фурье (FFT):
- разбиение сигнала на сегменты с наложением окна;
- прямое FFT;
- обработка спектра;
- обратное FFT;
- повторное наложение окна (поскольку после обратного FFT границы не обязательно будут стыковаться с нулём без разрыва);
- суммирование результирующих сегментов.
При этом, если обработку спектра не производить, сигнал на выходе должен быть идентичен сигналу на входе (только с неизбежной задержкой во времени).
При использовании окна Ханна перекрытия в 50% уже недостаточно, так как будут возникать провалы:
Поскольку двойное наложение равносильно возведению в квадрат, то очевидным решением будет использовать корень из окна Ханна, чтобы компенсировать возведение в квадрат:
В этом случае, правда, окно перестало быть гладким на краях — появился разрыв в первой производной.
Примечание
Интересно, что в данном случае у нас получилась половина периода синусоиды.
Можно пойти и другим путём — использовать перекрытие в 75%, и тогда окна также будут суммироваться в константу — только уже не в , а в :
В данном случае нам просто повезло. Если разложить квадрат на сумму — то можно увидеть, что оно представляет собой композицию из двух окон Ханна, но в разных масштабах, что и позволяет выполнять необходимые нам требования:
С другими оконными функциями такой фокус не пройдёт; также далеко не все стандартные оконные функции могут обеспечить суммирование в константу и при 50% перекрытии.
Идея
Можно рассматривать окно Ханна не как самостоятельную функцию, а как разницу двух кусочно-непрерывных функций (подробному рассмотрению которых была посвящена отдельная статья) со смещением. Например, используя следующую функцию
можно записать
Рассмотрев компоненты суммы двух таких окон, их способность суммироваться в константу станет более наглядным:
На отрезке мы получили взаимную компенсацию при сложении функций и , поскольку
Можно выбрать и другое смещение, с большим перекрытием, например:
И тогда, при смещении с шагом , они также будут суммироваться в константу:
Видно, что если перегруппировать компоненты оконной функции, то получатся всё те же окна Ханна.
Таким образом, используя разные функции ограничения, можно формировать окна необходимой формы.
Итоговая формула
Теперь осталось только задать масштаб, чтобы области определения и значения не зависели от величины перекрытия. Определив окно на интервале получим
где — кусочно-непрерывная функция вида
а — некоторая интерполирующая функция между точками и .
Параметр определяет уровень перекрытия — делитель, определяющий шаг, на который необходимо смещать каждое следующее окно, , и должен быть больше единицы, .
Процент перекрытия можно посчитать по формуле
и соответственно наоборот
Примечание
При работе с реальными данными может потребоваться пересчёт уровня перекрытия в зависимости от конкретного размера FFT. Например, при FFT на 2048 точек и уровнем перекрытия 3 получаем шаг 2048/3=682.666..., что на практике, естественно, нереализуемо. Поэтому округлим его до целого, а пересчитаем как 2048/683=2.998535871156662…
Либо же можно наоборот — использовать размер окна, заведомо делящийся на 3 (скажем, 999), а остаток до необходимого размера для FFT дополнить нулями (25-ю).
Либо же можно наоборот — использовать размер окна, заведомо делящийся на 3 (скажем, 999), а остаток до необходимого размера для FFT дополнить нулями (25-ю).
Итоговый вид окна будет зависеть как от выбора уровня перекрытия, так и от выбора ограничивающей функции.
Несколько интересных примеров
Здесь мы рассмотрим несколько готовых решений, ради которых всё и затевалось. Для простоты будем рассматривать просто интерполирующую функцию , без всякой прочей обвязки.
Полиномиальные окна
Являются наименее вычислительно затратными. Используя ранее выведенную формулу
получим полином с заданным количеством нулей на высших производных, обеспечивающих необходимую гладкость окна на краях.
первые 10 полиномов
С перекрытием в 75% окна с различными значениями n окна будут выглядеть так:
А в случае с извлечением корня — так (при использовании 75% перекрытия):
или так (при использовании 50% перекрытия):
Максимально гладкое окно
Функция
интересна тем, что бесконечно дифференцируема и все её производные на краях равны 0 (что можно доказать, рассмотрев её производные исходя из правил дифференцирования — в каждом слагаемом будет обнуляющий его множитель). Это позволяет на её основе строить окна, все производных которых не имеют разрывов:
Окно вида «юбочка»
Необходимость такого вида окна вызвана тем, чтобы увеличить разрешение FFT, но снизить влияние эффекта «частотно-временной неопределённости» на высоких частотах за счёт увеличения их концентрации в центре.
Сначала определим желаемый вид оконной функции — например, следующим образом:
Здесь первое слагаемое определяет сам вид функции, второе — обеспечивает пересечение с осью абсцисс, третье (парабола) обнуляет производную на краях для гладкой стыковки; а параметр определяет «остроту» вершины. В таком виде она ещё не пригодна для использования — сначала из неё нужно получить функцию ограничения посредством интегрирования и масштабирования:
Для удобства настройки можно привязать параметр к уровню перекрытия — например, таким образом, чтобы 4-ая производная в центре окна была равна 0 — и тогда будет считаться как:
Здесь для наглядности все окна приведены к одному масштабу.
Окно вида «иголка»
Представляет из себя более «агрессивный» вариант предыдущего окна. В качестве основы была выбрана гипербола, из которой путём последовательных трансформаций
и использования тех же шагов в виде интегрирования и масштабирования получили формулу
Здесь также можно привязать параметр к уровню перекрытия. Непосредственное решение уравнения 4-ой производной даёт слишком громоздкий результат, поэтому просто сделаем по образу и подобию из решения для предыдущего окна, определив как , обеспечив таким образом роль параметра как «тонкая настройка». При окна будут выглядеть следующим образом:
Асимметричное окно
Оконная функция совсем не обязательно должна быть симметричной. Допустим, нам требуется окно с резкой атакой и плавным затуханием. Мы можем получить его по уже знакомой схеме — сначала определить желаемый вид функции, а затем интегрированием получить функцию ограничения. Здесь задача слегка усложняется за счёт того, что из-за асимметрии центр уже не будет проходить через начало координат, поэтому добавляется дополнительный шаг вычислений. Это также приводит к тому, что формулы в результате получаются довольно громоздкими. Для пример рассмотрим простейший вариант — параболу, умноженную на полиномиальное весовое окно:
Здесь степень при x в веcовом окне (а именно 10) определяет «резкость» атаки. Мы использовали конкретное значение, а не символьный параметр, чтобы упростить формулы для наглядности — при желании, в дальнейшем его можно пересчитать.
После интегрирования просто масштабирования уже недостаточно — нужно ещё выровнять края:
Для этого мы сначала сместим функцию наверх, чтобы выровнять левый край, а затем масштабируем к двойке по правому краю и вычтем единицу. После чего получим следующую формулу:
Для того, чтобы итоговое окно имело желаемый вид, нужно также обеспечить достаточное большой уровень перекрытия:
Заключение
Аналогичным образом можно строить окна и из любых других колоколообразных функций — например, гауссианы; а также можно модифицировать уже рассмотренные для обеспечения большей гладкости или изменения формы кривой.
Вне рассмотрения остался спектральный состав таких оконных функций — этому нужно посвящать отдельные исследования.
Чуть более расширенный вариант статьи (с возможностью динамического изменения параметров в рассматриваемых окнах и скрытыми формулами) в виде документа Wolfram Mathematica можно скачать здесь.
Комментарии (12)
maybe_im_a_leo
23.11.2018 22:19Спасибо, интересная статья. Взял на заметку.
А в чем вы рисовали графики?Refridgerator Автор
24.11.2018 15:17Не только графики, но и все вычисления сделаны в Wolfram Mathematica, в конце статьи есть ссылка на исходник. Код для графиков там скрыт по умолчанию, для открытия нужно выделить ячейку серым цветом над графиком и в меню Cell->Cell Properties->Open поставить галочку.
ser-mk
23.11.2018 23:27За счёт симметричности функции косинуса при сложении они суммируются в единицу:
А какое сложение используется?
Или имеется ввиду, что будет единица от первого «бугра» до последнего?
Sabubu
Статья интересная — но, вот, мне кажется, пояснений немножечко не хватает. Вы пишете с расчетом на читателя, который прекрасно разбирается в оконных функциях, а наверно, стоило бы немного пояснить подробнее, зачем они нужны, для тех, кто не занимается ежедневно обработкой сигналов и просто заглянул из любопытства. А у вас лишь краткое понятное не всем предложение:
> При спектральном анализе через (обычно быстрое) дискретное преобразование Фурье анализируемый блок данных как бы «зацикливается», что приводит к разрыву на краях и искажению спектра:
Ну и стоило бы во вступлении объяснить, где это вообще применяется и зачем. Как я понимаю — при какой-то цифровой обработке сигналов, либо для добавления эффектов к звуковому сигналу, либо может быть для обработки радиосигнала.
И интересно, где вообще нужны нестандартные оконные функции, особенно несимметричной формы?
И еще интересно, а почему оконные функции не делают в виде скругленного с краев прямоугольного импульса, чтобы почти вся она равнялась единице и вносила минимум искажений в сигнал? А то ваши оконные функции похожи на горки и сигнал без изменений остается только в серединке.
И еще вопрос, может вы знаете ответ, раз уж занимаетесь обработкой сигналов. Если есть сигнал неизвестного вида, который может содержать частоту X + шумы и щелчки, и мы хотели бы получить на выходе амплитуду этой частоты X в сигнале, то есть увидеть, где она есть, где ее нет, где ее больше — есть какой-то готовый простой алгоритм, без вычисления FFT? Какой-то простой фильтр, может быть? Нужно для определения задержки прохождения сигнала через звуковую карту и ее драйвера.
Refridgerator Автор
Потому что умножение сигнала на оконную функцию равносильно свёртке их спектров, и чем больше окно «квадратное», тем выше уровень боковых лепестков после FFT, что затрудняет спектральный анализ.
Процент перекрытия может быть и меньше 50%. Я не стал заострять на этом внимание, потому что это казалось очевидным (каюсь):
Refridgerator Автор
Sabubu
Ну, это слишком просто и неинтересно. У нас могут быть посторонние шумы и искажения, так как вход и выход не соединены кабелем, а акустической связью через динамики/наушники и микрофон с неизвестными характеристиками.
Nokta_strigo
А чем FFT не устраивает? Медленно считается? Если нужна только одна частота (т.е. одна точка на дискретном спектре), то можно считать дискретное преобразование Фурье для одной частоты. Сложность FFT — O(n * log (n)), а расчёта одной точки спектра «в лоб» — O(n), т.е. для очень узких фильтров (при больших n) будет в несколько раз быстрей.
Но учтите, что чем точней вам надо получить частоту, тем более длинную реализацию сигнала (окно) надо брать. Это принципиальное ограничение, не важно используете FFT (хотя ресурсов на расчёт FFT тоже надо больше), «железные» фильтры или ещё что.
Так что узкополосный сигнал может быть не самым удачным выбором, если надо измерять время. Как написал Refridgerator, лучше мощный импульсный сигнал или какой-то более сложный с широким спектром (ЛЧМ или ещё что).
Refridgerator Автор
Refridgerator Автор
Например, с их помощью я делал генератор шума дождя — из записи дождя ограниченной продолжительности извлекал небольшие куски со случайным смещением и соединял их заново (в 4-х каналах), чтобы не слушать бесконечно одно и то же и получить объёмный звук. Это позволяло также настраивать «плотность» звука, смешивая в разных пропорциях разные части записи.
interrupt
По поводу определения неизвестной частоты в сигнале, возможно Generalized Harmonic Analysis то что вы ищете, например статья «Fast and Accurate Generalized Harmonic Analysis Using Newton’s Method». Ну и пользуясь случаем порекламирую библиотечку, которую как раз начал писать по этой статье, libgha
Идея там такая, сначала через FFT грубо ищем максимум, потом используя метод Ньютона уточняем частоту и фазу.
Работает это в предположении что в сигнале нет двух синусоид частоты которых расположены ближе частотного разрешения FFT с заданным окном.
blackghost56
Посмотрите алгоритм Гёрцеля