Search code examples
javaimage-processingdct

2d DCT program not working


I have to do this 2d DCT of an image for my project. I translated the formula right to code. It all seems fine logically but it doesn't give the required result. I've tallied it with matlab function to check the results for a 3x3 matrix but they are incorrect.

Also, what and how I've coded gives a huge number of loops such that an actual image operation takes hours to compute.

Any suggestion to reduce the loops and pointing of program error would be great. Thanks.

This is my code.

    double alpha_p, alpha_q;
    double pi = Math.atan(1.0) * 4.0;
    //dct begins
    System.out.println("it begins");
    for (int p = 0; p < M; p++) {
        for (int q = 0; q < N; q++) {
            if (p == 0)
                alpha_p = 1 / sqrt(M);
            else
                alpha_p = sqrt(2 / M);
            if (q == 0)
                alpha_q = 1 / sqrt(N);
            else
                alpha_q = sqrt(2 / N);
            double toreturn = 0;
            for (int m = 0; m < M; m++) {
                for (int n = 0; n < N; n++) {
                    toreturn = toreturn + img[m][n]
                            * cos(((2 * m + 1) * p * pi) / 2 * M)
                            * cos(((2 * n + 1) * q * pi) / 2 * N);
                }
            }
            dctimg[p][q] = alpha_p * alpha_q * toreturn;
            System.out.println("euta");
        }
    }
    // dct over
    System.out.println("its over");

    //inverse dct begins
    for (int m = 0; m < M; m++) {
        for (int n = 0; n < N; n++) {
            double toreturn = 0;
            for (int p = 0; p < M; p++) {
                for (int q = 0; q < N; q++) {
                    if (p == 0)
                        alpha_p = 1 / sqrt(M);
                    else
                        alpha_p = sqrt(2 / M);
                    if (q == 0)
                        alpha_q = 1 / sqrt(N);
                    else
                        alpha_q = sqrt(2 / N);
                    toreturn = toreturn + alpha_p * alpha_q * dctimg[p][q]
                                          * cos(((2 * m + 1) * p * pi) / 2 * M)
                                          * cos(((2 * n + 1) * q * pi) / 2 * N);
                }
            }
            finalimg[m][n] = toreturn;
        }
    }
    //inverse dct over

Solution

  • First of all, in the formula of DCT the denominator of cos is 2 * M. It is a typical mistake. 4 / 2 * 2 = 4 not 1

    cos(((2 * m + 1) * p * pi) / 2 * M) should be cos(((2 * m + 1) * p * pi) / (2 * M))

    Parentheses are required in all four cases.


    Another moment that I want to mention is sqrt(2 / M). If M has an integer type (it is not clear by your code) and it is greater than 2, then the expression 2 / M is equal to 0. Because both operands have integer types and / gives only integer part. To fix it, add a floating point like that sqrt(2.0 / M).


    As you have already noticed, there is a lot of loops, in other words, the complexity of the 2D DCT II is O(n^4).

    In real life nobody applies DCT to the whole actual image. The image is split into blocks of size 8x8 and each block is processed by DCT. This approach allows to keep n low and the complexity becomes acceptable.

    To decrease the algorithmic complexity, I want to link here, where methods of using 1D DCT and FFT are good explained.