本文第一部分先解釋AR譜,但并不會給出太多的細節(jié),第二部分介紹幾種常見的語音中的特征,有些在之前的博文中已經(jīng)用過,諸如過零率。第三部分給出實際操作的過程及識別的效果。本文的目標是通過對DSP采集的聲音信號提取特征,識別卡車和飛機。
AR模型全稱Auto-Regression Model,是通過參數(shù)計算信號功率譜的一種方法。在Matlab中計算AR譜很簡單:假設(shè)有一個1024個點的車輛信號x,
y =pyulear(x,256,128);
AR譜的計算有2個重要的參數(shù):系數(shù)階數(shù)、FFT反變換的點數(shù)。AR譜是一種遞推模型,即用前p個時刻的時域值估計當前第n時刻的值:
其中u(n)是噪聲輸入,系數(shù)階數(shù)就是上式中的p。牽扯到FFT,是因為功率譜的計算中可以使用FFT進行快速計算,因此就有離散FFT在單位圓上抽樣點數(shù)的問題,功率譜的計算公式是:
上式中轉(zhuǎn)化后有a0=1,將FFT計算擴充到N點后有a(p+1)...a(N-1)=0,F(xiàn)FT點數(shù)就是指的這里用于FFT計算的長度N。
AR譜是一個什么樣的概念呢,首先我對功率譜的理解就是:不同頻率處的能量值的大小,這個大小并不一定是真實的能量值,但不同頻率的能量譜值的相對大小關(guān)系卻接近真實值,因此不同頻率處功率譜值的相對關(guān)系比其真實的譜值更重要。比如,車輛在遠處的時候能量相對較小,在近處的時候能量較大,但對于平穩(wěn)的信號,雖然能量值不同,但都具有相似的譜包絡(luò),因此我們更關(guān)注的是譜在不同頻率上的分布大小,就像概率一樣,看在哪個頻率值(或段)的功率譜大。
通過觀察AR譜,我們能清晰的知道:主要的能量都集中在什么頻率段,從而對信號進行分析主要關(guān)注這些頻率段就行了。
AR譜的細節(jié)參見胡廣書編著《數(shù)字信號處理》一書,其C實現(xiàn)參考我的Github項目,關(guān)于AR的基本理論參見之前的博文“現(xiàn)代數(shù)字信號處理——AR模型”
1 短時平均能量(Short Time Energy, STE)
其中N表示一幀的長度。短時平均能量可用于判斷靜音幀,靜音幀的短時能量小,這比直接通x(n)的最高幅值進行判斷穩(wěn)定性要高。對于靜音幀,應(yīng)該在后續(xù)的處理之前去除。通常,語音比音樂含有更多的靜音(人說話沒有音樂那樣著腔帶調(diào)),因此,語音的平均能量的變化要比音樂中大很多。
2 短時過零率(Short Time Zero-Corssing Rate, ZCR)
短時過零率是在一個音頻幀內(nèi),離散采樣信號值由負到正或由正到負的變換次數(shù)。
從某種程序上講,過零率表達了信號的跳變速度,是頻率的一種簡單度量。過零率與平均能量結(jié)合能用于語音端點檢測。在博文自適應(yīng)含噪信號過零率算法中也曾嘗試改進過零率用于震動信號的識別。
3 子帶能量比(Sub-band energy ratio, SER)
子帶能量用于描述主要能量的頻域分布特征,其過程就是將頻域等間隔劃分成B個子帶,在AR譜圖上,對每個子帶范圍進行積分就可求出子帶能量Ei,則子帶能量比就是
不同音頻信號的能量分布不同,通過子帶能量能區(qū)分能量的主要分布頻帶。子帶能量比是一個很好參數(shù),用于識別頻率能量分布不同的目標。當然類似的思想也可以用到FFT頻譜圖上。
4 譜頻率重心(Spectrum Centroid, SC)
將AR譜的幅值看做權(quán)值w,則譜頻率重心的計算是:
譜頻率重心是通過譜峰統(tǒng)計的中心,并不會(當然也可能等于)等于AR譜主峰對應(yīng)的頻率。
帶寬指信號譜值下降到中心頻率譜值的0.707處的高低頻率差BW=fH-fL。
卡車和飛機的主頻位置可能存在不同,所以使用聲音信號AR譜的最高峰值對應(yīng)的頻率Fmax作為一個特征維度;另外使用譜頻率重心和子帶能量比分別作為特征的另兩個維度。因此,最后組合特征為{Fmax,SC,SER}。
值得注意的是,本文使用的譜頻率重心不是簡單的對所有頻域進行統(tǒng)計計算,而是:
先對頻譜org_psd進行從高到低排序,排序后的psd以及對應(yīng)的頻率索引為idx
選擇部分具有高的譜值(這些譜值的和占整個頻域譜值和的0.707)進行頻譜重心計算,這樣能避免一些高頻噪聲的影響。
識別使用支持向量機(SVM)模型,關(guān)于支持向量機,對于沒太多基礎(chǔ)的可以參考July的博文支持向量機通俗導論(理解SVM的三層境界),有一點基礎(chǔ)的可以看看林智仁老師的講義,這里使用的工具箱就是林智仁的LibSVM,可以從軟件主頁http://www.csie.ntu.edu.tw/~cjlin/libsvm/index.html中下載到。
實際操作通過自己設(shè)計的DSP+FPGA控制AD7606采集聲音信號,將聲音信號上傳到PC的matlab上進行訓練,提取特征。很重要的一點是:使用分類算法(比如這里的LibSVM支持向量機或其它的如神經(jīng)網(wǎng)絡(luò)等)進行分類的前提是數(shù)據(jù)本身可分,如下為卡車和飛機的特征可視化結(jié)果,從圖中可以看出,兩類樣本使用上面構(gòu)造的特征可分,因此才可以接著做識別的工作。
使用LibSVM訓練,核函數(shù)使用RBF,效果一般比其它的要好一些,這里大部分參數(shù)默認(主要有g(shù)amma和C參數(shù))。要使用LibSVM獲得好的效果,請參考我的另一篇博文“LibSVM筆記系列(2)——如何提升LibSVM分類效果”,主要是一些關(guān)于如何搜索獲得最佳參數(shù)的方法。
實驗總共數(shù)據(jù)1400組,卡車和飛機各選200組用于訓練(代碼為實際代碼的一部分,由于其它原因,暫時無法公開代碼),
n_trian = 200;
label_car = zeros(length(car_feat),1);
label_plane = ones(length(plane_feat),1);
instance = [car_feat(idx,1:n_trian) plane_feat(idx,1:n_trian)];? % idx表示第idx維的特征
instance = instance';
label = [label_car(1:n_trian); label_plane(1:n_trian)];
model = svmtrain(label, instance, '-s 0 -t 2');? % SVM訓練結(jié)果為model模型,這個模型將用于下面的預測
其余的1000組用于測試,
tests = [car_feat(idx,(n_trian+1):end) plane_feat(idx,(n_trian+1):end)];
test_label = [label_car((n_trian+1):end); label_plane((n_trian+1):end)];
tests = tests';
pd_label = svmpredict(test_label, tests, model);
fprintf('\n識別正確率%.4f\n', length(pd_label(test_label==pd_label))/length(test_label));
最后的預測結(jié)果如下:
預測正確率達到86.50%,能使用到到實際當中。