ローパスフィルタの設計と比較:移動平均・バターワース・チェビシェフ

移動平均フィルタ、バターワースフィルタ、チェビシェフフィルタの3種のローパスフィルタをPythonで設計し、周波数応答・群遅延・ステップ応答を比較します。

はじめに

ローパスフィルタ(Low-Pass Filter; LPF)は、信号処理において最も基本的かつ重要なフィルタです。カットオフ周波数以下の低周波成分を通過させ、高周波ノイズを除去する役割を持ちます。

本記事では、代表的な3種類のローパスフィルタを取り上げます。

  1. 移動平均フィルタ(FIR型):最も単純な構造で線形位相を持つ
  2. バターワースフィルタ(IIR型):通過域で最大限に平坦な振幅特性を持つ
  3. チェビシェフI型フィルタ(IIR型):通過域にリプルを許容する代わりに急峻な遷移帯域を実現する

それぞれの理論的背景を示したうえで、Pythonによる設計と特性比較を行います。

移動平均フィルタ(Moving Average Filter)

移動平均フィルタは、直近 \(N\) 個のサンプルの算術平均を出力するFIRフィルタです。

伝達関数

入力信号 \(x[n]\) に対して、出力は次のように定義されます。

\[y[n] = \frac{1}{N}\sum_{k=0}^{N-1} x[n-k] \tag{1}\]

Z変換を適用すると、伝達関数は次のようになります。

\[H(z) = \frac{1}{N}\sum_{k=0}^{N-1} z^{-k} = \frac{1}{N} \cdot \frac{1 - z^{-N}}{1 - z^{-1}} \tag{2}\]

周波数応答

\(z = e^{j\omega}\) を代入すると、周波数応答が得られます。

\[H(e^{j\omega}) = \frac{1}{N} \cdot \frac{1 - e^{-jN\omega}}{1 - e^{-j\omega}} = \frac{1}{N} \cdot \frac{\sin(N\omega/2)}{\sin(\omega/2)} \cdot e^{-j(N-1)\omega/2} \tag{3}\]

振幅特性は \(\frac{1}{N}\left|\frac{\sin(N\omega/2)}{\sin(\omega/2)}\right|\) であり、sinc関数に似た形状を示します。この特性により、移動平均フィルタは阻止域での減衰が緩やかで、周波数選択性は高くありません。一方、位相特性は \(-(N-1)\omega/2\) であり、完全な線形位相を持つという大きな利点があります。

バターワースフィルタ(Butterworth Filter)

バターワースフィルタは、通過域において最も平坦な振幅特性(最大平坦特性)を持つIIRフィルタです。

振幅特性

\(N\) 次バターワースフィルタの振幅の2乗特性は次のように定義されます。

\[|H(j\omega)|^2 = \frac{1}{1 + \left(\frac{\omega}{\omega_c}\right)^{2N}} \tag{4}\]

ここで、\(\omega_c\) はカットオフ周波数、\(N\) はフィルタの次数です。

この式から、以下の性質がわかります。

  • \(\omega = 0\) のとき \(|H| = 1\)(DCゲインは1)
  • \(\omega = \omega_c\) のとき \(|H| = 1/\sqrt{2}\)(\(-3\) dB)
  • 次数 \(N\) が大きいほど遷移帯域が急峻になる

バターワースフィルタは通過域・阻止域ともにリプルがなく、滑らかな特性を持つため、汎用的なフィルタとして広く使われています。

設計

Pythonでは scipy.signal.butter を使って設計できます。

from scipy.signal import butter
b, a = butter(N=4, Wn=0.3)  # 4次、正規化カットオフ0.3

チェビシェフI型フィルタ(Chebyshev Type I Filter)

チェビシェフI型フィルタは、通過域にチェビシェフ多項式に基づく等リプル特性を持つIIRフィルタです。

振幅特性

\(N\) 次チェビシェフI型フィルタの振幅の2乗特性は次のとおりです。

\[|H(j\omega)|^2 = \frac{1}{1 + \varepsilon^2 T_N^2\left(\frac{\omega}{\omega_c}\right)} \tag{5}\]

ここで、\(\varepsilon\) はリプルの大きさを制御するパラメータ、\(T_N\) は \(N\) 次チェビシェフ多項式です。チェビシェフ多項式は次の漸化式で定義されます。

\[T_0(x) = 1, \quad T_1(x) = x, \quad T_{n+1}(x) = 2xT_n(x) - T_{n-1}(x) \tag{6}\]

通過域(\(\omega \le \omega_c\))では \(T_N\) が \([-1, 1]\) の範囲で振動するため、振幅にリプルが生じます。その代わり、同じ次数のバターワースフィルタと比較して遷移帯域がより急峻になるという利点があります。

設計

Pythonでは scipy.signal.cheby1 を使って設計できます。rp パラメータで通過域リプルをdB単位で指定します。

from scipy.signal import cheby1
b, a = cheby1(N=4, rp=1, Wn=0.3)  # 4次、リプル1dB、正規化カットオフ0.3

Pythonによる比較

以下のコードでは、3種類のフィルタを同一条件で設計し、周波数応答・群遅延・ステップ応答を比較します。

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import (
    butter, cheby1, freqz, group_delay, dstep, dlti
)

# --- フィルタ設計 ---
N_ORDER = 4        # フィルタ次数
WN = 0.3           # 正規化カットオフ周波数 (ナイキスト周波数に対する比)
N_MA = 13           # 移動平均のタップ数 (奇数を推奨)
RP = 1.0            # チェビシェフI型の通過域リプル [dB]

# 移動平均フィルタ
b_ma = np.ones(N_MA) / N_MA
a_ma = [1.0]

# バターワースフィルタ
b_bw, a_bw = butter(N_ORDER, WN)

# チェビシェフI型フィルタ
b_cb, a_cb = cheby1(N_ORDER, RP, WN)

filters = [
    ("Moving Average (N=13)", b_ma, a_ma),
    ("Butterworth (N=4)", b_bw, a_bw),
    ("Chebyshev I (N=4, rp=1dB)", b_cb, a_cb),
]

# --- 1. 周波数応答 ---
fig, ax = plt.subplots(figsize=(8, 5))
for label, b, a in filters:
    w, h = freqz(b, a, worN=2048)
    freq = w / np.pi  # 正規化周波数
    mag_db = 20 * np.log10(np.abs(h) + 1e-12)
    ax.plot(freq, mag_db, label=label)

ax.set_xlabel("Normalized Frequency (×π rad/sample)")
ax.set_ylabel("Magnitude (dB)")
ax.set_title("Frequency Response Comparison")
ax.set_xlim(0, 1)
ax.set_ylim(-60, 5)
ax.axvline(WN, color="gray", linestyle="--", alpha=0.5, label=f"Cutoff = {WN}")
ax.legend()
ax.grid(True)
plt.tight_layout()
plt.show()

# --- 2. 群遅延 ---
fig, ax = plt.subplots(figsize=(8, 5))
for label, b, a in filters:
    w, gd = group_delay((b, a), w=2048)
    freq = w / np.pi
    ax.plot(freq, gd, label=label)

ax.set_xlabel("Normalized Frequency (×π rad/sample)")
ax.set_ylabel("Group Delay (samples)")
ax.set_title("Group Delay Comparison")
ax.set_xlim(0, 1)
ax.legend()
ax.grid(True)
plt.tight_layout()
plt.show()

# --- 3. ステップ応答 ---
fig, ax = plt.subplots(figsize=(8, 5))
n_steps = 60
for label, b, a in filters:
    system = dlti(b, a, dt=1)
    t, y = dstep(system, n=n_steps)
    ax.step(t[0].flatten(), y[0].flatten(), label=label, where="post")

ax.set_xlabel("Sample")
ax.set_ylabel("Amplitude")
ax.set_title("Step Response Comparison")
ax.axhline(1.0, color="gray", linestyle="--", alpha=0.5)
ax.legend()
ax.grid(True)
plt.tight_layout()
plt.show()

周波数応答の比較

群遅延の比較

ステップ応答の比較

周波数応答の読み取り

  • 移動平均フィルタは阻止域の減衰が浅く、ヌル(零点)の位置以外では高周波が漏れやすい
  • バターワースフィルタは通過域が平坦で、遷移帯域も比較的滑らか
  • チェビシェフI型フィルタは通過域にリプルがある代わりに、遷移帯域が最も急峻

群遅延の読み取り

  • 移動平均フィルタは線形位相のため群遅延が全周波数で一定(\((N-1)/2\) サンプル)
  • バターワースフィルタチェビシェフI型フィルタはカットオフ周波数付近で群遅延が増大し、非線形位相となる

ステップ応答の読み取り

  • 移動平均フィルタはオーバーシュートなしに定常値へ到達する
  • バターワースフィルタはわずかなオーバーシュートの後に収束する
  • チェビシェフI型フィルタはリプルの影響で最もオーバーシュートが大きい

フィルタ選択ガイド

特性移動平均バターワースチェビシェフI型
通過域平坦最大平坦等リプル
遷移帯域緩やか中程度急峻
阻止域減衰浅い中程度深い
位相特性線形非線形非線形
群遅延一定周波数依存周波数依存
計算コスト低い中程度中程度
主な用途ノイズ平滑化汎用フィルタリング急峻な遮断が必要な場合

用途に応じた選び方の目安は次のとおりです。

  • 位相歪みを避けたい場合(波形の形状が重要)→ 移動平均フィルタ
  • 通過域の平坦性が重要な場合(計測信号の忠実な再現)→ バターワースフィルタ
  • 遷移帯域をできるだけ狭くしたい場合(隣接する周波数成分の分離)→ チェビシェフI型フィルタ

まとめ

本記事では、移動平均フィルタ、バターワースフィルタ、チェビシェフI型フィルタの3種のローパスフィルタについて、理論的背景と設計方法を示し、Pythonで周波数応答・群遅延・ステップ応答を比較しました。

各フィルタにはそれぞれ長所と短所があり、アプリケーションの要件に応じて適切なフィルタを選択することが重要です。また、EMAフィルタ(1次IIRフィルタ)との関連については指数移動平均(EMA)フィルタの周波数特性も併せてご参照ください。状態空間モデルに基づくフィルタリング手法(カルマンフィルタ、拡張カルマンフィルタ、UKF、粒子フィルタ)については信号処理におけるフィルタリング手法の基礎で体系的に解説しています。

参考