Під час згортання сигналу, чому нам потрібно перевертати імпульсну відповідь під час процесу?
Під час згортання сигналу, чому нам потрібно перевертати імпульсну відповідь під час процесу?
Відповіді:
Адаптований з відповіді на інше запитання (про що згадується в коментарі), сподіваючись, що це питання не буде піддаватися повторній роботі спільнотою Wiki як одне з головних питань ....
Не відбувається "перегортання" імпульсної відповіді лінійною (інваріантною за часом) системою. Вихід лінійної інваріантної системи часу - це сума масштабованих і затримок у часі версій імпульсної відповіді, а не "перевернутого" імпульсного відгуку.
Розбиваємо вхідний сигнал на суму масштабованих одиничних імпульсних сигналів. Відповідь системи на одиничний імпульсний сигнал - імпульсна характеристика або імпульсна характеристика
Аналогічно, значення одного входу або створює x [ 1 ] ( ⋯ , 0 , 0 , 0 , 1 , 0 , ⋯ ) = ⋯ 0 , 0 , 0 , x [ 1 ] , 0 , ⋯ створює відповідь 0 , х [ 1 ] год [ 0 ] , х [ 1
Який вихід у момент ?
Ось приклад C / C ++, який показує, що згортання можна зробити без використання імпульсної відповіді у зворотному напрямку. Якщо ви перевіряєте convolve_scatter()
функцію, жодна змінна не заперечується ніде. Це згортання розсіювання, коли кожен вхідний зразок розсіюється (підсумовується) на декілька вихідних зразків у пам'яті, використовуючи ваги, задані імпульсним відгуком. Це марно, оскільки вихідні зразки потрібно буде прочитати та записати кілька разів.
Зазвичай згортання здійснюється як збір згортки, як у convolve_gather()
. У цьому способі кожен вихідний зразок формується окремо, шляхом збору (підсумовування) до нього вхідних зразків, із зворотним імпульсним відгуком як вагами. Зразок виводу знаходиться в регістрі процесора, який використовується як акумулятор, поки це робиться. Зазвичай це метод вибору, тому що буде записано лише одну пам'ять на кожен відфільтрований зразок. Зараз існує більше зчитування пам'яті на вході, але лише стільки, скільки було зчитування пам'яті виводу в методі розсіювання.
#include <stdio.h>
const int Nx = 5;
const int x[Nx] = {1, 0, 0, 0, 2};
const int Ny = 3;
const int y[Ny] = {1, 2, 3};
const int Nz = Nx+Ny-1;
int z[Nz];
void convolve_scatter() { // z = x conv y
for (int k = 0; k < Nz; k++) {
z[k] = 0;
}
for (int n = 0; n < Nx; n++) {
for (int m = 0; m < Ny; m++) {
z[n+m] += x[n]*y[m]; // No IR reversal
}
}
}
void convolve_gather() { // z = x conv y
for (int k = 0; k < Nz; k++) {
int accu = 0;
for (int m = 0; m < Ny; m++) {
int n = k+m - Ny + 1;
if (n >= 0 && n < Nx) {
accu += x[n]*y[Ny-m-1]; // IR reversed here
}
}
z[k] = accu;
}
}
void print() {
for (int k = 0; k < Nz; k++) {
printf("%d ", z[k]);
}
printf("\n");
}
int main() {
convolve_scatter();
print();
convolve_gather();
print();
}
Він складається з послідовностей:
1 0 0 0 2
1 2 3
і використовуючи обидва виходи методу згортки:
1 2 3 0 2 4 6
Я не уявляю нікого, хто використовує метод розсіювання, якщо фільтр не відрізняється за часом, і тоді два способи дадуть різні результати, і один може бути більш підходящим.
Це лише "перевернуте" для точкового обчислення.
@Dilip пояснює, що являє собою інтеграл / підсумовування згортки, але для пояснення того, чому одна з двох вхідних функцій (часто h(t)
) перевернута для цілей обчислення, розглянемо дискретно-часову систему з вхідним x[n]
та імпульсним відгуком h[n]
:
Ви можете взяти свою функцію введення x[n]
і для кожного ненульового * зразка x[n]
обчислити масштабовану імпульсну відповідь від вибірки n
і далі, поки зміщений час не h[n]
знизиться до нуля (припускаючи причину h[n]
). Це передбачає відсутність "перегортання" (або точніше "зміни часу" жодного x[n]
або h[n]
. Однак наприкінці вам доведеться додати / накласти всі ці масштабовані + зміщені 'відлуння' імпульсної відповіді для кожного ненульового x[n]
.
x[0]
k
h[n]
x[n]
, який є x[0]h[0]
. Потім приріст k
на один зміститься h[n]
вправо на один крок часу, таким чином, що h[n]
другий запис ( h[1]
), повернутий за часом ( ) тепер буде лежати на вершині x[0]
, чекаючи його множення. Це дасть бажаний внесок x[0]h[1]
у часі так n=1
само, як це було б зроблено в попередньому методі.x[n]
h[n]
y[n]
В індексі c [n] згортка [n] і b [n] така, що:
"c [n] - це підсумок всіх добутків (a [k] b [m]) таким, що m + k = n", тому m = n - k або k = n - m, що означає, що одна з послідовностей доводиться перевертати.
Тепер, чому згортання поводиться саме так? Через його зв’язок з множеннями многочленів.
Помноження двох многочленів призводить до появи нового многочлена з коефіцієнтами. Коефіцієнти многочлена продукту визначають операцію згортки. Тепер, в обробці сигналів, функції передачі - перетворення Лапласа або z-перетворення - це поліноми, кожен з коефіцієнтів яких відповідає різній затримці в часі. Відповідність коефіцієнтів продукту та множників призводить до того, що "множення в одному представленні відповідає згортці в перетвореному поданні".
Під час згортання взагалі не повинно відбуватися "перевертання" імпульсної реакції ...
Однак, якщо ви хочете запобігти будь-якій зміні фази, ви можете скласти сигнал з імпульсною відповіддю, а потім повернути імпульсну відповідь і повторно скрутити для скасування фазових ефектів.
У режимі офлайн-обробки ви можете так само легко повернути сигнал після першого згортання, щоб дійти до того самого висновку (як підказують коментарі).
Тепер форма ручного розмахування чітко показує симетрію, яка тут задіяна, і жодне "перегортання" не пов'язане. Перетворення цього в належний одновимірний інтеграл вимагає зробити один з двох аргументів фактичною змінною інтеграції. Це або пошук жорсткої симетричної форми, що не передбачає рукоділля. Останнє хитріше. В основному, вам потрібно повернути нормалізацію, створивши щось (при використанні функції / розподілу дельти Дірака), наприклад Якщо потім переставити в один бік, ви отримаєте і від властивості просіювання оператора Dirac ∫ t 1 f ( t 1 )