Убираем сетевую наводку 50 Гц из ЭКГ
Решаем классическую медицинскую задачу: чистим кардиограмму от помехи электросети.
Сетевая наводка — паразитный сигнал частотой 50 Гц (в РФ и Европе; 60 Гц в США/Японии), наводимый проводкой на чувствительные датчики вроде электродов ЭКГ.
Это, возможно, самая частая практическая задача DSP в медицине и измерениях. Электроды ЭКГ снимают милливольты, а вокруг — провода под напряжением 220 В, 50 Гц. Наводка «подмешивается» в сигнал и мешает врачу видеть зубцы кардиограммы. Полезный сигнал сердца — это в основном частоты до ~40 Гц, а помеха — ровно 50 Гц. Их можно разделить фильтром.
Видим проблему
Смоделируем ЭКГ как медленный полезный тон 2 Гц плюс сильную наводку 50 Гц. Сравним сигнал с эталоном (чистым 2 Гц) по RMS-отклонению.
import math
fs, N = 200.0, 200
ecg = [math.sin(2 * math.pi * 2 * n / fs) + 0.7 * math.sin(2 * math.pi * 50 * n / fs)
for n in range(N)]
clean = [math.sin(2 * math.pi * 2 * n / fs) for n in range(N)]
def rms(a, b):
return round(math.sqrt(sum((x - y) ** 2 for x, y in zip(a, b)) / len(a)), 3)
print("RMS наводки в сыром сигнале:", rms(ecg, clean))
Вывод:
RMS наводки в сыром сигнале: 0.495
Отклонение 0.495 — наводка сравнима по силе с полезным сигналом. Без фильтрации зубцы ЭКГ тонут в «сетевой ряби».
Трюк: скользящее среднее, гасящее ровно 50 Гц
Есть элегантное решение. Скользящее среднее длиной L отсчётов имеет в АЧХ нули на частотах fs/L, 2*fs/L, .... Если выбрать L = fs/50, один из нулей попадёт ровно на 50 Гц — и наводка исчезнет. При fs = 200 нужно L = 200/50 = 4.
import math
fs, N = 200.0, 200
ecg = [math.sin(2 * math.pi * 2 * n / fs) + 0.7 * math.sin(2 * math.pi * 50 * n / fs)
for n in range(N)]
clean = [math.sin(2 * math.pi * 2 * n / fs) for n in range(N)]
def convolve_same(x, h):
M = len(h); pad = M // 2; out = []
for i in range(len(x)):
s = 0.0
for j in range(M):
idx = i - pad + j
if 0 <= idx < len(x):
s += x[idx] * h[j]
out.append(s)
return out
def rms(a, b):
return round(math.sqrt(sum((x - y) ** 2 for x, y in zip(a, b)) / len(a)), 3)
L = int(fs / 50) # = 4: нуль АЧХ ровно на 50 Гц
ma = [1 / L] * L
filtered = convolve_same(ecg, ma)
print("Длина фильтра L =", L)
print("RMS наводки после фильтра:", rms(filtered, clean))
Вывод:
Длина фильтра L = 4 RMS наводки после фильтра: 0.028
Наводка упала с 0.495 до 0.028 — почти в 18 раз. Простое 4-точечное среднее, настроенное на нуль 50 Гц, вычистило помеху, почти не задев полезный сигнал 2 Гц. Кардиограмма читается.
Почему это работает
АЧХ скользящего среднего длины L — это функция вида |sin(pi*f*L/fs) / (L*sin(pi*f/fs))|. Её нули — там, где числитель равен нулю, то есть на частотах, кратных fs/L. При L=4 и fs=200 нули стоят на 50, 100, 150 Гц. Наша помеха 50 Гц попадает точно в первый нуль и подавляется почти полностью. А полезные 2 Гц лежат далеко в полосе пропускания и проходят. Это дешёвый аналог режекторного (notch) фильтра, идеально подходящий, когда мешающая частота кратна fs/L.
Как работает под капотом
В реальной аппаратуре ЭКГ применяют специальный notch-фильтр: IIR второго порядка с парой нулей точно на 50 Гц и парой полюсов чуть внутри окружности рядом с ними. Полюса делают провал АЧХ узким, чтобы вырезать только 50 Гц, не трогая соседние полезные частоты (наш MA-трюк вырезает шире). Иногда вместо фильтра используют адаптивное вычитание: берут опорный сигнал сети, подстраивают его амплитуду и фазу и вычитают из ЭКГ — так убирают наводку, вообще не трогая спектр сигнала. Выбор метода зависит от того, насколько стабильна частота сети и важны ли частоты возле 50 Гц.
Частые ошибки
- Резать слишком широко. Грубый фильтр уберёт вместе с 50 Гц и полезные близкие частоты (для ЭКГ это детали зубцов).
- Перепутать 50 и 60 Гц. В США сеть 60 Гц; фильтр под 50 Гц там не сработает.
- Фильтровать вместо экранирования. Лучше сначала уменьшить наводку аппаратно (экран, заземление), а фильтром добивать остаток.
Итог
- Сетевая наводка — паразитный тон 50 Гц (60 в США) на чувствительных датчиках.
- Скользящее среднее длины
L = fs/50имеет нуль АЧХ ровно на 50 Гц. - Такой фильтр дёшево гасит помеху, почти не трогая полезный низкочастотный сигнал.
- В аппаратуре применяют узкий notch-фильтр или адаптивное вычитание сети.