Trying to implement The inverse of a dct 8*8 matri

2019-08-30 06:08发布

问题:

I have managed to calculate the dct of an 8*8 matrix and I am having trouble doing the inverse. Can anyone have a look at this code and tell me what I am doing now. I should be getting the exact same values as before but im getting different values. I am reading in the input from a csv file and out putting it to anther csv file. Its programmed in c

void idct_func(float inMatrix[8][8]){

double idct,
Cu,
sum,
Cv;

int i,
j,
u,
v;


float idctMatrix[8][8],
greyLevel;

FILE * fp = fopen("mydata.csv", "r");
FILE * wp = fopen("idct.csv", "w");
fprintf(fp, "\n Inverse DCT");                     

for (i = 0; i < 8; ++i) {
    for (j = 0; j < 8; ++j) { 
        sum = 0.0;  
        for (u = 0; u < 8; u++) {
            for (v = 0; v < 8; v++) {
            if (u == 0)
                Cu = 1.0 / sqrt(2.0);
            else
                Cu = 1.0;
            if (v == 0)
                Cv = 1.0 / sqrt(2.0);
            else
                Cv = (1.0);
            // Level around 0
            greyLevel = idctMatrix[u][v];
            idct = (greyLevel * cos((2 * i + 1) * u * M_PI / 16.0) *
                    cos((2 * j + 1) * v * M_PI / 16.0));
            sum += idct;
            }               
        }

        idctMatrix[i][j] = 0.25 * Cu * Cv * sum;
        fprintf(wp, "\n %f", idctMatrix[i][j]);         
    }
    fprintf(wp, "\n");
}

the original matrix is:

{255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255}};

the dct is :

2040   0  -0   0   0   0  -0  -0
   0   0   0   0  -0   0  -0   0
  -0   0  -0   0   0   0   0   0
   0  -0  -0  -0   0  -0  -0   0
   0   0  -0   0  -0  -0  -0   0
   0  -0  -0  -0  -0   0  -0  -0
  -0  -0  -0   0   0   0   0  -0
  -0   0   0   0  -0   0  -0   0

the idct calculated should be the same as the original

回答1:

You're trying to calculate the IDCT in-place, using idctMatrix[][] as both input and output and hence the input is being modified in the process. That's wrong. You need to have a separate 2-dimensional array for input (or output).

It also appears that the u- and v-dependent scaling factors Cu and Cv are applied outside of the u- and v- loops. That would be wrong too.

EDIT: Here's the code if you can't understand the words:

#include <stdio.h>
#include <math.h>

#ifndef M_PI
#define M_PI 3.14159265358979324
#endif

void Compute8x8Dct(const double in[8][8], double out[8][8])
{
  int i, j, u, v;
  double s;

  for (i = 0; i < 8; i++)
    for (j = 0; j < 8; j++)
    {
      s = 0;

      for (u = 0; u < 8; u++)
        for (v = 0; v < 8; v++)
          s += in[u][v] * cos((2 * u + 1) * i * M_PI / 16) *
                          cos((2 * v + 1) * j * M_PI / 16) *
               ((i == 0) ? 1 / sqrt(2) : 1) *
               ((j == 0) ? 1 / sqrt(2) : 1);

      out[i][j] = s / 4;
    }
}

void Compute8x8Idct(const double in[8][8], double out[8][8])
{
  int i, j, u, v;
  double s;

  for (i = 0; i < 8; i++)
    for (j = 0; j < 8; j++)
    {
      s = 0;

      for (u = 0; u < 8; u++)
        for (v = 0; v < 8; v++)
          s += in[u][v] * cos((2 * i + 1) * u * M_PI / 16) *
                          cos((2 * j + 1) * v * M_PI / 16) *
               ((u == 0) ? 1 / sqrt(2) : 1.) *
               ((v == 0) ? 1 / sqrt(2) : 1.);

      out[i][j] = s / 4;
    }
}

void Print8x8(const char* title, const double in[8][8])
{
  int i, j;

  printf("%s\n", title);

  for (i = 0; i < 8; i++)
  {
    for (j = 0; j < 8; j++)
      printf("%8.3f ", in[i][j]);
    printf("\n");
  }
}

int main(void)
{
  double pic1[8][8], dct[8][8], pic2[8][8];
  int i, j;

  for (i = 0; i < 8; i++)
    for (j = 0; j < 8; j++)
#if 01
      pic1[i][j] = 255;
#else
      pic1[i][j] = (i ^ j) & 1;
#endif
  Print8x8("pic1:", pic1);
  Compute8x8Dct(pic1, dct);
  Print8x8("dct:", dct);
  Compute8x8Idct(dct, pic2);
  Print8x8("pic2:", pic2);

  return 0;
}

Here's its output:

pic1:
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
dct:
2040.000    0.000    0.000    0.000    0.000    0.000    0.000    0.000 
   0.000    0.000    0.000    0.000    0.000    0.000    0.000    0.000 
   0.000    0.000    0.000    0.000    0.000    0.000    0.000    0.000 
   0.000    0.000    0.000    0.000    0.000    0.000    0.000    0.000 
   0.000    0.000    0.000    0.000    0.000    0.000    0.000    0.000 
   0.000    0.000    0.000    0.000    0.000    0.000    0.000    0.000 
   0.000    0.000    0.000    0.000    0.000    0.000    0.000    0.000 
   0.000    0.000    0.000    0.000    0.000    0.000    0.000    0.000 
pic2:
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000 
 255.000  255.000  255.000  255.000  255.000  255.000  255.000  255.000