2
votes

I'm trying to implement DCT (Discrete Cosine Transform) in Matlab but without using Fast Fourier Transform, just by using the next formula: enter image description here

I know this can be inefficient but this way I will get how it works.

First I divided my grayscale image in 8x8 blocks, then I apply the formula to each block.

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

My dctII function looks like this:

   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

I also created a summation function to keep things more readable (at least for me).

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

The problem is that the result of my algorithm differs by far the result of Matlab prebuilt function dct2. Maybe I didn't get DCT algorithm at all. Do you know what I'm doing wrong? I know all these nested loops kill performance serverely but I can't imagine how to solve this without using FFT.

Any help would be really appreciated, thanks.

1
At least you can put (2*b) to parenthesis in summation function. - Aki Suihkonen
You're right, thanks for noting that - Jorge Zapata

1 Answers

1
votes

Already solved!

My results differ from Matlab prebuilt function dct2 because that function doesn't consider an 8x8 block division like I do, so the matrices aren't equal.

I also made slight modifications to my code, I read that before working with pixels values you need to substract 128 to each value in order to work within the range [-128, 127]. This is my code:

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

Is not very efficient but it is an implementation of the formula. Hope that helps