頻域塊濾波

DFT特性

對于離散時間信號,時域的循環(huán)卷積與其DFT信號的頻域乘積互為變換對
\sum_{m=0}^{N-1}x_1(m)x_2[((n_m))_N] \iff X_1(k)X_2[k]

時域信號通過線性系統(tǒng)時,所經(jīng)歷的運算為線性卷積。
當線性系統(tǒng)的響應階數(shù)增大時,時域相卷的運算要遠高于頻域的點乘運算(DFT可以使用FFT實現(xiàn))。
因此如何將時域的線性卷積轉換到頻域上進行點乘是降低復雜度的關鍵
進而問題可以轉換為如何將循環(huán)卷積與線性卷積等價的問題上來。

線性卷積與循環(huán)卷積的關系

信號x(n),長度為M,系統(tǒng)響應h(n),長度為N

  • 線性卷積:y_l(n)=x(n)*h(n)=\sum_{m=0}^{N-1}x(m)h(n-m)
    卷積結果長度為M+N-1
  • 循環(huán)卷積:y_c(n)=\Big[\sum_{m=0}^{N-1}x(m)h\big((n-m)\big)_L\Big]R_L(n)
    兩者關系:y_c(n)=\Big[\sum_{m=0}^{N-1}y_l(n+iL)R_L(n)\Big]

y_c(n)y_l(n)是以L為周期的周期延拓序列的主值序列。

循環(huán)卷積與線性卷積的關系是由循環(huán)卷積的長度L決定:

  • L<M+N-1:循環(huán)卷積是線性卷積長度為L的混疊(對應下圖中p1);
  • L=M+N-1:兩者相等(對應下圖中p2);
  • L>M+N-1:線性卷積末尾補L-M-N+1個0(對應下圖中p3);。

仿真驗證

完整代碼附在文章最后

close all;clc;clear ;
N = 4 ; M = 5 ;
xn = (1:M).' ;
hn = (N:-1:1).';
yn_liner = conv(xn, hn) ;
L = M+N-4; [yn_circle1] = cConv.circle_conv_func(xn,hn,L) ;
L = M+N-1; [yn_circle2] = cConv.circle_conv_func(xn,hn,L) ;
L = M+N+5; [yn_circle3] = cConv.circle_conv_func(xn,hn,L) ;
nr = 2 ; nc = 2 ;
figure;set(gcf,'position',[0 0 800 800])
subplot(nr, nc,1);stem(xn,'b.'); hold on;grid on;
stem(hn,'ro');title('xn, hn');legend('xn', 'yn', 'location', 'best')
subplot(nr, nc,2);plot(yn_liner,'b');hold on;title('p1'); grid on;
plot(yn_circle1,'ro');legend('liner', 'circle L<N+M-1', 'location', 'best')
subplot(nr, nc,3);plot(yn_liner,'b');hold on;title('p2'); grid on;
plot(yn_circle2,'ro');legend('liner', 'circle L=N+M-1', 'location', 'best')
subplot(nr, nc,4);plot(yn_liner,'b');hold on;title('p3'); grid on;
plot(yn_circle3,'ro');legend('liner', 'circle L>N+M-1', 'location', 'best')
線性卷積vs循環(huán)卷積.png

實時信號濾波中的應用

在實際應用中,由于需要處理的信號是持續(xù)不斷的信號,無法全部存儲下來進行濾波處理。工程實現(xiàn)中是將持續(xù)不斷的信號進行塊狀分割,單獨對每一塊進行濾波處理。單獨每塊的操作即可以用DFT的性質來實現(xiàn)頻域濾波。每塊的長度以硬件處理能力相關。塊狀處理由以下兩種方案:

  • 重疊保留法(Overlap-Save)
  • 重疊相加法(Overlap-Add)

重疊保留法

后續(xù)整理為中文內容


image.png
仿真驗證

olp采用50%

close all;clc;clear ;
olp_rate = 0.50 ;

tap_num  = 8;
N_dft    = ceil(tap_num/olp_rate) ;
olp_len  = floor(N_dft*olp_rate) ;
N_data   = N_dft - olp_len ;
din_len  = N_data*10 ;
xn       = rand(1,din_len).' ;
hn       = rand(1,tap_num).' ;

%% liner
yn_liner = conv(xn, hn) ;

%% overlap-save
yn_circle = cConv.olp_save_func(xn, hn, N_dft, olp_len) ;

figure;
plot(yn_liner,'b-o');hold on;grid on;plot(yn_circle,'r-*');
legend('liner', 'circle', 'location', 'best');xlabel('n'),ylabel('yn');
title(['overlap-save yn=xn*hn (olp=' num2str(olp_rate),')']);
olp-save50%.png

由上圖結果可以驗證頻域DFT相乘可以等效實現(xiàn)時域線性卷積。

重疊相加法

image.png

仿真驗證

close all;clc;clear ;
olp_rate = 0.50;

tap_num  = 8 ;
N_dft    = ceil(tap_num/olp_rate) ;
olp_len  = floor(N_dft*olp_rate) ;
N_data   = N_dft - olp_len ;
din_len  = N_data*10 ;
xn       = rand(1,din_len).' ;
hn       = rand(1,tap_num).' ;
yn_liner = conv(xn, hn) ;

%% overlap-add
yn_circle = cConv.olp_add_func(xn, hn, N_dft, olp_len) ;

figure;
plot(yn_liner,'b-o');hold on;grid on;plot(yn_circle,'r-*');
legend('liner', 'circle', 'location', 'best');xlabel('n'),ylabel('yn');
title(['overlap-add yn=xn*hn (olp=' num2str(olp_rate),')']);
olp-add50%

不同olp ratio的影響

N_{DFT}表示DFT點數(shù),N_{tap}表示濾波器抽頭數(shù),R為olp比例,M表示數(shù)據(jù)長度,N_{blk}表示信號分的塊數(shù)。有如下關系:
N_{DFT}=\frac{N_{tap}}{R},N_{blk}=\frac{M}{1-R}

  • 從理論角度,olp比例取值范圍為(0,1],比例取1時,即為不加olp,此時數(shù)據(jù)長度較小時,可以一次完成DFT,因此不需要olp。
  • N_{DFT},M確定時, 濾波器抽頭數(shù)與olp比例成正比,與分組數(shù)量成反比,即:抽頭越多,R需要越大,則每拍中無效信號增加,導致處理信號的效率越低。

實際中,濾波器抽頭數(shù)量與FFT點數(shù)共同確定olp比例。

附本文所用到的代碼

classdef cConv
    %CCONV 此處顯示有關此類的摘要
    %   此處顯示詳細說明
    
    properties
        Property1
    end
    
    methods
        function obj = cConv()
            close all;clc;clear ;
            %% overlap-save
            cConv.test_olp_save(0.25) ;
            cConv.test_olp_save(0.5) ;
            cConv.test_olp_save(0.75) ;
            %% overlap-add
            cConv.test_olp_add(0.25) ;
            cConv.test_olp_add(0.5) ;
            cConv.test_olp_add(0.75) ;
        end
    end
    methods(Static)
        function test_liner_circle_conv()
            close all;clc;clear ;
            N = 4 ; M = 5 ;
            xn = (1:M).' ;
            hn = (N:-1:1).';
            yn_liner = conv(xn, hn) ;
            L = M+N-4; [yn_circle1] = cConv.circle_conv_func(xn,hn,L) ;
            L = M+N-1; [yn_circle2] = cConv.circle_conv_func(xn,hn,L) ;
            L = M+N+5; [yn_circle3] = cConv.circle_conv_func(xn,hn,L) ;
            nr = 2 ; nc = 2 ;
            figure;set(gcf,'position',[0 0 800 800])
            subplot(nr, nc,1);stem(xn,'b.'); hold on;grid on;
            stem(hn,'ro');title('xn, hn');legend('xn', 'yn', 'location', 'best')
            subplot(nr, nc,2);plot(yn_liner,'b');hold on;title('p1'); grid on;
            plot(yn_circle1,'ro');legend('liner', 'circle L<N+M-1', 'location', 'best')
            subplot(nr, nc,3);plot(yn_liner,'b');hold on;title('p2'); grid on;
            plot(yn_circle2,'ro');legend('liner', 'circle L=N+M-1', 'location', 'best')
            subplot(nr, nc,4);plot(yn_liner,'b');hold on;title('p3'); grid on;
            plot(yn_circle3,'ro');legend('liner', 'circle L>N+M-1', 'location', 'best')
        end
        function test_olp_save(olp_rate)
            tap_num  = 8 ;
            N_dft    = ceil(tap_num/olp_rate) ;
            olp_len  = floor(N_dft*olp_rate) ;
            N_data   = N_dft - olp_len ;
            din_len  = N_data*10 ;
            xn       = rand(1,din_len).' ;
            hn       = rand(1,tap_num).' ;
            
            %% liner
            yn_liner = conv(xn, hn) ;
            
            %% overlap-save
            yn_circle = cConv.olp_save_func(xn, hn, N_dft, olp_len) ;
            
            figure;
            plot(yn_liner,'b-o');hold on;grid on;plot(yn_circle,'r-*');
            legend('liner', 'circle', 'location', 'best');xlabel('n'),ylabel('yn');
            title(['overlap-save yn=xn*hn (olp=' num2str(olp_rate),')']);
        end
        function test_olp_add(olp_rate)
            tap_num  = 8 ;
            N_dft    = ceil(tap_num/olp_rate) ;
            olp_len  = floor(N_dft*olp_rate) ;
            N_data   = N_dft - olp_len ;
            din_len  = N_data*10 ;
            xn       = rand(1,din_len).' ;
            hn       = rand(1,tap_num).' ;
            yn_liner = conv(xn, hn) ;
            
            %% overlap-save
            yn_circle = cConv.olp_add_func(xn, hn, N_dft, olp_len) ;
            
            figure;
            plot(yn_liner,'b-o');hold on;grid on;plot(yn_circle,'r-*');
            legend('liner', 'circle', 'location', 'best');xlabel('n'),ylabel('yn');
            title(['overlap-add yn=xn*hn (olp=' num2str(olp_rate),')']);
        end
        function yn = circle_conv_func(xn,hn,L)
            M = length(xn) ;
            N = length(hn) ;
            xn_l = [xn; zeros(L-M, 1)] ;
            hn_l = [hn; zeros(L-N, 1)] ;
            
            xk_f = fft(xn_l, L) ;
            hk_f = fft(hn_l, L) ;
            yk_f = xk_f.*hk_f ;
            yn   = ifft(yk_f, L) ;
        end
        function yn = olp_save_func(xn, hn, N_dft, olp_len)
            din_len = length(xn) ;
            N_data  = N_dft - olp_len ;
            grp_num = floor(din_len/N_data) ;
            xn      = xn(1:grp_num*N_data) ;
            
            %% olp
            xn_pad = [zeros(olp_len,1); xn] ;
            xn_olp = zeros(N_dft, grp_num) ;
            for ii = 1:din_len/N_data
                idx = (1:N_dft)+(ii-1)*N_data ;
                xn_olp(:, ii) = xn_pad(idx) ;
            end
            
            %% dft
            xk_f = fft(xn_olp, N_dft) ;
            hk_f = fft(hn, N_dft) ;
            yk_f = xk_f.*hk_f ;
            yn_t_olp = ifft(yk_f, N_dft) ;
            
            %% save
            yn_t_grp = yn_t_olp(olp_len+1:N_dft,:) ;
            yn = reshape(yn_t_grp, [], 1) ;
        end
        function yn = olp_add_func(xn, hn, N_dft, olp_len)
            din_len = length(xn) ;
            N_data  = N_dft - olp_len ;
            grp_num = floor(din_len/N_data) ;
            xn      = xn(1:grp_num*N_data) ;
            
            %% overlap;
            xn_olp  = zeros(N_dft, grp_num) ;
            idx_grp = zeros(N_dft, grp_num) ;
            for ii = 1:grp_num
                idx = (1:N_data)+(ii-1)*N_data ;
                xn_olp(:, ii) = [xn(idx); zeros(olp_len, 1) ];
                idx_grp(:,ii) = (1:N_dft)+(ii-1)*N_data ;
            end
            
            %% fft
            xk_f = fft(xn_olp, N_dft) ;
            hk_f = fft(hn, N_dft) ;
            yk_f = xk_f.*hk_f ;
            yn_t_olp = ifft(yk_f, N_dft) ;
            
            %% add
            yn_t_grp = zeros(grp_num*N_data, grp_num) ;
            for ii = 1:grp_num
                yn_t_grp(idx_grp(:,ii),ii) = yn_t_olp(:,ii) ;
            end
            yn = sum(yn_t_grp,2) ;
        end
    end
end


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容