当前位置 博文首页 > XSES_yasuoman的博客:基于cv2、numpy→python实现二维DCT、IDCT
原理见博客
以下实现python程序
# 江南大学物联18级——MH
import numpy as np
import cv2
import math
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变换,变换后的矩阵为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、进行电平移位恢复,两步并一步,结果使用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,分解,为了美观,先计算分母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