2016-02-18 55 views
3

我试图用矩阵向量乘法来实现DCT在MATLAB。具体来说,我想创建系数的DCT矩阵,然后使用它与1D信号相乘来计算1D DCT。离散余弦变换1D Matlab的

这里是我的代码,以产生DCT矩阵:

x=[1 2 3 4 5 6 7 8]; 
y=dct1(8)*x'; 

它给出的答案是:

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]测试信号进行DCT后

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 

回答

3

在你的代码的错误是很轻微的,但根本的。在那里你计算的系数行:

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矩阵。顺便说一句,要检查的一种方式,如果你有正确的答案是使用dctmtx功能,其计算你正在寻找的N x N DCT系数矩阵。然而,这种功能是信号处理工具箱的一部分,所以如果你没有这样的,那么你可惜不能使用此功能,但如果我能提出一个备选答案,而不是使用for循环,我将建立一个2D网格的坐标与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)。此代码应产生与您更正的代码相同的结果。


在任何情况下,一旦我在纠正这些问题,我比较两者之间你的代码提供什么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矩阵

>> dct1d(8)*((1:8).') 

ans = 

    12.7279 
    -6.4423 
    -0.0000 
    -0.6735 
     0 
    -0.2009 
    -0.0000 
    -0.0507 

:,我们可以通过您所使用的 1:8的测试向量进行矩阵乘法检查实际DCT计算

1.这段代码实际上是在dctmtx的底下完成的,一旦你剥离了所有的错误检查和输入一致性检查。

+0

Thnx我忘了优先级 –

+0

@MarkBen你非常欢迎。祝你好运! – rayryeng

+0

@MarkBen我也为你创建了更高效的'dct1d'版本。我更喜欢用矢量化操作这样做,但无论你需要了解它是如何工作的! – rayryeng