20.11.03 butter濾波瓷炮,c代碼

最近要把巴特沃斯濾波算法移植到嵌入式端,之前一直是在服務(wù)器端用python搞的递宅,簡(jiǎn)單粗暴娘香,幾行代碼就解決問(wèn)題了苍狰,如下:

import numpy as np
from scipy import signal

def data_filt(array):
    array = array-np.mean(array, axis=1, keepdims=True)
    b, a = signal.butter(4, [0.5, 30], 'bandpass',fs=Fs) 
    print('b = ', b)
    print('a = ', a)
    data = signal.filtfilt(b, a, array, axis=1)
    return data

b = [ 0.00842863 0. -0.03371451 0. 0.05057177 0.
-0.03371451 0. 0.00842863]
a = [ 1. -6.05023914 16.06728061 -24.56190002 23.72091821
-14.84696022 5.88026366 -1.34582827 0.13646518]

采用scipy.signal里面的butter函數(shù),先計(jì)算濾波系數(shù)b,a,然后利用signal.filtfilt進(jìn)行iir濾波烘绽。

效果展示如下淋昭,輸入一個(gè)采樣率為250Hz的信號(hào),進(jìn)行[0.5 30]Hz范圍內(nèi)的帶通濾波安接。


butter帶通濾波

可以看出翔忽,對(duì)高頻分量和低頻分量都進(jìn)行了有效濾除,效果還不錯(cuò)盏檐。

總結(jié)下總共兩步:

  • 計(jì)算butter系數(shù)b歇式,a
  • 將b,a輸入到iir濾波器胡野,進(jìn)行濾波

其中iir濾波的公式如下:
y[n] = \sum_{i=0}^Nb[i]x[n-i]-\sum_{i=1}^Na[i]y[n-i]

現(xiàn)在要做的是材失,把這兩步用c實(shí)現(xiàn)。

1. 計(jì)算butter系數(shù)

找了很多教程硫豆,最后發(fā)現(xiàn)了一個(gè)神奇的網(wǎng)站龙巨,https://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html,可以直接幫助計(jì)算參數(shù)b熊响,a,且給出濾波代碼旨别。

自動(dòng)計(jì)算濾波參數(shù)

如上圖,把參數(shù)填好后耘眨,直接點(diǎn)擊網(wǎng)頁(yè)下方的提交昼榛,濾波系數(shù)就生成了,如下:

結(jié)果展示

其中參數(shù)b,a就隱藏在Recurrence relation里面境肾。根據(jù)公式y[n] = \sum_{i=0}^Nb[i]x[n-i]-\sum_{i=1}^Na[i]y[n-i]可以知道剔难,

y[n] = (  1 * x[n- 8])
     + (  0 * x[n- 7])
     + ( -4 * x[n- 6])
     + (  0 * x[n- 5])
     + (  6 * x[n- 4])
     + (  0 * x[n- 3])
     + ( -4 * x[n- 2])
     + (  0 * x[n- 1])
     + (  1 * x[n- 0])

     + ( -0.1364651827 * y[n- 8])
     + (  1.3458282682 * y[n- 7])
     + ( -5.8802636583 * y[n- 6])
     + ( 14.8469602185 * y[n- 5])
     + (-23.7209182114 * y[n- 4])
     + ( 24.5619000249 * y[n- 3])
     + (-16.0672806050 * y[n- 2])
     + (  6.0502391423 * y[n- 1])

這里面的x[n-8], x[n-7], ..., x[n-0]對(duì)應(yīng)的系數(shù)就是b[8], b[7], ..., b[0]。即b=[1,0,-4,0,6,0,-4,0,1]奥喻。同理可得
a =[1,-6.0502391423,16.0672806050,-24.5619000249,23.7209182114, -14.8469602185,5.8802636583,-1.3458282682,0.1364651827]
跟上面python的結(jié)果對(duì)比下偶宫,發(fā)現(xiàn)a是一致的,但是b不一致环鲤,原因是因?yàn)樗麄冎g差了一個(gè)gain纯趋。就是Results那副圖里面的 gain at centre: mag = 1.185137516e+02, b的每個(gè)值都除以1.185137516e+02,就和python的結(jié)果一致了冷离。

2. 將參數(shù)b吵冒,a用于iir濾波

主要就是對(duì)公式y[n] = \sum_{i=0}^Nb[i]x[n-i]-\sum_{i=1}^Na[i]y[n-i]的實(shí)現(xiàn)。
比較牛逼的點(diǎn)就是西剥,上面推薦的那個(gè)網(wǎng)站把這個(gè)也給做好了痹栖,我們基本上只需要復(fù)制。

image.png

這是網(wǎng)站生成的Ansi C的代碼瞭空。

#define NZEROS 8
#define NPOLES 8
#define GAIN   1.185137516e+02

static float xv[NZEROS+1], yv[NPOLES+1];

static void filterloop()
  { for (;;)
      { xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6]; xv[6] = xv[7]; xv[7] = xv[8]; 
        xv[8] = next input value / GAIN;
        yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6]; yv[6] = yv[7]; yv[7] = yv[8]; 
        yv[8] =   (xv[0] + xv[8]) - 4 * (xv[2] + xv[6]) + 6 * xv[4]
                     + ( -0.1364651827 * yv[0]) + (  1.3458282682 * yv[1])
                     + ( -5.8802636583 * yv[2]) + ( 14.8469602180 * yv[3])
                     + (-23.7209182110 * yv[4]) + ( 24.5619000250 * yv[5])
                     + (-16.0672806050 * yv[6]) + (  6.0502391423 * yv[7]);
        next output value = yv[8];
      }
  }

利用這個(gè)代碼揪阿,對(duì)信號(hào)進(jìn)行濾波疗我,并同python的結(jié)果對(duì)比,如下:


butter濾波對(duì)比南捂。第一行是原始信號(hào)吴裤,第二行用python的butter代碼濾波,第三行c的butter代碼濾波

發(fā)現(xiàn)效果基本上都有了溺健,但是還是差一點(diǎn)點(diǎn)麦牺,仔細(xì)看還是沒有python濾波的效果好。
那么問(wèn)題出在了那里呢鞭缭?

第一步計(jì)算參數(shù)b,a枕面,python和c的結(jié)果是一樣的。所以只能是出在了第二步:iir濾波缚去。

python用到的是signal.filtfilt()函數(shù)潮秘。我們看下它的源碼的核心部分:

image.png

原因找到了,在filtfilt函數(shù)里易结,進(jìn)行完Forward filter濾波——lfilter以后枕荞,把結(jié)果y做了翻轉(zhuǎn),然后又進(jìn)行了一次lfilter濾波——即Backword濾波搞动。最后再把y翻轉(zhuǎn)回來(lái)躏精,進(jìn)行return。

相比較的話鹦肿,我們的代碼里只進(jìn)行了Forward濾波矗烛,沒有Backword。所以我們仿照這個(gè)方法箩溃,把生成的結(jié)果y進(jìn)行翻轉(zhuǎn)瞭吃,再做一次相同的濾波,最后再翻轉(zhuǎn)回來(lái)涣旨,作為最終的濾波結(jié)果歪架。對(duì)照?qǐng)D如下:

對(duì)照?qǐng)D

YES!! 這一次python和c的結(jié)果就一模一樣了。大功告成霹陡,完美和蚪!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市烹棉,隨后出現(xiàn)的幾起案子攒霹,更是在濱河造成了極大的恐慌,老刑警劉巖浆洗,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件催束,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡辅髓,警方通過(guò)查閱死者的電腦和手機(jī)泣崩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門少梁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人矫付,你說(shuō)我怎么就攤上這事凯沪。” “怎么了买优?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵妨马,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我杀赢,道長(zhǎng)烘跺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任脂崔,我火速辦了婚禮滤淳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘砌左。我一直安慰自己脖咐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布汇歹。 她就那樣靜靜地躺著屁擅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪产弹。 梳的紋絲不亂的頭發(fā)上派歌,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音痰哨,去河邊找鬼胶果。 笑死,一個(gè)胖子當(dāng)著我的面吹牛作谭,可吹牛的內(nèi)容都是我干的稽物。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼折欠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了吼过?” 一聲冷哼從身側(cè)響起锐秦,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盗忱,沒想到半個(gè)月后酱床,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡趟佃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年扇谣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昧捷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡罐寨,死狀恐怖靡挥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸯绿,我是刑警寧澤跋破,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瓶蝴,受9級(jí)特大地震影響毒返,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舷手,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一拧簸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧男窟,春花似錦狡恬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至姥芥,卻和暖如春兔乞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凉唐。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工庸追, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人台囱。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓淡溯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親簿训。 傳聞我的和親對(duì)象是個(gè)殘疾皇子咱娶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355