没有FFT的DCT 2D

时间:2012-11-01 05:13:58

标签: matlab fft dct

我正在尝试在Matlab中实现DCT(离散余弦变换)但不使用快速傅里叶变换,只需使用下一个公式: enter image description here

我知道这可能效率低下,但这样我就会知道它是如何工作的。

首先,我将灰度图像分成8x8块,然后将公式应用于每个块。

for i=1:8:h
    for j=1:8:w
        dctMatrix(i:(i-1)+block,j:(j-1)+block) = dctII(img(i:(i-1)+block,j:(j-1)+block), block);
    end
end

我的 dctII 功能如下所示:

   function [newB] = dctII(segmento, b)
    [h w] = size(segmento);
    segmento = double(segmento);
    newB = zeros(b,b);
    for u=0:h-1
        for v=0:w-1
            if u == 0
                Cu = 1/sqrt(2);
            else
                Cu = 1;
            end
            if v == 0
                Cv = 1/sqrt(2);
            else
                Cv = 1;
            end
            sumRes = summation(segmento,u,v,b);
            dct = (1/4)*Cu*Cv*sumRes;
            segmento(u+1,v+1) = dct;
        end
    end
    newB = segmento;
end

我还创建了一个求和函数,以使事物更具可读性(至少对我而言)。

function [sum] = summation(segmento,u,v,b)
    [h w] = size(segmento);
    sum = 0;
    for x=0:h-1
        for y=0:w-1
            sum = sum + (double(segmento(x+1,y+1))*cos((((2*x)+1)*u*pi)/(2*b))*cos((((2*y)+1)*v*pi)/(2*b)));
        end
    end
end

问题是我的算法的结果到目前为止是Matlab预建函数 dct2 的结果。也许我根本没有得到DCT算法。你知道我做错了什么吗?我知道所有这些嵌套循环都会严重破坏性能,但我无法想象如何在不使用FFT的情况下解决这个问题。

非常感谢任何帮助,谢谢。

1 个答案:

答案 0 :(得分:0)

已经解决了!

我的结果与Matlab预建函数dct2不同,因为该函数不像我那样考虑8x8块除法,因此矩阵不相等。

我也对我的代码做了一些修改,我读过在处理像素值之前你需要将128减去每个值才能在[-128,127]范围内工作。这是我的代码:

function [newB] = dctII(segmento, b)
    [h w] = size(segmento);
    segmento = double(segmento) - 128;
    newB = zeros(b,b);
    for u=0:h-1
        for v=0:w-1
            if u == 0
                Cu = 1/sqrt(2);
            else
                Cu = 1;
            end
            if v == 0
                Cv = 1/sqrt(2);
            else
                Cv = 1;
            end
            sumRes = summation(segmento,u,v,b);
            dct = (1/4)*Cu*Cv*sumRes;
            newB(u+1,v+1) = dct;
        end
    end
end

function [sum] = summation(segmento,u,v,b)
    [h w] = size(segmento);
    sum = 0;
    for x=0:h-1
        for y=0:w-1
            sum = sum + (double(segmento(x+1,y+1))*cos(((2*x)+1)*u*pi/(2*b))*cos(((2*y)+1)*v*pi/(2*b)));
        end
    end
end

效率不高,但它是公式的实现。希望有所帮助