• 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

  • 相关阅读:
    TVM性能评估分析(三)
    TVM性能评估分析(二)
    TVM性能评估分析(一)
    飞腾上实体名单?
    华为不造车,广汽合作智能驾驶
    异构计算编程
    服务器硬件层次架构
    为何说要多用组合少用继承?如何决定该用组合还是继承?
    极客时间学习
    如果学不好编程,就看看这个吧
  • 原文地址:https://www.cnblogs.com/dylancao/p/10018530.html
Copyright © 2020-2023  润新知