你的代码中出现了一个非常微小但基本的错误。在计算系数的那一行:
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);
由于乘法和除法具有相同的优先级,因此这与执行以下操作完全相同:
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矩阵。顺便说一句,检查是否有正确答案的一种方法是使用
dctmtx
函数,该函数计算您正在寻找的
N x N
DCT系数矩阵。但是,该函数是信号处理工具箱的一部分,因此如果您没有该工具箱,则不幸地无法使用该函数,但是如果我可以建议一种替代答案而不使用
for
循环,我会使用
meshgrid
构建一个二维坐标网格,然后计算逐元素乘积。类似以下内容即可:
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
在幕后所执行的操作。
dct1d
版本。我更喜欢使用向量化操作来完成它,但无论如何,你需要理解它是如何工作的! - rayryeng