欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

离散余弦变换(DCT)的C++实现

程序员文章站 2022-07-14 22:18:54
...

DCT变换具体概念性质参考博客https://blog.csdn.net/BigDream123/article/details/101426393

这里仅仅描述DCT-2变换的C++实现。

DCT-2正变换的公式如下:

离散余弦变换(DCT)的C++实现

DCT-2反变换公式如下:

 离散余弦变换(DCT)的C++实现

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;

#define NUM 8
#define PI 3.1415926

int around(double a)
{
    if(a >= 0)
    {
        return int(a+0.5);
    }
    else
    {
        return int(a-0.5);
    }

}
// DCT - Discrete Cosine Transform
void DCT(int data[NUM][NUM])
{
    int output[NUM][NUM];
    double alpha,beta;//C(k)  C(l)
    int m=0,n=0,k=0,l=0;
    for(k = 0;k < NUM;k++)
    {
        for(l = 0;l < NUM;l++)
        {
            if(k == 0)
            {
                alpha = sqrt(1.0/NUM);
            }
            else
            {
                alpha = sqrt(2.0/NUM);
            }
            if(l == 0)
            {
                beta = sqrt(1.0/NUM);
            }
            else
            {
                beta = sqrt(2.0/NUM);
            }
            double temp = 0.0;
            for(m = 0;m < NUM;m++)
            {
                for(n = 0;n < NUM;n++)
                {
                    temp += data[m][n] * cos((2*m+1)*k*PI/(2.0*NUM)) * cos((2*n+1)*l*PI/(2.0*NUM));
                }
            }
            output[k][l] = around(alpha * beta *temp);
        }
    }
    memset(data,0,sizeof(int)*NUM*NUM);
    memcpy(data,output,sizeof(int)*NUM*NUM);

}
//Inverse DCT
void IDCT(int data[NUM][NUM])
{
    int output[NUM][NUM];
    double alpha,beta;
    int m=0,n=0,k=0,l=0;
    for(m = 0;m < NUM;m++)
    {
        for(n = 0;n < NUM;n++)
        {
            double temp = 0.0;
            for(k = 0;k < NUM;k++)
            {
                for(l = 0;l < NUM;l++)
                {
                    if(k == 0)
                    {
                        alpha = sqrt(1.0/NUM);
                    }
                    else
                    {
                        alpha = sqrt(2.0/NUM);
                    }
                    if(l == 0)
                    {
                        beta = sqrt(1.0/NUM);
                    }
                    else
                    {
                        beta = sqrt(2.0/NUM);
                    }

                    temp += alpha * beta * data[k][l] * cos((2*m+1)*k*PI/(2*NUM)) * cos((2*n+1)*l*PI/(2*NUM));

                }
            }
            output[m][n] = around(temp);
        }
    }
    memset(data,0,sizeof(int)*NUM*NUM);
    memcpy(data,output,sizeof(int)*NUM*NUM);

}

int main()
{
    int input[NUM][NUM] =
         {

                   {89, 101, 114, 125, 126, 115, 105, 96},

                   {97, 115, 131, 147, 149, 135, 123, 113},

                   {114, 134, 159, 178, 175, 164, 149, 137},

                   {121, 143, 177, 196, 201, 189, 165, 150},

                   {119, 141, 175, 201, 207, 186, 162, 144},

                   {107, 130, 165, 189, 192, 171, 144, 125},

                   {97, 119, 149, 171, 172, 145, 117, 96},

                   {88, 107, 136, 156, 155, 129, 97, 75}

         };
    DCT(input);
    cout << "The result of DCT is:\n";
    for(int i = 0;i < NUM;i++)
    {
        for(int j = 0;j < NUM;j++)
        {
            cout << input[i][j] << '\t';
        }
        cout << endl;
    }
    IDCT(input);
    cout << "The result of IDCT is:\n";
    for(int i = 0;i < NUM;i++)
    {
        for(int j = 0;j < NUM;j++)
        {
            cout << input[i][j] << '\t';
        }
        cout << endl;
    }
    return 0;
}

由于DCT变换的可分离性,可以将二维DCT变换分解为两个一维DCT变换,如下

离散余弦变换(DCT)的C++实现

代码实现如下:

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;

#define NUM 8
#define PI 3.1415926

int around(double a)
{
    if(a >= 0)
    {
        return int(a+0.5);
    }
    else
    {
        return int(a-0.5);
    }

}
//两次一维DCT变换
void DCT_1D_1D(int data[NUM][NUM])
{
    int temp[NUM][NUM],output[NUM][NUM];
    double alpha,beta;
    int m=0,n=0,k=0,l=0;
    //一维DCT水平变换
    for(m = 0;m < NUM;m++)
    {
        for(l = 0;l < NUM;l++)
        {
            if(l == 0)
            {
                alpha = sqrt(1.0/NUM);
            }
            else
            {
                alpha = sqrt(2.0/NUM);
            }
            double tmp = 0.0;
            for(n = 0;n < NUM;n++)
            {
                tmp += data[m][n] * cos((2*n+1)*l*PI/(2*NUM));
            }
            temp[m][l] = around(alpha * tmp);
        }
    }
    //一维DCT垂直变换
    for(l = 0;l < NUM;l++)
    {
        for(k = 0;k < NUM;k++)
        {
            if(k == 0)
            {
                beta = sqrt(1.0/NUM);
            }
            else
            {
                beta = sqrt(2.0/NUM);
            }
            double tmp = 0;
            for(m = 0;m < NUM;m++)
            {
                tmp += temp[m][l] * cos((2*m+1)*k*PI/(2*NUM));
            }
            output[k][l] = around(beta * tmp);
        }
    }
    memset(data,0,sizeof(int)*NUM*NUM);
    memcpy(data,output,sizeof(int)*NUM*NUM);

}
//Inverse DCT
void IDCT(int data[NUM][NUM])
{
    int output[NUM][NUM];
    double alpha,beta;
    int m=0,n=0,k=0,l=0;
    for(m = 0;m < NUM;m++)
    {
        for(n = 0;n < NUM;n++)
        {
            double temp = 0.0;
            for(k = 0;k < NUM;k++)
            {
                for(l = 0;l < NUM;l++)
                {
                    if(k == 0)
                    {
                        alpha = sqrt(1.0/NUM);
                    }
                    else
                    {
                        alpha = sqrt(2.0/NUM);
                    }
                    if(l == 0)
                    {
                        beta = sqrt(1.0/NUM);
                    }
                    else
                    {
                        beta = sqrt(2.0/NUM);
                    }

                    temp += alpha * beta * data[k][l] * cos((2*m+1)*k*PI/(2*NUM)) * cos((2*n+1)*l*PI/(2*NUM));

                }
            }
            output[m][n] = around(temp);
        }
    }
    memset(data,0,sizeof(int)*NUM*NUM);
    memcpy(data,output,sizeof(int)*NUM*NUM);

}

int main()
{
    int input[NUM][NUM] =
         {

                   {89, 101, 114, 125, 126, 115, 105, 96},

                   {97, 115, 131, 147, 149, 135, 123, 113},

                   {114, 134, 159, 178, 175, 164, 149, 137},

                   {121, 143, 177, 196, 201, 189, 165, 150},

                   {119, 141, 175, 201, 207, 186, 162, 144},

                   {107, 130, 165, 189, 192, 171, 144, 125},

                   {97, 119, 149, 171, 172, 145, 117, 96},

                   {88, 107, 136, 156, 155, 129, 97, 75}

         };

    DCT_1D_1D(input);
    cout << "The result of 1D-DCT and 1D-DCT is:\n";
    for(int i = 0;i < NUM;i++)
    {
        for(int j = 0;j < NUM;j++)
        {
            cout << input[i][j] << '\t';
        }
        cout << endl;
    }
    IDCT(input);
    cout << "The result of IDCT is:\n";
    for(int i = 0;i < NUM;i++)
    {
        for(int j = 0;j < NUM;j++)
        {
            cout << input[i][j] << '\t';
        }
        cout << endl;
    }

    return 0;
}

 

相关标签: C++