※記事内に商品プロモーションを含むことがあります。
はじめに
SciPyを使って、FIR (Finite Impulse Response, 有限インパルス応答) フィルタによる離散信号の波形を整形する。ローパス、ハイパス、バンドパス、バンドエリミネイトの各フィルタの設計から、信号への適用まで行う。
環境
ソフトウェア | バージョン |
---|---|
Python | 3.6.5 |
NumPy | 1.14.2 |
SciPy | 1.0.1 |
元の離散信号
次の3つの信号を合成して、フーリエ変換を行う離散信号とする。
- 周波数30[Hz], 振幅3の正弦波
- 周波数50[Hz], 振幅0.3の正弦波
- 周波数120[Hz], 振幅0.2の正弦波
信号のデータ点数は2048, サンプリング周期は0.001[s]とする。
|
|
SciPyの関数
フィルタの設計
まず、関数scipy.signal.firwin()
によりフィルタを設計する。
|
|
主な引数の説明は以下の通り。
numtaps
: int
FIRフィルタの長さ。
cutoff
: float or 1D array_like
カットオフ周波数。
ローパス、ハイパスの場合はfloat,
バンドパス、バンドエリミネイトの場合は1D array_likeとする。
cutoff
は0
からfs/2
の間にしなければならない。
window
: string
窓関数を指定する。デフォルトは’hamming' (ハミング窓)。
pass_zero
: bool
周波数0(直流成分)が通過するか指定。
デフォルトはTrue
.
fs
: float
信号のサンプル周波数。デフォルト値は2
.
scipy.signal.firwin()
の戻り値は、長さnumtapsのFIRフィルタの係数配列となる。
フィルタの適用
次に、関数scipy.signal.lfilter()
により信号にフィルタを適用する。
|
|
主な引数の説明は以下の通り。
b
: array
分子の係数。
a
: array
分母の係数。
x
: array
入力信号。
戻り値は、フィルタを掛けた信号の配列となる。
この関数では、フィルタが以下の式で表されているものとする。
$$ H(z)=\frac{\sum_{k=0}^{M} b_k z^{-k} } {\sum_{k=0}^{N} a_k z^{-k} } $$
引数b
が右辺の分子の係数、引数a
が右辺の分母の係数に対応する。今回はFIRフィルタを扱うので、分母のa
を1とおく。
波形整形
基本的なフィルタを信号に適用して、波形や振幅の変化を確認する。
ローパスフィルタ
カットオフ周波数を40[Hz]としたローパスフィルタ。
|
|
60, 300[Hz]の高周波成分が減衰・除去されている。
ハイパスフィルタ
カットオフ周波数を100[Hz]としたハイパスフィルタ。
|
|
10, 60[Hz]の低周波成分が除去されている。
バンドパスフィルタ
通過周波数を30~100[Hz]としたバンドパスフィルタ。
|
|
10, 300[Hz]の信号が減衰・除去されいている。
バンドエリミネイトフィルタ
通過周波数を30[Hz]以下、100[Hz]以上としたバンドエリミネイトフィルタ。
|
|
60[Hz]の信号が除去されいている。