离散余弦变换1D Matlab

时间:2016-02-18 14:41:50

标签: matlab signal-processing image-compression dct

我尝试使用矩阵向量乘法在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]

的测试信号执行DCT
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

1 个答案:

答案 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内部进行的操作,一旦您删除所有错误检查和输入一致性检查。