gpt4 book ai didi

c - 离散余弦变换DCT实现C

转载 作者:太空狗 更新时间:2023-10-29 17:10:14 24 4
gpt4 key购买 nike

我试图在 C 中实现正向和反向离散余弦变换 (DCT)。代码是通过 dct() 函数将单个输入像素 block 转换为转换矩阵,然后通过 dct() 函数返回原始像素值idct() 函数。请参阅随附的代码。我的 idct 输出是 244、116、244、116 等的连续值。从 idct 值的外观来看,我的程序似乎没有运行。有人可以帮我看看我的结果是什么吗应该期待每个功能后?显然在 idct 之后,我应该非常接近原始输入矩阵。

谢谢

 # include <stdio.h>
# 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
}

虽然没有检查得太正确。使用 german wikipedia关于余弦变换,以下代码有效...我不想花时间弄清楚你是如何定义转换常量的。我想您需要确保使用正确的常量和反函数:

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

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 <dimX;i++){
m[i] = &p[i*dimY];

}
return m;
}

void free_mat(float **m){
free(m[0]);
free(m);
}

void write_mat(FILE *fp, float **m, int N, int M){

int i, j;
for(i =0; i< N; i++){
fprintf(fp, "%f", m[i][0]);
for(j = 1; j < M; j++){
fprintf(fp, "\t%f", m[i][j]);
}
fprintf(fp, "\n");
}
fprintf(fp, "\n");
}

void dct(float **DCTMatrix, float **Matrix, int N, int M){

int i, j, u, v;
for (u = 0; u < N; ++u) {
for (v = 0; v < M; ++v) {
DCTMatrix[u][v] = 0;
for (i = 0; i < N; i++) {
for (j = 0; j < M; j++) {
DCTMatrix[u][v] += Matrix[i][j] * cos(M_PI/((float)N)*(i+1./2.)*u)*cos(M_PI/((float)M)*(j+1./2.)*v);
}
}
}
}
}

void idct(float **Matrix, float **DCTMatrix, int N, int M){
int i, j, u, v;

for (u = 0; u < N; ++u) {
for (v = 0; v < M; ++v) {
Matrix[u][v] = 1/4.*DCTMatrix[0][0];
for(i = 1; i < N; i++){
Matrix[u][v] += 1/2.*DCTMatrix[i][0];
}
for(j = 1; j < M; j++){
Matrix[u][v] += 1/2.*DCTMatrix[0][j];
}

for (i = 1; i < N; i++) {
for (j = 1; j < M; j++) {
Matrix[u][v] += DCTMatrix[i][j] * cos(M_PI/((float)N)*(u+1./2.)*i)*cos(M_PI/((float)M)*(v+1./2.)*j);
}
}
Matrix[u][v] *= 2./((float)N)*2./((float)M);
}
}
}



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} };

FILE * fp = fopen("mydata.csv", "w");
int dimX = 8, dimY = 8;
int i, j;

float **testBlock = calloc_mat(dimX, dimY);
float **testDCT = calloc_mat(dimX, dimY);
float **testiDCT = calloc_mat(dimX, dimY);

for(i = 0; i<dimX; i++){
for(j = 0; j<dimY; j++){
testBlock[i][j] = testBlockB[i][j];
}
}

dct(testDCT, testBlock, dimX, dimY);
write_mat(fp, testDCT, dimX, dimY);

idct(testiDCT, testDCT, dimX, dimY);
write_mat(fp, testiDCT, dimX, dimY);

fclose(fp);
free_mat(testBlock);
free_mat(testDCT);
free_mat(testiDCT);

return 0;
}

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

关于c - 离散余弦变换DCT实现C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8310749/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com