はじめに
チェビシェフフィルタは、通過域(I型)または阻止域(II型)に等リップルを許容することで、同次数のバターワースフィルタよりも急峻な遷移帯域を実現するIIRフィルタです。
バターワースフィルタが通過域で最大限に平坦な特性を持つのに対し、チェビシェフフィルタはその平坦性を犠牲にして遷移の鋭さを優先します。本記事ではI型とII型それぞれの数学的基礎から、SciPyを使った実践的な設計・実装までを解説します。
チェビシェフ多項式
チェビシェフフィルタの周波数特性は、チェビシェフ多項式 \(T_N(x)\) に基づいています。
\[T_N(x) = \begin{cases} \cos(N \arccos x) & |x| \leq 1 \\ \cosh(N \operatorname{arccosh} x) & |x| > 1 \end{cases} \tag{1}\]低次のチェビシェフ多項式は次のとおりです。
| 次数 \(N\) | \(T_N(x)\) |
|---|---|
| 0 | \(1\) |
| 1 | \(x\) |
| 2 | \(2x^2 - 1\) |
| 3 | \(4x^3 - 3x\) |
| 4 | \(8x^4 - 8x^2 + 1\) |
\(|x| \leq 1\) の範囲でチェビシェフ多項式は \(-1\) から \(+1\) の間を等振幅で振動する性質があり、これがフィルタに等リップル特性をもたらします。
チェビシェフI型フィルタ
振幅特性
\(N\) 次チェビシェフI型ローパスフィルタの振幅二乗関数は次の式で定義されます。
\[|H(j\Omega)|^2 = \frac{1}{1 + \varepsilon^2 T_N^2\!\left(\dfrac{\Omega}{\Omega_p}\right)} \tag{2}\]ここで、
- \(\varepsilon\): リップル係数(\(\varepsilon > 0\))
- \(\Omega_p\): 通過域端の角周波数
- \(T_N\): \(N\) 次チェビシェフ多項式
\(\Omega \leq \Omega_p\) の通過域では \(T_N(\Omega/\Omega_p) \in [-1, 1]\) となり、振幅は \(1/\sqrt{1+\varepsilon^2}\) から \(1\) の間を等振幅でリップルします。通過域リップル \(R_p\) [dB] とリップル係数の関係は次のとおりです。
\[\varepsilon = \sqrt{10^{R_p/10} - 1} \tag{3}\]極の配置
チェビシェフI型フィルタの極は、楕円上に配置されます。\(k = 1, 2, \ldots, N\) について
\[\sigma_k = -\sinh\!\left(\frac{\operatorname{arcsinh}(1/\varepsilon)}{N}\right)\sin\theta_k \tag{4}\]\[\omega_k = \cosh\!\left(\frac{\operatorname{arcsinh}(1/\varepsilon)}{N}\right)\cos\theta_k \tag{5}\]ただし \(\theta_k = \dfrac{\pi(2k-1)}{2N}\) です。安定な左半平面の極 \(s_k = \sigma_k + j\omega_k\) のみを採用します。
チェビシェフII型フィルタ
チェビシェフII型(逆チェビシェフ)フィルタは、阻止域に等リップルを持ち、通過域は単調です。振幅二乗関数は次のとおりです。
\[|H(j\Omega)|^2 = \frac{1}{1 + \left[\varepsilon^2 T_N^2\!\left(\dfrac{\Omega_s}{\Omega}\right)\right]^{-1}} \tag{6}\]ここで \(\Omega_s\) は阻止域端の角周波数です。通過域が単調なので、位相特性がI型より滑らかになります。
I型とII型の特性比較
| 特性 | チェビシェフI型 | チェビシェフII型 |
|---|---|---|
| 通過域 | 等リップル | 単調(平坦) |
| 阻止域 | 単調 | 等リップル |
| 遷移帯域 | バターワースより急峻 | バターワースより急峻 |
| 位相特性 | 非線形(I型より非線形) | 比較的滑らか |
| 用途 | ノイズ除去の急峻遮断 | 通過域平坦性重視 |
フィルタ次数の決定
所望の仕様(通過域リップル \(R_p\)、阻止域減衰 \(R_s\)、通過域端 \(\Omega_p\)、阻止域端 \(\Omega_s\))から必要な次数を求めます。
\[N \geq \frac{\operatorname{arccosh}\!\left(\sqrt{\dfrac{10^{R_s/10}-1}{10^{R_p/10}-1}}\right)}{\operatorname{arccosh}(\Omega_s/\Omega_p)} \tag{7}\]同じ仕様に対して、チェビシェフフィルタはバターワースフィルタよりも低い次数で仕様を満足できます。
Python実装
SciPyによるチェビシェフI型フィルタ設計
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
# --- フィルタ仕様 ---
fs = 1000 # サンプリング周波数 [Hz]
fp = 100 # 通過域端 [Hz]
rp = 1.0 # 通過域リップル [dB]
orders = [2, 4, 6]
fig, axes = plt.subplots(2, 1, figsize=(10, 8))
for N in orders:
# チェビシェフI型ローパスフィルタ
sos = signal.cheby1(N, rp, fp, btype='low', fs=fs, output='sos')
w, h = signal.sosfreqz(sos, worN=4096, fs=fs)
axes[0].plot(w, 20 * np.log10(np.abs(h) + 1e-12), label=f'N={N}')
axes[1].plot(w, np.degrees(np.unwrap(np.angle(h))), label=f'N={N}')
axes[0].set_xlabel('Frequency [Hz]')
axes[0].set_ylabel('Magnitude [dB]')
axes[0].set_title('Chebyshev Type I - Magnitude Response (rp=1dB)')
axes[0].set_xlim(0, 500)
axes[0].set_ylim(-80, 5)
axes[0].axvline(fp, color='gray', linestyle='--', alpha=0.5, label=f'fp={fp}Hz')
axes[0].axhline(-rp, color='r', linestyle=':', alpha=0.5, label=f'-{rp}dB ripple')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
axes[1].set_xlabel('Frequency [Hz]')
axes[1].set_ylabel('Phase [degrees]')
axes[1].set_title('Chebyshev Type I - Phase Response')
axes[1].set_xlim(0, 500)
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
チェビシェフII型フィルタ設計
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
fs = 1000
fs_stop = 150 # 阻止域端 [Hz]
rs = 40.0 # 阻止域減衰量 [dB]
orders = [2, 4, 6]
fig, axes = plt.subplots(2, 1, figsize=(10, 8))
for N in orders:
# チェビシェフII型ローパスフィルタ
sos = signal.cheby2(N, rs, fs_stop, btype='low', fs=fs, output='sos')
w, h = signal.sosfreqz(sos, worN=4096, fs=fs)
axes[0].plot(w, 20 * np.log10(np.abs(h) + 1e-12), label=f'N={N}')
axes[1].plot(w, np.degrees(np.unwrap(np.angle(h))), label=f'N={N}')
axes[0].set_xlabel('Frequency [Hz]')
axes[0].set_ylabel('Magnitude [dB]')
axes[0].set_title('Chebyshev Type II - Magnitude Response (rs=40dB)')
axes[0].set_xlim(0, 500)
axes[0].set_ylim(-80, 5)
axes[0].axvline(fs_stop, color='gray', linestyle='--', alpha=0.5, label=f'fs={fs_stop}Hz')
axes[0].axhline(-rs, color='r', linestyle=':', alpha=0.5, label=f'-{rs}dB')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
axes[1].set_xlabel('Frequency [Hz]')
axes[1].set_ylabel('Phase [degrees]')
axes[1].set_title('Chebyshev Type II - Phase Response')
axes[1].set_xlim(0, 500)
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
バターワースとの次数比較
from scipy.signal import buttord, cheb1ord
import numpy as np
# フィルタ仕様
fp = 100 # 通過域端 [Hz]
fs_stop = 150 # 阻止域端 [Hz]
rp = 1.0 # 通過域リップル [dB]
rs = 40.0 # 阻止域減衰量 [dB]
fs = 1000 # サンプリング周波数
# バターワースの必要次数
N_butter, Wn_butter = buttord(fp, fs_stop, rp, rs, fs=fs)
# チェビシェフI型の必要次数
N_cheby1, Wn_cheby1 = cheb1ord(fp, fs_stop, rp, rs, fs=fs)
print(f"バターワース : {N_butter}次")
print(f"チェビシェフI型 : {N_cheby1}次")
実行例では、同じ仕様に対してチェビシェフI型の方がバターワースよりも低い次数で設計できることが確認できます。
ノイズ除去への応用
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
fs = 1000
t = np.arange(0, 1, 1/fs)
clean = np.sin(2 * np.pi * 10 * t) + 0.5 * np.sin(2 * np.pi * 30 * t)
noisy = clean + 0.8 * np.random.randn(len(t))
# バターワース(4次)
sos_butter = signal.butter(4, 100, fs=fs, output='sos')
y_butter = signal.sosfiltfilt(sos_butter, noisy)
# チェビシェフI型(4次、1dBリップル)
sos_cheby1 = signal.cheby1(4, 1, 100, fs=fs, output='sos')
y_cheby1 = signal.sosfiltfilt(sos_cheby1, noisy)
# チェビシェフII型(4次、40dB減衰)
sos_cheby2 = signal.cheby2(4, 40, 150, fs=fs, output='sos')
y_cheby2 = signal.sosfiltfilt(sos_cheby2, noisy)
fig, axes = plt.subplots(4, 1, figsize=(10, 12), sharex=True)
axes[0].plot(t, noisy, alpha=0.5, label='Noisy'); axes[0].plot(t, clean, 'k', label='Original')
axes[0].set_title('Input Signal'); axes[0].legend(); axes[0].grid(True, alpha=0.3)
axes[1].plot(t, y_butter, label='Butterworth N=4'); axes[1].plot(t, clean, 'k', lw=1.5)
axes[1].set_title('Butterworth (N=4)'); axes[1].legend(); axes[1].grid(True, alpha=0.3)
axes[2].plot(t, y_cheby1, label='Chebyshev I N=4, rp=1dB'); axes[2].plot(t, clean, 'k', lw=1.5)
axes[2].set_title('Chebyshev Type I (N=4, rp=1dB)'); axes[2].legend(); axes[2].grid(True, alpha=0.3)
axes[3].plot(t, y_cheby2, label='Chebyshev II N=4, rs=40dB'); axes[3].plot(t, clean, 'k', lw=1.5)
axes[3].set_title('Chebyshev Type II (N=4, rs=40dB)')
axes[3].set_xlabel('Time [s]'); axes[3].legend(); axes[3].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
他のIIRフィルタとの比較
| フィルタ | 通過域 | 阻止域 | 遷移帯域 | 位相特性 |
|---|---|---|---|---|
| バターワース | 最大平坦 | 単調減少 | 広い | 比較的滑らか |
| チェビシェフI型 | 等リップル | 単調減少 | バターワースより狭い | 非線形 |
| チェビシェフII型 | 単調減少 | 等リップル | バターワースより狭い | 比較的滑らか |
| 楕円(Cauer) | 等リップル | 等リップル | 最も狭い | 最も非線形 |
急峻な遮断が必要で通過域のリップルが許容できる場合はI型、通過域の平坦性を保ちつつ阻止域を改善したい場合はII型が適しています。
まとめ
- チェビシェフフィルタはチェビシェフ多項式の等振幅特性を利用した等リップルIIRフィルタ
- I型は通過域に等リップル、II型は阻止域に等リップルを持つ
- 同次数でバターワースより急峻な遷移帯域を実現できる
- SciPyでは
signal.cheby1()/signal.cheby2()で設計、signal.cheb1ord()で必要次数を自動計算できる
関連記事
- ローパスフィルタの設計と比較:移動平均・バターワース・チェビシェフ - 移動平均・バターワース・チェビシェフを周波数応答・群遅延・ステップ応答で比較しています。
- バターワースフィルタの設計原理とPython実装 - チェビシェフと同系統のIIRフィルタで、通過域が最大平坦なバターワースを解説しています。
- FIRフィルタとIIRフィルタの比較 - チェビシェフ(IIR)とFIRフィルタの設計思想の違いを解説しています。
- ノッチフィルタの設計とPython実装 - 特定周波数を除去するIIRフィルタの応用例を解説しています。
- 指数移動平均(EMA)フィルタの周波数特性 - 最も単純な1次IIRフィルタであるEMAの周波数特性を解説しています。
- 高速フーリエ変換(FFT)の仕組みとPython実装 - フィルタの周波数特性を解析するFFTの詳細を解説しています。
- 適応フィルタ(LMS/RLS)の理論とPython実装 - 固定設計のチェビシェフと対比して、パラメータが自動調整される適応フィルタを解説しています。
参考文献
- Proakis, J. G., & Manolakis, D. G. (2007). Digital Signal Processing (4th ed.). Pearson.
- Oppenheim, A. V., & Schafer, R. W. (2009). Discrete-Time Signal Processing (3rd ed.). Prentice Hall.
- SciPy scipy.signal.cheby1 documentation
- SciPy scipy.signal.cheby2 documentation
関連ツール
- DevToolBox - 開発者向け無料ツール集 - JSON整形、正規表現テスターなど85種類以上の開発者向けツール
- CalcBox - 暮らしの計算ツール - 統計計算、複利計算など61種類以上の計算ツール