ハイパスフィルタとは
ハイパスフィルタ(高域通過フィルタ)は、設定した遮断周波数より高い周波数成分を通過させ、低い周波数成分を減衰させるフィルタです。
直流成分(DC)の除去、振動センサの低周波ドリフト抑制、画像処理でのエッジ強調など、幅広い分野で活用されています。
主要パラメータ
| パラメータ | 説明 |
|---|---|
| \(f_c\) | 遮断周波数(-3dB点) |
| \(\omega_c\) | 遮断角周波数(\(\omega_c = 2\pi f_c\)) |
| \(N\) | フィルタ次数(大きいほど遷移帯域が急峻) |
| 通過帯域 | \(f > f_c\) の周波数範囲 |
| 阻止帯域 | \(f < f_c\) の周波数範囲 |
次数 \(N\) が大きいほど遮断特性が急峻になりますが、位相遅れや数値的不安定性のリスクも増します。
周波数応答の導出
ローパス→ハイパス変換
ハイパスフィルタはローパスフィルタ(LPF)のプロトタイプから周波数変換によって設計できます。
アナログ領域でのローパス→ハイパス変換は、複素変数 \(s\) を以下のように置き換えます。
\[ s \rightarrow \frac{\omega_c^2}{s} \tag{1}\]\(N\) 次のバターワース LPF の伝達関数
\[H_{LP}(s) = \frac{1}{\prod_{k=1}^{N}(s - s_k)} \tag{2}\]に変換 \((1)\) を適用すると、同次のバターワースハイパスフィルタが得られます。1次の場合は次式になります。
\[H_{HP}(s) = \frac{s}{s + \omega_c} \tag{3}\]式 \((3)\) は「微分器 + 1次ローパス」の構造を持ち、\(s \to 0\)(直流)で出力がゼロ、\(s \to \infty\)(高周波)で出力が1に近づくことを示しています。
離散時間ハイパスフィルタ(双一次変換)
式 \((3)\) を双一次変換(Bilinear Transform)でデジタル領域に変換します。
\[s = \frac{2}{T} \cdot \frac{1 - z^{-1}}{1 + z^{-1}} \tag{4}\]これを式 \((3)\) に代入すると、1次デジタルハイパスフィルタの伝達関数が得られます。
\[H(z) = \frac{1 - z^{-1}}{1 + \alpha z^{-1}} \cdot \frac{1}{1 + \frac{1}{\alpha}} \tag{5}\]ここで \(\alpha = 1 - 2f_c / f_s\)(プリワーピング係数)です。実用上は scipy.signal がこの計算を自動的に行います。
Pythonによる実装
scipy.signalを用いたIIRハイパスフィルタ
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
# --- パラメータ設定 ---
fs = 1000.0 # サンプリング周波数 [Hz]
fc = 100.0 # 遮断周波数 [Hz]
order = 4 # フィルタ次数
# --- バターワース ハイパスフィルタの設計 ---
nyq = fs / 2.0 # ナイキスト周波数
wn = fc / nyq # 正規化遮断周波数
b, a = signal.butter(order, wn, btype='high')
# --- 周波数応答の計算 ---
w, h = signal.freqz(b, a, worN=8000, fs=fs)
# --- プロット ---
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))
# ゲイン特性 (dB)
ax1.semilogx(w, 20 * np.log10(np.abs(h) + 1e-10))
ax1.axvline(fc, color='r', linestyle='--', label=f'$f_c$ = {fc} Hz')
ax1.axhline(-3, color='gray', linestyle=':', label='-3 dB')
ax1.set_xlabel('Frequency [Hz]')
ax1.set_ylabel('Gain [dB]')
ax1.set_title(f'Butterworth Highpass Filter (order={order})')
ax1.legend()
ax1.grid(True, which='both', alpha=0.3)
ax1.set_xlim([1, nyq])
ax1.set_ylim([-80, 5])
# 位相特性
ax2.semilogx(w, np.angle(h, deg=True))
ax2.axvline(fc, color='r', linestyle='--')
ax2.set_xlabel('Frequency [Hz]')
ax2.set_ylabel('Phase [degrees]')
ax2.set_title('Phase Response')
ax2.grid(True, which='both', alpha=0.3)
ax2.set_xlim([1, nyq])
plt.tight_layout()
plt.savefig('highpass_response.png', dpi=150, bbox_inches='tight')
plt.show()
FIRハイパスフィルタの設計
IIRフィルタは位相が非線形ですが、FIRフィルタは線形位相を実現できます。音声・医療信号処理など位相の保存が重要な場面で有用です。
from scipy.signal import firwin, freqz
# --- FIR ハイパスフィルタ ---
numtaps = 101 # フィルタ係数の数(奇数推奨)
fir_hpf = firwin(
numtaps,
fc,
pass_zero=False, # ハイパス指定
fs=fs,
window='hamming'
)
w_fir, h_fir = freqz(fir_hpf, worN=8000, fs=fs)
# IIRとFIRの比較プロット
plt.figure(figsize=(10, 5))
plt.semilogx(w, 20 * np.log10(np.abs(h) + 1e-10),
label='IIR Butterworth (order=4)', linewidth=2)
plt.semilogx(w_fir, 20 * np.log10(np.abs(h_fir) + 1e-10),
label=f'FIR Hamming (taps={numtaps})', linewidth=2, linestyle='--')
plt.axvline(fc, color='r', linestyle=':', alpha=0.7, label=f'$f_c$ = {fc} Hz')
plt.axhline(-3, color='gray', linestyle=':', alpha=0.7)
plt.xlabel('Frequency [Hz]')
plt.ylabel('Gain [dB]')
plt.title('Highpass Filter Comparison: IIR vs FIR')
plt.legend()
plt.grid(True, which='both', alpha=0.3)
plt.xlim([1, nyq])
plt.ylim([-80, 5])
plt.tight_layout()
plt.show()
信号への適用例
実際のノイズ混じり信号にハイパスフィルタを適用します。
# --- テスト信号の生成 ---
t = np.linspace(0, 1.0, int(fs), endpoint=False) # 1秒分
# 目的信号: 200 Hz のサイン波(高周波成分)
signal_pure = np.sin(2 * np.pi * 200 * t)
# ノイズ: 5 Hz の低周波ドリフト + ホワイトノイズ
noise = (
2.0 * np.sin(2 * np.pi * 5 * t) + # 低周波ドリフト(大振幅)
0.3 * np.random.randn(len(t)) # ホワイトノイズ
)
x_noisy = signal_pure + noise
# --- フィルタ適用 ---
# lfilter: 因果的フィルタ(リアルタイム処理向け、位相遅れあり)
y_lfilter = signal.lfilter(b, a, x_noisy)
# filtfilt: ゼロ位相フィルタ(オフライン処理向け、位相遅れなし)
y_filtfilt = signal.filtfilt(b, a, x_noisy)
# --- 比較プロット ---
fig, axes = plt.subplots(3, 1, figsize=(12, 8), sharex=True)
axes[0].plot(t[:300], x_noisy[:300], alpha=0.8, label='ノイズ混じり信号(低周波ドリフトあり)')
axes[0].set_ylabel('Amplitude')
axes[0].set_title('Input Signal (with low-frequency drift)')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
axes[1].plot(t[:300], y_lfilter[:300], color='orange', label='lfilter (因果的)')
axes[1].plot(t[:300], signal_pure[:300], color='gray', linestyle='--', alpha=0.6, label='真の信号')
axes[1].set_ylabel('Amplitude')
axes[1].set_title('After lfilter (位相遅れあり)')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
axes[2].plot(t[:300], y_filtfilt[:300], color='green', label='filtfilt (ゼロ位相)')
axes[2].plot(t[:300], signal_pure[:300], color='gray', linestyle='--', alpha=0.6, label='真の信号')
axes[2].set_ylabel('Amplitude')
axes[2].set_xlabel('Time [s]')
axes[2].set_title('After filtfilt (ゼロ位相)')
axes[2].legend()
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('highpass_filtering_result.png', dpi=150, bbox_inches='tight')
plt.show()
IIR vs FIR 設計の比較
| 特性 | IIR(バターワース等) | FIR |
|---|---|---|
| 位相特性 | 非線形(位相歪みあり) | 線形位相が実現可能 |
| フィルタ係数数 | 少ない(\(2N+1\)程度) | 多い(数十〜数百) |
| 計算コスト | 低い | 高い(タップ数依存) |
| 安定性 | 設計によっては不安定 | 常に安定 |
| 遮断特性 | 低次でも急峻 | タップ数増加で改善 |
| 遅延 | 非定数 | 定数遅延(\((N-1)/2\)サンプル) |
| 適した用途 | リアルタイム処理 | 音声・医療信号処理 |
設計指針:
- リアルタイムで計算コストを抑えたい → IIR(バターワース/チェビシェフ)
- 位相の線形性が重要(音声・医療信号) → FIR(Hamming/Kaiser窓)
- オフライン処理で位相遅れを完全除去 →
filtfilt(IIR/FIR共通)
次数と遮断特性の影響
# 次数の違いによる周波数応答の比較
fig, ax = plt.subplots(figsize=(10, 6))
for ord_n in [1, 2, 4, 8]:
b_n, a_n = signal.butter(ord_n, wn, btype='high')
w_n, h_n = signal.freqz(b_n, a_n, worN=8000, fs=fs)
ax.semilogx(w_n, 20 * np.log10(np.abs(h_n) + 1e-10), label=f'order={ord_n}')
ax.axhline(-3, color='gray', linestyle=':', label='-3 dB')
ax.axvline(fc, color='r', linestyle='--', alpha=0.5, label=f'$f_c$ = {fc} Hz')
ax.set_xlabel('Frequency [Hz]')
ax.set_ylabel('Gain [dB]')
ax.set_title('Effect of Filter Order on Highpass Response')
ax.legend()
ax.grid(True, which='both', alpha=0.3)
ax.set_xlim([1, nyq])
ax.set_ylim([-80, 5])
plt.tight_layout()
plt.show()
次数1では遷移帯域が緩やかで、次数8では急峻な遮断特性が得られます。ただし IIR フィルタでは次数が高くなるほど位相遅れと数値的不安定性のリスクが増すため、次数8以下が実用的な目安です。
ハイパスフィルタの実用例
| 用途 | \(f_c\) の目安 | 備考 |
|---|---|---|
| 音声のDC除去(マイク補正) | 20〜80 Hz | DC 成分による信号飽和を防ぐ |
| 加速度センサのドリフト除去 | 0.1〜1 Hz | 重力成分(定常成分)を除去 |
| 心電図(ECG)のベースライン | 0.5〜1 Hz | 呼吸による低周波変動を除去 |
| 画像のエッジ強調 | — | 2次元HPFで輪郭を強調(鮮鋭化) |
| 振動解析の低周波ノイズ除去 | 1〜10 Hz | 機械振動の直流バイアスや電源ハム波を除去 |
関連記事
- ローパスフィルタの設計と比較:移動平均・バターワース・チェビシェフ - ハイパスフィルタの双対であるローパスフィルタの設計を解説しています。
- バターワースフィルタの設計とPython実装 - ハイパス設計に利用するバターワースプロトタイプを詳しく解説しています。
- バンドパスフィルタの設計とPython実装 - ハイパス+ローパスを組み合わせた帯域通過フィルタを解説しています。
- FIRフィルタとIIRフィルタの比較 - FIR/IIRの設計思想の違いを理論から解説しています。
- ノッチフィルタの設計とPython実装 - 特定周波数のみを除去するバンドストップフィルタを解説しています。
- 指数移動平均(EMA)フィルタの周波数特性 - 1次IIRローパスフィルタとして見たEMAの周波数特性をZ変換から導出しています。
- 高速フーリエ変換(FFT)の仕組みとPython実装 - フィルタの効果を周波数領域で確認するために必要なFFTの基礎を解説しています。
- 適応フィルタ(LMS/RLS)の理論とPython実装 - 固定帯域ではなく環境に応じて特性を自動調整する適応フィルタを解説しています。
参考文献
- Proakis, J. G., & Manolakis, D. G. (2006). Digital Signal Processing: Principles, Algorithms, and Applications. Pearson.
- scipy.signal.butter — SciPy documentation
- scipy.signal.filtfilt — SciPy documentation
関連ツール
- DevToolBox - 開発者向け無料ツール集 - JSON整形、正規表現テスターなど85種類以上の開発者向けツール
- CalcBox - 暮らしの計算ツール - 統計計算、周波数変換など61種類以上の計算ツール