我尝试使用矩阵向量乘法在MATLAB中实现DCT。具体来说,我想创建系数的DCT矩阵,然后用它乘以1D信号来计算1D DCT。
这是我制作DCT矩阵的代码:
function D=dct1d(n)
for u=0:n-1
if u==0
au=sqrt(1/n);
else
au=sqrt(2/n);
end
for x=0:n-1
D(u+1,x+1)=au*cos(((2*x+1)*u*pi)/2*n);
end
end
在此之后,我尝试使用x = [1 2 3 4 5 6 7 8]
:
x=[1 2 3 4 5 6 7 8];
y=dct1(8)*x';
它给出的答案是:
12.7279
18.0000
18.0000
18.0000
18.0000
18.0000
18.0000
18.0000
然而,正确的答案是:
12.7279
-6.4423
-0.0000
-0.6735
0
-0.2009
-0.0000
-0.0507
答案 0 :(得分:4)
您的代码中的错误非常轻微,但却很重要。您计算系数的行:
D(u+1,x+1)=au*cos(((2*x+1)*u*pi)/2*n);
看一下该行的最后部分:
D(u+1,x+1)=au*cos(((2*x+1)*u*pi)/2*n);
%// ^^^
Because multiplication and division are equal in precedence,这与执行完全相同:
D(u+1,x+1)=au*cos((((2*x+1)*u*pi)/2)*n);
因此,您没有除以2n
。你除以2然后乘以n
这是不正确的。您只需用括号括起2*n
操作:
D(u+1,x+1)=au*cos(((2*x+1)*u*pi)/(2*n));
一旦你这样做,我们得到正确的DCT矩阵。 BTW,检查你是否有正确答案的一种方法是使用dctmtx
函数,它计算你正在寻找的N x N
DCT系数矩阵。但是,这个函数是信号处理工具箱的一部分,所以如果你没有那个,那么你很遗憾不能使用这个函数,但如果我可以建议一个替代答案而不是使用for
循环,我会用meshgrid
构建一个坐标的2D网格,然后计算元素方面的产品。
这样的事情会起作用:
function D = dct1d(n)
[x,u] = meshgrid(0:n-1);
D = sqrt(2/n)*cos(((2*x+1).*u*pi)/(2*n));
D(1,:) = D(1,:) / sqrt(2);
end
我们可以使用if
然后除以sqrt(2/n)
来获取第一行,而不是使用sqrt(2)
语句来确定我们需要对每行应用哪些权重,这样您就可以了除以sqrt(1/n)
。此代码应生成与更正后的代码 1 相同的结果。
无论如何,一旦我做了这些更正,我就比较了你的代码给出的和dctmtx
给出的答案之间的两个答案:
>> dct1d(8)
ans =
0.3536 0.3536 0.3536 0.3536 0.3536 0.3536 0.3536 0.3536
0.4904 0.4157 0.2778 0.0975 -0.0975 -0.2778 -0.4157 -0.4904
0.4619 0.1913 -0.1913 -0.4619 -0.4619 -0.1913 0.1913 0.4619
0.4157 -0.0975 -0.4904 -0.2778 0.2778 0.4904 0.0975 -0.4157
0.3536 -0.3536 -0.3536 0.3536 0.3536 -0.3536 -0.3536 0.3536
0.2778 -0.4904 0.0975 0.4157 -0.4157 -0.0975 0.4904 -0.2778
0.1913 -0.4619 0.4619 -0.1913 -0.1913 0.4619 -0.4619 0.1913
0.0975 -0.2778 0.4157 -0.4904 0.4904 -0.4157 0.2778 -0.0975
>> dctmtx(8)
ans =
0.3536 0.3536 0.3536 0.3536 0.3536 0.3536 0.3536 0.3536
0.4904 0.4157 0.2778 0.0975 -0.0975 -0.2778 -0.4157 -0.4904
0.4619 0.1913 -0.1913 -0.4619 -0.4619 -0.1913 0.1913 0.4619
0.4157 -0.0975 -0.4904 -0.2778 0.2778 0.4904 0.0975 -0.4157
0.3536 -0.3536 -0.3536 0.3536 0.3536 -0.3536 -0.3536 0.3536
0.2778 -0.4904 0.0975 0.4157 -0.4157 -0.0975 0.4904 -0.2778
0.1913 -0.4619 0.4619 -0.1913 -0.1913 0.4619 -0.4619 0.1913
0.0975 -0.2778 0.4157 -0.4904 0.4904 -0.4157 0.2778 -0.0975
一旦我们得到校正的DCT矩阵,我们可以通过使用您使用的1:8
的测试向量执行矩阵乘法来检查实际的DCT计算:
>> dct1d(8)*((1:8).')
ans =
12.7279
-6.4423
-0.0000
-0.6735
0
-0.2009
-0.0000
-0.0507
1。这段代码实际上是在dctmtx
内部进行的操作,一旦您删除所有错误检查和输入一致性检查。