zoukankan      html  css  js  c++  java
  • DCT(离散余弦变换)算法原理和源码

      原理:

      离散余弦变换(DCT for Discrete Cosine Transform)是与傅里叶变换相关的一种变换,它类似于离散傅里叶变换(DFT for Discrete Fourier Transform),但是只使用实数。离散余弦变换相当于一个长度大概是它两倍的离散傅里叶变换,这个离散傅里叶变换是对一个实偶函数进行的(因为一个实偶函数的傅里叶变换仍然是一个实偶函数),在有些变形里面需要将输入或者输出的位置移动半个单位(DCT有8种标准类型,其中4种是常见的)。

      使用场景:

      离散余弦变换,尤其是它的第二种类型,经常被信号处理和图像处理使用,用于对信号和图像(包括静止图像和运动图像)进行有损数据压缩。一个类似的变换, 改进的离散余弦变换被用在高级音频编码(AAC for Advanced Audio Coding),Vorbis 和 MP3 音频压缩当中。

      python源码实现:  

    # import numpy
    import numpy as np
     
    # import dct
    from scipy.fftpack import dct
     
    # numpy array
    x = np.array([1.0, 2.0, 1.0, 2.0, -1.0])
    print("x      : ",x)
     
    # apply dct function on array
    y = dct(x)
    print("dct(x) : ",y)

      C源码实现:

    #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, "	%f", m[i][j]);
            }
            fprintf(fp, "
    ");
        }
        fprintf(fp, "
    ");
    }
    
    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;
    }

      代码路径: https://github.com/DyLanCao/DCT.git

    参考文档:

    https://stackoverflow.com/questions/8310749/discrete-cosine-transform-dct-implementation-c

  • 相关阅读:
    leetcode 190 Reverse Bits
    vs2010 单文档MFC 通过加载位图文件作为客户区背景
    leetcode 198 House Robber
    记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
    逆序数2 HDOJ 1394 Minimum Inversion Number
    矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
    递推DP URAL 1586 Threeprime Numbers
    递推DP URAL 1167 Bicolored Horses
    递推DP URAL 1017 Staircases
    01背包 URAL 1073 Square Country
  • 原文地址:https://www.cnblogs.com/dylancao/p/10018530.html
Copyright © 2011-2022 走看看