離散卷積及計算

離散卷積的定義:

將兩個離散序列中的數,按照規則,兩兩相乘再相加的操作。

卷積運算:

y(n)=x(n)*h(n)=\sum_{m=-\infty }^{\infty }x(m)h(n-m)

x(n) 的長度是 n_{a}h(n) 的長度是 n_{b}y(n) 的長度是 n_{c}=n_{a}+n_{b}-1

計算卷積的過程:序列翻轉,移位,相乘,取和

計算舉例:

c_{n} = \sum_{k=0}^{k-1} a_{k} * b_{n-k} \\ x(n) = [1,2,3]; h(n) = [2,3,1]; \\ n=0;k=0,1,2 \\ y(0) = x(0)h(0-0) + x(1)h(0-1)+x(2)h(0-2) = 1*2 + 2*0 + 3*0 =2 \\ y(1) = x(0)h(1-0) + x(1)h(1-1) + x(2)h(1-2) = 1*3 + 2*2 + 3*0 = 7 \\ y(2) = x(0)h(2-0) + x(1)h(2-1) + x(2)h(2-2) =1*1 + 2*3 + 3*2=13 \\ y(3) = x(0)h(3-0) + x(1)h(3-1) + x(2)h(3-2) =1*0 + 2*1 + 3*3=11 \\ y(4) = x(0)h(4-0) + x(1)h(4-1) + x(2)h(4-2) =1*0 + 2*0 + 3*1=3 \\ y(n)=[2,7,13,11,3];

其中k等於a的長度。

翻轉移位相乘的操作如下:

y= x*h \\ y(0) \\ 0,0,1,2,3,0,0 \\ 1,3,2,0,0,0,0 \\ y(1) \\ 0,0,1,2,3,0,0 \\ 0,1,3,2,0,0,0 \\ y(2) \\ 0,0,1,2,3,0,0 \\ 0,0,1,3,2,0,0 \\ y(3) \\ 0,0,1,2,3,0,0 \\ 0,0,0,1,3,2,0 \\ y(4) \\ 0,0,1,2,3,0,0 \\ 0,0,0,0,1,3,2 \\

代碼實現:

Matlab代碼:

a=[1,2,3];
b=[2,3,1];
y=conv(b,a);

C++代碼:

這裏實現的主要問題有幾個:

1.k的取值範圍:和a的長度相關

2.b的下標,如果按照公式來看的話比較直接,但是按照翻轉移位來寫就會比較令人迷惑

3.卷積滿足交換律

void convolution(int a[],int b[],int NA,int NB)
{
	int NC=NA+NB-1;
	int *c=(int *)malloc(sizeof(int)*NC);
	memset(c,0,sizeof(int)*NC);
	for(int n=0;n<NC;n++)
	{
		for(int k=0;k<NA;k++)
		{
			int bindex=n-k;
			if(bindex>=0&&bindex<NB)
			{
				c[n]+=a[k]*b[bindex];
			}
		}
	}
	for(int n=0;n<NC;n++)
		printf("%d ",c[n]);
}

離散卷積與傅里葉變換的關係:

圖源自:快速傅里葉變換:算法與應用

使用matlab代碼驗證

clear;
a=[1,2,3];
b=[2,3,1];
c1=conv(a,b);
na=length(a);
nb=length(b);
for i=na+1:na+nb-1
    a(1,i)=0;
end
for i=nb+1:na+nb-1
    b(1,i)=0;
end
FA=fft(a);
FB=fft(b);
FC=FA.*FB;
c2=ifft(FC);

這個代碼裏的pad0的長度只需要大於等於na+nb-1即可,可以設置的更大。

c1: 2     7    13    11     3
c2: 2.0000    7.0000   13.0000   11.0000    3.0000

 

發佈了10 篇原創文章 · 獲贊 2 · 訪問量 2822
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章