美文网首页
DCT变换(离散余弦变换)

DCT变换(离散余弦变换)

作者: 客昂康 | 来源:发表于2019-05-09 18:40 被阅读0次
  • 离散余弦变换原理
    一句话概括核心原理:频率不同的正弦波相乘,其黎曼积分总是为零。下图是网上找来的离散余弦变换公式:
  • C代码实现
    dct.h
//==============================================================================
//  Copyright (C) 2019 王小康. All rights reserved.
//
//  作者: 王小康
//  描述: 一维二维DCT变换
//  日期: 2019-05-09
//
//==============================================================================

#ifndef _DCT_H_
#define _DCT_H_

#define  DCT_LEN  8    //一维或二维矩阵边长

void dct_init       (void);
void dct_1Ddct      (float *out, float *in);
void dct_1Didct     (float *out, float *in);
void dct_1Dspectrum (float *out, float *in);
void dct_2Ddct      (float out[][DCT_LEN], float in[][DCT_LEN]);
void dct_2Didct     (float out[][DCT_LEN], float in[][DCT_LEN]);

#endif

dct.c

//==============================================================================
//  Copyright (C) 2019 王小康. All rights reserved.
//
//  作者: 王小康
//  描述: 一维二维DCT变换
//  日期: 2019-05-09
//
//==============================================================================

#include <math.h>
#include "dct.h"

static float  dctTableA[DCT_LEN][DCT_LEN];
static float  sqrt_1_N;
static float  sqrt_2_N;

////////////////////////////////////////////////////////////////////////////////

// 离散余弦变换初始化,生成变换核。一维二维同核。
void dct_init(void){
    sqrt_1_N = sqrt(1.0/DCT_LEN);
    sqrt_2_N = sqrt(2.0/DCT_LEN);
    int i, j;
    for(i=0; i<DCT_LEN; i++){
        dctTableA[0][i] = sqrt_1_N;
    }
    for(i=1; i<DCT_LEN; i++){
        for(j=0; j<DCT_LEN; j++){
            dctTableA[i][j] = sqrt_2_N * cos((3.14159265359*i*(2*j+1))/(2*DCT_LEN));
        }
    }
}

// 一维离散余弦变换
void dct_1Ddct(float *out, float *in){
    unsigned i, j;
    for(i=0; i<DCT_LEN; i++){
        out[i] = 0;
        for(j=0; j<DCT_LEN; j++) out[i] += dctTableA[i][j] * in[j];
    }
}

// 一维离散余弦变换,返回频谱图
void dct_1Dspectrum(float *out, float *in){
    unsigned i, j;
    out[0] = 0;
    for(i=0; i<DCT_LEN; i++) out[0] += in[i];
    out[0] /= DCT_LEN;
    if(out[0] < 0) out[0] = -out[0];
    for(i=1; i<DCT_LEN; i++){
        out[i] = 0;
        for(j=0; j<DCT_LEN; j++) out[i] += dctTableA[i][j] * in[j];
        out[i] *= sqrt_2_N;
        if(out[i] < 0) out[i] = -out[i];
    }
}

// 一维离散余弦逆变换
void dct_1Didct(float *out, float *in){
    unsigned i, j;
    for(i=0; i<DCT_LEN; i++){
        out[i] = 0;
        for(j=0; j<DCT_LEN; j++) out[i] += dctTableA[j][i] * in[j];
    }
}

// 二维离散余弦变换
void dct_2Ddct(float out[][DCT_LEN], float in[][DCT_LEN]){
    float tmp[DCT_LEN][DCT_LEN];
    float sum;
    int i, j, k;
    for(i=0; i<DCT_LEN; i++){
        for(j=0; j<DCT_LEN; j++){
            sum = 0;
            for(k=0; k<DCT_LEN; k++) sum += dctTableA[i][k] * in[k][j];
            tmp[i][j] = sum;
        }
    }
    for(i=0; i<DCT_LEN; i++){
        for(j=0; j<DCT_LEN; j++){
            sum = 0;
            for(k=0; k<DCT_LEN; k++) sum += dctTableA[j][k] * tmp[i][k];
            out[i][j] = sum;
        }
    }
}

// 二维离散余弦逆变换
void dct_2Didct(float out[][DCT_LEN], float in[][DCT_LEN]){
    float tmp[DCT_LEN][DCT_LEN];
    float sum;
    int i, j, k;
    for(i=0; i<DCT_LEN; i++){
        for(j=0; j<DCT_LEN; j++){
            sum = 0;
            for(k=0; k<DCT_LEN; k++) sum += dctTableA[k][i] * in[k][j];
            tmp[i][j] = sum;
        }
    }
    for(i=0; i<DCT_LEN; i++){
        for(j=0; j<DCT_LEN; j++){
            sum = 0;
            for(k=0; k<DCT_LEN; k++) sum += dctTableA[k][j] * tmp[i][k];
            out[i][j] = sum;
        }
    }
}

  • 测试代码
//==============================================================================
//
//  作者: 王小康
//  描述: 一维二维DCT变换测试程序
//  日期: 2019-05-09
//
//==============================================================================

#include <stdio.h>
#include <stdlib.h>
#include "dct.h"

static void show1D(float *x){
    int i;
    for(i=0; i<DCT_LEN; i++){
        printf("%15f", x[i]);
    }
    putchar('\n');
}

static void show2D(float x[][DCT_LEN]){
    int i, j;
    for(i=0; i<DCT_LEN; i++){
        for(j=0; j<DCT_LEN; j++){
            printf("%15f", x[i][j]);
        }
        putchar('\n');
    }
    putchar('\n');
}

int main(int argc, char *argv[]){
    
    float data1[DCT_LEN][DCT_LEN] = {
        { 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}
        
        // {200, 200, 200, 200, 200, 200, 200, 200},
        // {240, 220, 190,  20,  20,  60,  30, 160},
        // {200, 160, 180,  40,  40,  50,  50, 120},
        // {220, 120, 190,  60,  60,  80,  70, 100},
        // {190, 100, 100,  80,  80,  90,  99, 111},
        // {100, 150, 120, 100,  70, 100, 120, 130},
        // {111, 111, 121, 123, 110, 111, 134, 167},
        // {120, 220, 222, 222, 210, 109, 190, 100}
    };
    float data2[DCT_LEN][DCT_LEN];
    float data3[DCT_LEN][DCT_LEN];
    
    dct_init();
    
    printf("一维原始数据    :");
    show1D((float*)data1);
    dct_1Dspectrum((float*)data2, (float*)data1);
    printf("一维原始数据频谱:");
    show1D((float*)data2);
    dct_1Ddct((float*)data2, (float*)data1);
    printf("一维DCT变换后   :");
    show1D((float*)data2);
    dct_1Didct((float*)data3, (float*)data2);
    printf("一维DCT逆变换后 :");
    show1D((float*)data3);
    putchar('\n');
    
    printf("二维原始数据:\n");
    show2D(data1);
    putchar('\n');
    
    dct_2Ddct(data2, data1);
    printf("二维DCT变换后:\n");
    show2D(data2);
    putchar('\n');
    
    dct_2Didct(data3, data2);
    printf("二维DCT逆变换后:\n");
    show2D(data3);
    putchar('\n');
    
    return 0;
}

  • 运行效果

相关文章

  • DCT变换(离散余弦变换)

    离散余弦变换原理一句话概括核心原理:频率不同的正弦波相乘,其黎曼积分总是为零。下图是网上找来的离散余弦变换公式: ...

  • DCT离散余弦变换

    原文网址:http://blog.csdn.net/newchenxf/article/details/51719...

  • 离散余弦变换(DCT)

    DCT变换的全称是离散余弦变换(Discrete Cosine Transform),主要运用于数据或图像的压缩。...

  • 关于离散余弦变换(DCT)

    1.转自:离散余弦变换(DCT)的定义_小火车_新浪博客 已知离散傅里叶变换(DFT)为: 由于许多要处理的信号都...

  • pyspark DCT(离散余弦变换)

    DCT:将时域的N维实数序列转换成频域的N维实数序列常用于信号处理和图像处理,对信号和图像(包括静止图像和运动图像...

  • H264系列七 JPEG DCT JPEG2000 DWT

    参考概述·离散余弦变换(DCT)及其实现过程基于DCT变换的JPEG图像压缩原理能不能通俗的讲解下傅立叶分析和小波...

  • 音视频理论:离散余弦变换-DCT

    离散余弦变换在压缩的时候中的应用 多媒体数据的显著特点就是数据量非常大,解决方案就是进行数据压缩,压缩后进行存储和...

  • 均值哈希算法和感知哈希算法

    1.离散余弦变换 离散余弦变换由于为数据与余弦函数乘积累计,将无规律数列改为规则排列,如图像数据原数据为无规则二维...

  • H264视频压缩

    关键点: 1.划分宏块 2.对所有图片进行分组 3.帧内预测压缩 4.帧间预测压缩 5.DCT 数据离散余弦变换 ...

  • 黑箱理论和等价信息的运用

    今天吴军老师着重讲解了等价信息的概念、原理和应用方法,并讲解了傅立叶变换和离散余弦变换的原理,最后举出核磁...

网友评论

      本文标题:DCT变换(离散余弦变换)

      本文链接:https://www.haomeiwen.com/subject/lcrwoqtx.html