当前位置 博文首页 > XSES_yasuoman的博客:基于cv2、numpy→python实现二维DCT、IDCT

    XSES_yasuoman的博客:基于cv2、numpy→python实现二维DCT、IDCT

    作者:[db:作者] 时间:2021-08-31 22:26

    基于cv2、numpy→python实现二维DCT、IDCT变换

    原理见博客

    以下实现python程序

    导入所需库

    # 江南大学物联18级——MH
    import numpy as np
    import cv2
    import math
    

    输入矩阵,arr存储8×8源图像数据,arr_brightness为亮度量化表数据

    arr = np.array(([142, 144, 151, 156, 156, 157, 156, 156],
                    [140, 143, 148, 150, 154, 155, 156, 155],
                    [148, 150, 156, 160, 158, 158, 156, 158],
                    [159, 160, 162, 161, 160, 159, 158, 160],
                    [158, 162, 161, 164, 162, 160, 160, 162],
                    [160, 164, 143, 162, 160, 158, 157, 159],
                    [162, 163, 148, 160, 158, 156, 154, 156],
                    [163, 160, 150, 154, 154, 154, 153, 155]), dtype=int)
    
    # arr_brightness的dtype为float,
    # 经过dct变换后的矩阵元素类型为float32,保证两者计算时元素类型相同。
    arr_brightness = np.array(([16,  11,  10,  16,  24,  40,  51,  61],
                               [12,  12,  14,  19,  26,  58,  60,  55],
                               [14,  13,  16,  24,  40,  57,  69,  56],
                               [14,  17,  22,  29,  51,  87,  80,  62],
                               [18,  22,  37,  56,  68, 109, 103,  77],
                               [24,  35,  55,  64,  81, 104, 113,  92],
                               [49,  64,  78,  87, 103, 121, 120, 101],
                               [72,  92,  95,  98, 112, 100, 103,  99]), dtype=np.float32)
    

    电平偏移+数据类型转换

    # 电平偏移——对arr所有维度的所有元素进行 - 128 操作,用arr_level_shift存储
    arr_level_shift = arr[:, :] - 128
    print("电平偏移后的arr矩阵为:\n", arr_level_shift)
    
    # python的opencv库中dct函数要求传入矩阵元素类型为float
    # 将矩阵元素类型由int转float,任选下面一种即可
    arr_level_shift = np.array(arr_level_shift, dtype=np.float32)
    # arr_level_shift = arr_level_shift.astype('float32')
    

    DCT变换

    # 进行dct变换,变换后的矩阵为arr_dct
    arr_dct = cv2.dct(arr_level_shift)
    # 规范输出格式,小数点后保留3位,不采用科学计数法
    np.set_printoptions(precision=3, suppress=True)
    print("DCT系数矩阵为:\n", arr_dct)
    

    量化系数矩阵

    # 计算量化系数矩阵,使用numpy的floor向下取整,结果用arr_QMatrix_ckl存储
    arr_QMatrix_ckl = np.floor(np.array(arr_dct / arr_brightness + 0.50, dtype=np.float32))
    print("量化系数矩阵为:\n", np.array(arr_QMatrix_ckl, dtype=np.int32))
    

    反量化

    # 反量化,用arr_inverse存储,类型需为float32,方便后续进行IDCT变换
    arr_inverse = np.array(arr_QMatrix_ckl * arr_brightness, dtype=np.float32)
    print("反量化系数矩阵为:\n", np.array(arr_inverse, dtype=np.int32))
    

    IDCT+电平偏移

    # IDCT、进行电平移位恢复,两步并一步,结果使用around函数四舍五入,用arr_idct_shift存储
    arr_idct_shift = np.around(np.array(cv2.idct(arr_inverse) + 128, dtype=np.float32), decimals=0)
    print("重建图像数据为:\n", np.array(arr_idct_shift, dtype=np.int32))
    

    计算NMSE

    # 计算NMSE,分解,为了美观,先计算分母Denominator,再计算分子molecular
    width, height = arr.shape
    denominator, molecular = float(0), float(0)
    for x_index in range(0, width):
        for y_index in range(0, height):
            denominator += math.pow(arr[x_index][y_index] - arr_idct_shift[x_index][y_index], 2)
            molecular += math.pow(arr[x_index][y_index], 2)
    NMSE = denominator / molecular
    print("归一化均方误差为:\n", NMSE)
    

    输出结果

    电平偏移后的arr矩阵为:
     [[14 16 23 28 28 29 28 28]
     [12 15 20 22 26 27 28 27]
     [20 22 28 32 30 30 28 30]
     [31 32 34 33 32 31 30 32]
     [30 34 33 36 34 32 32 34]
     [32 36 15 34 32 30 29 31]
     [34 35 20 32 30 28 26 28]
     [35 32 22 26 26 26 25 27]]
    DCT系数矩阵为:
     [[225.25   -9.176  -4.527   1.973   6.25   -2.73   -5.702  -7.06 ]
     [-14.777 -19.457 -12.65   -7.98   -5.402   3.874   7.517   6.577]
     [-20.79   -4.29    1.539   3.994   0.399   0.733   0.198   0.089]
     [  2.533  -3.084  -0.873   2.499   2.389  -1.418  -5.467  -4.111]
     [  8.      4.096   0.472  -3.646  -2.5     1.384   4.405   3.693]
     [  5.129   4.442  -0.827   0.181   1.622   0.284   0.079  -1.554]
     [  0.764  -0.636  -0.552   1.019   2.27    0.221  -1.289  -2.757]
     [  3.579  -0.325  -3.827  -3.405  -0.332   1.19    1.995   0.673]]
    量化系数矩阵为:
     [[14 -1  0  0  0  0  0  0]
     [-1 -2 -1  0  0  0  0  0]
     [-1  0  0  0  0  0  0  0]
     [ 0  0  0  0  0  0  0  0]
     [ 0  0  0  0  0  0  0  0]
     [ 0  0  0  0  0  0  0  0]
     [ 0  0  0  0  0  0  0  0]
     [ 0  0  0  0  0  0  0  0]]
    反量化系数矩阵为:
     [[224 -11   0   0   0   0   0   0]
     [-12 -24 -14   0   0   0   0   0]
     [-14   0   0   0   0   0   0   0]
     [  0   0   0   0   0   0   0   0]
     [  0   0   0   0   0   0   0   0]
     [  0   0   0   0   0   0   0   0]
     [  0   0   0   0   0   0   0   0]
     [  0   0   0   0   0   0   0   0]]
    重建图像数据为:
     [[141 144 149 153 156 157 157 156]
     [144 146 151 155 157 158 158 157]
     [149 151 154 157 159 159 159 159]
     [154 155 156 158 159 160 160 160]
     [159 158 158 158 158 159 160 160]
     [161 160 158 157 156 157 158 159]
     [162 160 157 155 154 154 155 157]
     [163 160 157 153 152 152 154 155]]
    归一化均方误差为:
     0.0005068397771952818
    
    cs