Scilabで連続ウェーブレット解析

id:ikeuchihiroki:20070222 で書いたように、連続ウェーブレット解析ができるフリーの環境というのはなかなか良いものがない。
Scilab上で動作するTOOLBOXでは以下のものがある。

  • Wavelab
  • Fraclab
  • Scilab Wavelet Toolbox

Scilab Wavelet Toolbox http://scwt.sourceforge.net/ は、小規模なウェーブレットツールボックスなのだが、地味に更新が続けられている。
連続ウェーブレット変換のコードはCで書かれていて、なかなか速い。

テストプログラム

fs=512;

x=[0:2047]/fs;
y=sin(2*%pi.*x.*(x/max(x)*64));

//        increase memory size
stacksize(10000000);

//        continous wavelet transform
scal=2^[1:1/32:6];
coef=cwt(y,scal,'cmor');

//        colormap obtaining
cmap=jetcolormap(512);
//        matrix normalization
n=wcodemat(abs(coef),512);

scf(0);
clf;
f=gcf();f.color_map=cmap;
xlabel Time[s]
ylabel Frequency[Hz]

getf scal2freq.sci

a=gca();

Matplot(n);


なかなかいい感じ。
でも、このままだと縦軸の意味がわからないので、スケールを周波数に変えて表示するようにしたい。
MATLABには、スケールを周波数に変換する関数が存在したので、同じような機能をする関数を書いてみる。

function [frq]=scal2freq(A,wname,fs)

  y=zeros(512,1);
  y($/2)=1;
  
  coef=cwt(y,A,wname);
  
  frq=[];
  for k=1:length(A)
    fftcoef=abs(fft(coef(k,:)));
    [m ind]=max(fftcoef,'c');
    
    tmp=ind-1;
    if tmp > length(y)/2
      tmp=length(y)-tmp;
    end
    frq=[frq;tmp/length(y)*fs];
  end
    
    
endfunction

Aがスケール、wnameがウェーブレットの名前、fsはサンプリング周波数。
理屈は簡単で、インパルスをウェーブレット変換して、各スケールの中心周波数を見ているだけだ。たぶん理屈はあっているはずだ。CWTの関数の制約上、スケールは長さ2以上のベクトルを入れないといけないので注意。

次に、縦軸横軸を調整する関数。

function coefs=cwt_plot(data,scal,wname,fs)
//plot settings
y_ticks_distance=16;

//        increase memory size
stacksize(10000000);

coef=cwt(data,scal,'cmor');

//        colormap obtaining
cmap=jetcolormap(512);
//        matrix normalization
n=wcodemat(abs(coef),512);

scf;
clf;
f=gcf();f.color_map=cmap;
xlabel Time[s]
ylabel Frequency[Hz]

getf scal2freq.sci

a=gca();

ay=a.y_ticks;
ay.locations=[0:y_ticks_distance:length(scal)]';
frq=scal2freq(scal($:-y_ticks_distance:1),'cmor',fs);
ay.labels=string(frq);
a.y_ticks=ay;


Matplot(n);

ax=a.x_ticks;
ax.labels=string(ax.locations/fs);
a.x_ticks=ax;
endfunction

dataは解析対象信号,scalはスケール,wnameはウェーブレット関数の名前,fsはサンプリング周波数。
ウェーブレット関数の名前は、cwt.cを見るとわかる。今のところ以下の関数が使える。

sinus,poisson,mexh,morl,DOG,
gaus1,gaus2,gaus3,gaus4,gaus5,gaus6,gaus7,gaus8,
cmor,shan,fbsp,cauchy,
cgau1,cgau2,cgau3,cgau4,cgau5,cgau6,cgau7,cgau8

使用例:

fs=512;

x=[0:2047]/fs;
y=sin(2*%pi.*x.*(x/max(x)*64));

cwt_plot(y,2^[1:1/32:8],'cmor',fs);


縦軸、横軸がサンプリング周波数に合わせて適正な表示になった。

意外にScilab Wavelet Toolboxが良い感じだ。