(1)「例題で学ぶ過渡現象」 大重力、森本義広、神田一伸 共著 森北出版
(2)「ディジタル信号処理技術」玉井徳みち、長島厚、藤田泰弘、若井修造著 日経BP社
(3)「ディジタル信号処理の基礎」三上直樹著 CQ出版
(4)「C言語によるディジタル信号処理入門」三上直樹著 CQ出版
(5)「アナログ&ディジタルフィルタ入門」小野浩司著 日刊工業
(6)「フーリエの冒険」ヒッポファミリークラブ
(7)「C言語ではじめる医用情報処理」小高和宏 著 Ohmsha
3点移動平均を作る
| 番目 | 元データ | 移動平均の値 |
|---|---|---|
| 0 | 10 | - |
| 1 | 14 | - |
| 2 | 11 | (10+14+11)/3=11.67 |
| 3 | 15 | (14+11+15)/3=13.33 |
| 4 | 13 | (11+15+13)/3=13 |
| 5 | 17 | (15+13+17)/3=15 |
■定義

i=0のとき
i=1のとき
i=2のとき
i=3のとき
■気付いた点
1. 現在の点と過去の2点を使用して移動平均としている。
2. 3点移動平均の場合、各データに1/3の重みがかかっているとも判断できる。
3. データが3つたまる前は、過度現象と判断できる。

「平均」とはデータのでこぼこをならす操作であるので、移動平均すると図のように
データは滑らかになる。
つまり、移動平均は「ローパスフィルタ」であるといえる。
式から考えると、移動平均はインパルス応答(フィルタ係数)![h[0]=h[1]=h[2]=\frac{1}{3} h[0]=h[1]=h[2]=\frac{1}{3}](B0DCC6B0CABFB6D1_eq0007.gif)
で表される式であると考えることができる。
つまり、フィルタ係数は、
![h[0]=\frac{1}{3}, h[1]=\frac{1}{3}, h[2]=\frac{1}{3} h[0]=\frac{1}{3}, h[1]=\frac{1}{3}, h[2]=\frac{1}{3}](B0DCC6B0CABFB6D1_eq0008.gif)
![h[n] = \frac{1}{3} \delta[n]+\frac{1}{3}\delta[n-1]+\frac{1}{3}\delta[n-2] h[n] = \frac{1}{3} \delta[n]+\frac{1}{3}\delta[n-1]+\frac{1}{3}\delta[n-2]](B0DCC6B0CABFB6D1_eq0009.gif)
この式のZ変換は、
定義 ![X(z) = \sum_{n=0}^{\infty} x[n] z^{-n} X(z) = \sum_{n=0}^{\infty} x[n] z^{-n}](B0DCC6B0CABFB6D1_eq0010.gif)
から![H[z] = \sum_{n=0}^{2} h[n]z^{-n} =h[0]+h[1]z^{-1}+h[2]z^{-2} H[z] = \sum_{n=0}^{2} h[n]z^{-n} =h[0]+h[1]z^{-1}+h[2]z^{-2}](B0DCC6B0CABFB6D1_eq0011.gif)

![H[z] = \frac{1}{3} +\frac{1}{3}z^{-1}+\frac{1}{3}z^{-2} H[z] = \frac{1}{3} +\frac{1}{3}z^{-1}+\frac{1}{3}z^{-2}](B0DCC6B0CABFB6D1_eq0013.gif)
の周波数特性は、
![H[e^{j\omega\Delta t_{s}}] = \frac{1}{3} +\frac{1}{3}e^{-j\omega\Delta t_{s}}+\frac{1}{3}e^{-2j\omega\Delta t_{s}} H[e^{j\omega\Delta t_{s}}] = \frac{1}{3} +\frac{1}{3}e^{-j\omega\Delta t_{s}}+\frac{1}{3}e^{-2j\omega\Delta t_{s}}](B0DCC6B0CABFB6D1_eq0014.gif)
ここで簡単化のためサンプリング周期を1[s]とすれば
![H[e^{j\omega}] = \frac{1}{3} +\frac{1}{3}e^{-j\omega}+\frac{1}{3}e^{-2j\omega} H[e^{j\omega}] = \frac{1}{3} +\frac{1}{3}e^{-j\omega}+\frac{1}{3}e^{-2j\omega}](B0DCC6B0CABFB6D1_eq0015.gif)
![H[e^{j\omega}] = (\frac{1}{3}e^{j\omega} +\frac{1}{3}+\frac{1}{3}e^{-j\omega})e^{-j\omega} H[e^{j\omega}] = (\frac{1}{3}e^{j\omega} +\frac{1}{3}+\frac{1}{3}e^{-j\omega})e^{-j\omega}](B0DCC6B0CABFB6D1_eq0016.gif)

オイラーの公式

を使って
(1)
そしてフィルタの振幅特性と位相特性は、
振幅特性: 
位相特性: 
より
振幅特性は![| H[e^{j\omega}] | = | \frac{1+2\cos(\omega)}{3} | |e^{-j\omega}| | H[e^{j\omega}] | = | \frac{1+2\cos(\omega)}{3} | |e^{-j\omega}|](B0DCC6B0CABFB6D1_eq0022.gif)
![| H[e^{j\omega}] | = | \frac{1+2\cos(\omega)}{3} | \times 1 | H[e^{j\omega}] | = | \frac{1+2\cos(\omega)}{3} | \times 1](B0DCC6B0CABFB6D1_eq0023.gif)
![| H[e^{j\omega}] | = | \frac{1+2\cos(\omega)}{3} | | H[e^{j\omega}] | = | \frac{1+2\cos(\omega)}{3} |](B0DCC6B0CABFB6D1_eq0024.gif)
位相特性は


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% moving_average sample program
% programming by embedded.samurai
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
echo off
clear all
close all
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 生データを表示する
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(1);
x=[10,14,11,15,13,17];
[gyo,max]=size(x);
iti=[0:1:max-1];
% 生データを表示する
plot(iti,x,'ro-','linewidth',2);
hold on;
%3点移動平均
data=0;
y=[];
N=3;
for i=[N-1:1:max-1] %0番目から始めるといちいちめんどくさい
data=0;
for j=(i-(N-1)):1:i
data=data+1/N*x(j+1); %x(j+1) x(0)ができないためこういった処理も生じる
end
y=[y,data];
end
y
iti2=[N-1:1:max-1]
%3点移動平均をプロットする
plot(iti2,y,'bs-','linewidth',2);
axis([0 5 8 18]);
h=gca;
set(h,'LineWidth',2,...,
'FontSize',15);
grid on;
% キャプション
h=legend('元信号',...,
'3点移動平均した信号',...,
2);
set(h,'FontSize',15);
xlabel('Time[s]','Fontsize',15);
ylabel('Amplitude','Fontsize',15)
print -djpeg moving_average_sample_t.jpg
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 移動平均の周波数特性、位相特性を表示する
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(2)
subplot(2,1,1)
%サンプリング周期 1[s]
dt=1;
%サンプリング周波数1Hz
df=1/dt;
%周波数軸を作る
fre = [0:df*2/1000:df*2];
%FFTの絶対値を求める
H=abs((1+2*cos(2*pi*fre*dt))/3);
plot(fre,H,'r-','linewidth',2);
axis([0 df*2 0 Inf]);
grid on;
h=gca;
set(h,'LineWidth',2,...,
'FontSize',15);
xlabel('Frequency[Hz]','Fontsize',15);
ylabel('Normalize','Fontsize',15);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
subplot(2,1,2)
%サンプリング周期 1e-3[s]
dt=1e-3;
%サンプリング周波数1kHz
df=1/dt;
%周波数軸を作る
fre = [0:df*2/1000:df*2];
%FFTの絶対値を求める
H=abs((1+2*cos(2*pi*fre*dt))/3);
plot(fre,H,'b-','linewidth',2);
axis([0 df*2 0 Inf]);
grid on;
h=gca;
set(h,'LineWidth',2,...,
'FontSize',15);
xlabel('Frequency[Hz]','Fontsize',15);
ylabel('Amplitude','Fontsize',15);
print -djpeg moving_average_sinpuku_tokusei.jpg
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 移動平均の位相特性を表示する
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(3)
%サンプリング周期 1[s]
dt=1;
%サンプリング周波数1Hz
df=1/dt;
%周波数軸を作る
fre = [0:df*2/1000:df*2];
%FFTの絶対値を求める
H_iso=-(2*pi*fre);
plot(fre,H_iso,'r-','linewidth',2);
axis([0 df*2 -Inf Inf]);
grid on;
h=gca;
set(h,'LineWidth',2,...,
'FontSize',15);
xlabel('Frequency[Hz]','Fontsize',15);
ylabel('Phase[rad]','Fontsize',15);
print -djpeg moving_average_iso_tokusei.jpg
Z変換で移動平均が求められるならば、ある一定量のデータを移動平均する
場合は周波数領域で計算したほうが速い。

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% fft moving_average sample program
% programming by embedded.samurai
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
echo off
clear all
close all
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 生データを表示する
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(1);
%サンプリング周期 1[s]
dt=1;
%サンプリング周波数1Hz
df=1/dt;
x=[10,14,11,15,13,17];
[gyo,max]=size(x);
iti=[0:1:max-1];
% 生データを表示する
plot(iti,x,'ro-','linewidth',2);
hold on;
%3点移動平均
data=0;
y=[];
N=3;
for i=[N-1:1:max-1] %0番目から始めるといちいちめんどくさい
data=0;
for j=(i-(N-1)):1:i
data=data+1/N*x(j+1); %x(j+1) x(0)ができないためこういった処理も生じる
end
y=[y,data];
end
y
iti2=[N-1:1:max-1]
%3点移動平均をプロットする
plot(iti2,y,'bs-','linewidth',2);
axis([0 5 8 18]);
grid on;
h=gca;
set(h,'LineWidth',2,...,
'FontSize',15);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 3点FFTで移動平均する
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%元信号をフーリエ変換する
fftx=fft(x)
%インパルス応答(フィルタ係数)をフーリエ変換する
hn=[1/3,1/3,1/3]
ffthn=fft(hn,6) %このように書くと6点で足りない点つまりこの場合は3点を0補間できる
yfft=fftx.*ffthn
%逆フーリエ変換
yifft=ifft(yfft)
y
plot(iti,yifft,'m-','linewidth',2);
% キャプション
h=legend('元信号',...,
'3点移動平均した信号',...,
'3点FFT移動平均した信号',...,
2);
set(h,'FontSize',15);
xlabel('Time[s]','Fontsize',15);
ylabel('Amplitude','Fontsize',15)
print -djpeg moving_average_fft.jpg
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
普通に移動平均をかける場合と、FFT移動平均の場合とで比較してみる

上を拡大したのが下図である。

図により最初の10ポイントが両者一致しない(フィルタの過度状態のため)
結果は以下のとおり、最初の9つのデータに違いが現れる(過度現象のため)。
そのため、9つの過去データを入れたうえでFFTしなければならない。

1.2000000e+003 -1.1000000e-002 -6.4000000e-003 1.2010000e+003 -8.7000000e-003 -5.8000000e-003 1.2020000e+003 -1.2900000e-002 -9.5000000e-003 1.2030000e+003 -1.5600000e-002 -1.2700000e-002 1.2040000e+003 -1.7500000e-002 -1.3200000e-002 1.2050000e+003 -1.8100000e-002 -1.7000000e-002 1.2060000e+003 -2.1500000e-002 -1.8100000e-002 1.2070000e+003 -2.0100000e-002 -1.7500000e-002 1.2080000e+003 -1.6900000e-002 -1.9600000e-002 2.4000000e+003 -6.5000000e-003 1.5000000e-003 2.4010000e+003 -7.5000000e-003 1.0000000e-003 2.4020000e+003 -5.3000000e-003 3.0000000e-003 2.4030000e+003 -6.6000000e-003 2.5000000e-003 2.4040000e+003 -7.2000000e-003 -1.0000000e-003 2.4050000e+003 -6.2000000e-003 5.0000000e-004 2.4060000e+003 -5.4000000e-003 -1.6000000e-003 2.4070000e+003 -5.2000000e-003 -1.9000000e-003 2.4080000e+003 -3.2000000e-003 -1.1000000e-003 3.6000000e+003 -6.7000000e-003 1.8000000e-003 3.6010000e+003 -3.2000000e-003 3.3000000e-003 3.6020000e+003 1.8000000e-003 5.4000000e-003 3.6030000e+003 -1.0000000e-004 4.0000000e-003 3.6040000e+003 2.0000000e-004 2.5000000e-003 3.6050000e+003 1.5000000e-003 1.4000000e-003 3.6060000e+003 2.2000000e-003 2.6000000e-003 3.6070000e+003 -1.7000000e-003 -5.0000000e-004 3.6080000e+003 1.5000000e-003 0.0000000e+000 4.8000000e+003 -1.8900000e-002 -3.2000000e-003 4.8010000e+003 -1.9100000e-002 -4.9000000e-003 4.8020000e+003 -1.9400000e-002 -7.8000000e-003
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% sample program
% programming by embedded.samurai
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
echo off
clear all
close all
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 生データを表示する
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(1);
subplot(2,1,1);
%//250Hz
dt=0.004;
load 'input1.txt'
load 'output_moveave.txt'
load 'output_fft_moveave.txt'
%row 行 column 列
[row,column]=size(output_fft_moveave)
time=[0:row-1];
input1=input1(1:row);
output_moveave=output_moveave(1:row);
% 生データを表示する
plot(time,input1,'r-','linewidth',2);
hold on;
axis([-Inf Inf -Inf Inf]);
h=gca;
set(h,'LineWidth',2,...,
'FontSize',15,'FontName','Century');
grid on;
% キャプション
h=legend('元のデータ',...,
'3',...,
2);
set(h,'FontSize',15,'FontName','MSゴシック');
xlabel('Time[s]','Fontsize',15,'FontName','Century');
ylabel('Amplitude','Fontsize',15,'FontName','Century')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
subplot(2,1,2);
% 移動平均データを表示する
plot(time,output_moveave,'ro-','linewidth',2);
hold on;
% 移動平均データを表示する
plot(time,output_fft_moveave,'b+-','linewidth',2);
hold on;
axis([-Inf Inf -Inf Inf]);
h=gca;
set(h,'LineWidth',2,...,
'FontSize',15,'FontName','Century');
grid on;
% キャプション
h=legend('移動平均',...,
'移動平均(FFT)',...,
'3',...,
4);
set(h,'FontSize',15,'FontName','MSゴシック');
xlabel('Time[s]','Fontsize',15,'FontName','Century');
ylabel('Amplitude','Fontsize',15,'FontName','Century')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
result2=[];
for i=1:1:row
if(output_moveave(i) ~= output_fft_moveave(i))
result=cat(2,i-1,output_moveave(i),output_fft_moveave(i));
result2=cat(1,result2,result);
end
end
save kentoudata.txt result2 -ascii
print -djpeg move_ave_discuss2.jpg