离散余弦变换DCT实现C.

我试图在C中实现正向和反向离散余弦变换(DCT)。代码是通过dct()函数将单个输入像素块转换为变换矩阵,然后通过idct返回到原始像素值( )function。 请参阅附带的代码。 我的输出formsidct是连续值244,116,244,116等。从idct值的外观,它看起来不像我的程序正在工作..有人可以帮助我,让我知道结果是什么每个function后应该期待什么? 显然,在idct之后,我应该得到prety接近原始输入矩阵。

谢谢

# include  # define PI 3.14 void dct(float [][]); // Function prototypes void idct(float [][]); // Function prototypes void dct(float inMatrix[8][8]){ double dct, Cu, sum, Cv; int i, j, u, h = 0, v; FILE * fp = fopen("mydata.csv", "w"); float dctMatrix[8][8], greyLevel; 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 { Cu = (1.0); } sum = 0.0; for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { // Level around 0 greyLevel = inMatrix[i][j]; dct = greyLevel * cos((2 * i + 1) * u * PI / 16.0) * cos((2 * j + 1) * v * PI / 16.0); sum += dct; } } dctMatrix[u][v] = 0.25 * Cu * Cv * sum; fprintf(fp, "\n %f", dctMatrix[u][v]); } fprintf(fp, "\n"); } idct(dctMatrix); } void idct(float dctMatrix[8][8]){ double idct, Cu, sum, Cv; int i, j, u, v; float idctMatrix[8][8], greyLevel; FILE * fp = fopen("mydata.csv", "a"); 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 { Cu = (1.0); } // Level around 0 greyLevel = dctMatrix[u][v]; idct = (greyLevel * cos((2 * i + 1) * u * PI / 16.0) * cos((2 * j + 1) * v * PI / 16.0)); sum += idct; } } idctMatrix[i][j] = 0.25 * Cu * Cv * sum; fprintf(fp, "\n %f", idctMatrix[i][j]); } fprintf(fp, "\n"); } } int main() { float testBlockA[8][8] = { {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} }, testBlockB[8][8] = {{255, 0, 255, 0, 255, 0, 255, 0}, {0, 255, 0, 255, 0, 255, 0, 255}, {255, 0, 255, 0, 255, 0, 255, 0}, {0, 255, 0, 255, 0, 255, 0, 255}, {255, 0, 255, 0, 255, 0, 255, 0}, {0, 255, 0, 255, 0, 255, 0, 255}, {255, 0, 255, 0, 255, 0, 255, 0}, {0, 255, 0, 255, 0, 255, 0, 255} }; dct(testBlockB); } 

if语句中的Cv常量赋值中至少有两个拼写错误:

  if (v == 0) { Cv = 1.0 / sqrt(2.0); } else { Cu = (1.0); // << this should be Cv = 1.0 } 

虽然没有检查得太正确。 使用关于余弦变换的德语维基百科 ,以下代码可以工作......我不想花时间搞清楚如何定义转换常量。 我想你需要确保使用正确的常量和反函数:

 #include  #include  #include  void dct(float **DCTMatrix, float **Matrix, int N, int M); void write_mat(FILE *fp, float **testRes, int N, int M); void idct(float **Matrix, float **DCTMatrix, int N, int M); float **calloc_mat(int dimX, int dimY); void free_mat(float **p); float **calloc_mat(int dimX, int dimY){ float **m = calloc(dimX, sizeof(float*)); float *p = calloc(dimX*dimY, sizeof(float)); int i; for(i=0; i  

编辑 dct基于wiki中公式DCT-II的交叉产品。 该idct基于式DCT-III的交叉产物,每个维度的归一化因子2 / N(因为这与文中提到的DCT-II相反)。 编辑我很确定你的版本中反向dct中的因子应该是sqrt(2)而不是1 / sqrt(2)。

你没有

 #include  

这可能意味着编译器假设数学函数不是真的,例如它们都返回int 。 请注意,您调用的所有函数都需要在某处声明,C不再具有“内置” sin() ,而不是内置的printf() (对于后者,您正确包含stdin.h ,课程)。

此外,一旦包含 ,就可以使用M_PI

除了之前关于Cv常量中的拼写错误(在dct()和idct()函数中)的答案之外,您还错误地使用了逆DCT公式(第2个) 。 每次循环时你都必须乘以Cv和Cu。 所以,idct()的正确代码应该是:

 void idct(float dctMatrix[8][8]){ double idct, Cu, sum, Cv; int i, j, u, v; float idctMatrix[8][8], greyLevel; FILE * fp = fopen("mydata.csv", "a"); 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); //mistake was here - the same is in dct() } greyLevel = dctMatrix[u][v]; // Multiply by Cv and Cu here! idct = (greyLevel * Cu * Cv * cos((2 * i + 1) * u * PI / 16.0) * cos((2 * j + 1) * v * PI / 16.0)); sum += idct; } } // not "* Cv * Cu" here! idctMatrix[i][j] = 0.25 * sum; fprintf(fp, "\n %f", idctMatrix[i][j]); } fprintf(fp, "\n"); } } 

在这种情况下,输出值接近255,0,255,0等。