Как получить огибающую сигнала через преобразование Гильберта?
Так сложилось что к данной области я практически никак не отношусь, но надо, надо как можно точнее получить из сигнала записанного по отсчетам огибающую кривую. Погуглив на эту тему я понял что вроде бы все используют для этих целей преобразование Гилберта и формулу t_i = ((sig_i)^2+(csig_i)^2)^(0.5), где i это отсчет, а t_i это y координата огибающей кривой для i отсчета, sig_i соответственно исходное значение сигнала в отсчете, а csig_i это значение функции сопряженной по Гилберту для этого отсчета. Собственно вопрос, в том ли направлении я иду, как посчитать эту самую сопряженную функцию имея только массив с отсчетами, чтобы правильно вычислить огибающую кривую?
В кратце, желательно, чтобы в массиве дискретизации было целое количество периодов входного сигнала, иначе необходимо накладывать окно, с целью минимизации краевых эффектов. Далее сделать преобразование Гильберта, найти ортогональный сигнал, после чего найти огибающую: A[iTд]=sqrt(Uг[iТд]^2+Uф[[iТд]^2), где Uг[iТд] ортогональный сигнал, а Uф[[iТд]- ваш исходный.
Так вот собственно в том и вопрос - как вычислить этот ортогональный сигнал? Аналитическое решение я находил, но я довольно давно в последний раз занимался подобной математикой и до меня не очень доходит, как мне прийти от исходного массива отсчетов к массиву значений для ортогонального сигнала.
Whiteha: Ортогональный сигнал можете вычислить через БПФ. Берете БПФ от исходного сигнала, далее в цикле от 0 до N/2-1 Re(i)=Im(i), Im(i)=-Re(i), в цикле от N/2 до N-1 Re(i)=-Im(i), Im(i)=Re(i) (формулы по памяти, по хорошему их бы уточнить). Далее ОБПФ и вот он ортогональный сигнал.
rediskus пока не выходит, конечно вероятно что я еще не все отдебажил, но если есть возможность уточнить формулу для расчета, то буду признателен.
PS Я нашел такую вещь, но к сожалению без очень долгого вспоминания матана я точно ее сам не осилю www.dsplib.ru/content/hilbert/hilbert.html
Whiteha: Зачем так глубоко копать? :) Если вам нужно FFT, возьмите готовую библиотеку допустим тут www.fftw.org Я раньше использовал Intel Math Kernel Library. Формулы я дал правильные. Если FFT у вас уже есть, работает ли оно? Проверяли ли вы его на простых входных данных? Допустим 256 дискрет синусоида с 5 периодами, получается ли правильный спектр? Если вы уверены в правильности кода, учтите, что для FFT важно количество входных отсчетов, так-же важно чтобы в это количество укладывалось ровное число периодов входного сигнала (иначе придется использовать оконные функции, чтобы убрать краевые эффекты и т.д.) Может стоит перейти на примеры кода?
Просто тащить целую библиотеку ради одного БПФ на эмбедед с ограниченными ресурсами не очень хорошая идея, поэтому я делаю велосипед.( Моя реализация БПФ работала, я проверял ее на алгоритме умножения двух длинных чисел, но если формулы верны, значит у меня где-то всплыл баг. Я бы и использовал fftw хотя бы для проверки, но документация там какая-то мудреная, за пять минут ее изучения я так и не нашел как вызвать БПФ, хотя мб это доки из Qt меня избаловали.
Да на мк тяжеловато либу тащить. И все же проверьте результат работы визуально :) Вот как то так, накидал на Delphi (i72.fastpic.ru/big/2015/0601/21/f2c03a5a8dce2d1e9a...). График сверху, синусоида, 5 периодов, 1024 точки дискретизации, в центре спектр(реальная часть), видно палку на цифре 5, вывод-БПФ работает. Картинка снизу "ортогональный" сигнал, после ОБПФ и формул, что я давал выше. Визуально сразу можно будет увидеть ошибку.
Проверяю на синусоиде, но на выходе какой-то хлам, при том что этот же БПФ работает в алгоритме для умножения больших чисел. =0
Закрадывается подозрение что я категорически что-то не так делаю.
Как я делаю:
1) Сохраняю массив отсчетов как действительную часть в векторе комплексных чисел (std::vector> sig), при этом комплексную составляющую везде оставляю нулевой
2) Отправляю sig вектор на БПФ
3) Затем к результату записанному в sig применяю от 0 до N/2 - 1 Re(i)=Im(i), Im(i)=-Re(i), затем от N/2 до N - 1 Re(i)=-Im(i), Im(i)=Re(i)
4) Отправляю sig на ОБПФ
5) В результате ожидаю получить аналитический сигнал, в котором вещественная часть это мой исходный сигнал, а комплексная - ортогональный. Однако ни вещественная часть, ни комплексная вообще ни на что не похожы и рисуют причудливые формы.
Если так и надо делать, значит проблема в моем БПФ, если не так, значит тройки по матану меня сгубили.
Whiteha: БПФ от ПФ отличается не только буквой Б :) В частности БПФ очень чувствительно к входным данным. Если вы смотрели мой рисунок, верхний график-косинусоида. Скорее всего у вас проявились краевые эффекты, бороться с которыми необходимо оконными функциями. Для проверки вашего БПФ, выполните пункты 1 и 2 и посмотрите на реальную часть спектра. В случае синуса(косинуса) там должна быть одна "палка" на отсчете, равном количеству целых периодов, укладывающихся в ваше окно дискретизации. Т.е. если периодов допустим 7, палка на цифре 7. Далее я писал, что само окно дискретизации (кол-во точек) должно быть степенью 2(256,512,1024 и т.д.). Если пункты 1 и 2 выполняются верно, остальное уже банальный линейный код не стоящий обсуждения.