找回密码
 立即注册
首页 业界区 安全 论DCT和IDCT的重要性,汇编SIMD版第一,此贴第二,就是 ...

论DCT和IDCT的重要性,汇编SIMD版第一,此贴第二,就是这么狂 :-)

雨角 昨天 19:35
输入: [1.000 2.000 3.000]
输出: [ 3.464 -1.414  0.000]
重建: [1.000 2.000 3.000]
[0] cos(0.0*π/3)*sqrt(1/N)*1.0 + cos(0.0*π/3)*sqrt(1/N)*2.0 + cos(0.0*π/3)*sqrt(1/N)*3.0 = 3.464
[1] cos(0.5*π/3)*sqrt(2/N)*1.0 + cos(1.5*π/3)*sqrt(2/N)*2.0 + cos(2.5*π/3)*sqrt(2/N)*3.0 = -1.414
[2] cos(1.0*π/3)*sqrt(2/N)*1.0 + cos(3.0*π/3)*sqrt(2/N)*2.0 + cos(5.0*π/3)*sqrt(2/N)*3.0 = 0.000
恭喜,你(基本)明白DCT了!可M为啥是正交矩阵?!
[0,0] cos(0.0*π/3)*sqrt(1/N)*cos(0.0*π/3)*sqrt(1/N) + cos(0.0*π/3)*sqrt(1/N)*cos(0.0*π/3)*sqrt(1/N) + cos(0.0*π/3)*sqrt(1/N)*cos(0.0*π/3)*sqrt(1/N)
[0,1] cos(0.0*π/3)*sqrt(1/N)*cos(0.5*π/3)*sqrt(2/N) + cos(0.0*π/3)*sqrt(1/N)*cos(1.5*π/3)*sqrt(2/N) + cos(0.0*π/3)*sqrt(1/N)*cos(2.5*π/3)*sqrt(2/N)
[0,2] cos(0.0*π/3)*sqrt(1/N)*cos(1.0*π/3)*sqrt(2/N) + cos(0.0*π/3)*sqrt(1/N)*cos(3.0*π/3)*sqrt(2/N) + cos(0.0*π/3)*sqrt(1/N)*cos(5.0*π/3)*sqrt(2/N)
[1,0] cos(0.5*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N) + cos(1.5*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N) + cos(2.5*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N)
[1,1] cos(0.5*π/3)*sqrt(2/N)*cos(0.5*π/3)*sqrt(2/N) + cos(1.5*π/3)*sqrt(2/N)*cos(1.5*π/3)*sqrt(2/N) + cos(2.5*π/3)*sqrt(2/N)*cos(2.5*π/3)*sqrt(2/N)
[1,2] cos(0.5*π/3)*sqrt(2/N)*cos(1.0*π/3)*sqrt(2/N) + cos(1.5*π/3)*sqrt(2/N)*cos(3.0*π/3)*sqrt(2/N) + cos(2.5*π/3)*sqrt(2/N)*cos(5.0*π/3)*sqrt(2/N)
[2,0] cos(1.0*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N) + cos(3.0*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N) + cos(5.0*π/3)*sqrt(2/N)*cos(0.0*π/3)*sqrt(1/N)
[2,1] cos(1.0*π/3)*sqrt(2/N)*cos(0.5*π/3)*sqrt(2/N) + cos(3.0*π/3)*sqrt(2/N)*cos(1.5*π/3)*sqrt(2/N) + cos(5.0*π/3)*sqrt(2/N)*cos(2.5*π/3)*sqrt(2/N)
[2,2] cos(1.0*π/3)*sqrt(2/N)*cos(1.0*π/3)*sqrt(2/N) + cos(3.0*π/3)*sqrt(2/N)*cos(3.0*π/3)*sqrt(2/N) + cos(5.0*π/3)*sqrt(2/N)*cos(5.0*π/3)*sqrt(2/N)
如果用上复数(欧拉公式),就可以用等比数列求和公式了!!
  1. from math import cos, sqrt, pi
  2. import numpy as np
  3. π = pi; N = 3
  4. m = None # DCT矩阵
  5. mt = None # IDCT矩阵,m的转置
  6. mc = None # "C"版本DCT矩阵
  7. ms = None # string版DCT矩阵
  8. ne = lambda a, b: not np.allclose(a, b, atol=1E-6)
  9. def generate_dct_matrices():
  10.   global m; global mt; global mc; global ms
  11.   m = np.zeros((N, N))
  12.   # [[0]*3]*3不对。[0]*3得[0,0,0],再*3复制引用‌而非创建独立副本。修改任意一行会影响所有行;debug 1小时
  13.   mc = [[0] * N for _ in range(N)]
  14.   ms = [[0] * N for _ in range(N)]
  15.   for k in range(N):
  16.     for n in range(N):
  17.       mc[k][n] = m[k,n] = cos((n + 0.5) * k * pi / N)
  18.       ms[k][n] = f'cos({(n+0.5)*k}*π/{N})'
  19.   m[0,:] *= sqrt(1/N)
  20.   for n in range(N):
  21.     mc[0][n] *= sqrt(1/N)
  22.     ms[0][n] += f'*sqrt(1/N)'
  23.   m[1:,:] *= sqrt(2/N)
  24.   for k in range(1,N):
  25.     for n in range(N):
  26.       mc[k][n] *= sqrt(2/N)
  27.       ms[k][n] += f'*sqrt(2/N)'
  28.   mt = m.T
  29.   if ne(m, mc): raise ValueError()
  30. # x是一维数组,shape=(3,),np将其视为‌列向量‌(3,1)
  31. # 3x3 x 3x1 = 3x1 再摆平
  32. dct  = lambda x: np.dot(m,  x)
  33. idct = lambda y: np.dot(mt, y)
  34. # So, dct和idct其实是一个函数
  35. np.set_printoptions(
  36.   suppress=True,  # 禁用科学计数法
  37.   precision=3,    # 保留3位小数
  38.   floatmode='fixed'  # 固定小数位数
  39. )
  40. generate_dct_matrices()
  41. x = np.array([1.0, 2.0, 3.0]); print("输入:", x)
  42. y = dct(x); print("输出:", y)
  43. r = idct(y); print("重建:", r)
  44. ee = np.eye(m.shape[0])
  45. if ne(np.matmul(m, mt), ee): raise ValueError()
  46. print()
  47. y2 = [0] * N
  48. for i in range(N):
  49.   for j in range(N): y2[i] += mc[i][j] * x[j]
  50. if ne(y, y2): raise ValueError()
  51. y2 = [0] * N
  52. for i in range(N):
  53.   s = ''
  54.   for j in range(N): s += f'{ms[i][j]}*{x[j]} + '
  55.   s = s[:-3]
  56.   y2[i] = eval(s)
  57.   print(f'{[i]} {s} = {y2[i]:.3f}')
  58. if ne(y, y2): raise ValueError()
  59. print('')
  60. print('恭喜,你(基本)明白DCT了!可M为啥是正交矩阵?!')
  61. a = ms; b = np.array(ms).T; e = [[0] * N for _ in range(N)]
  62. for i in range(N):
  63.   for j in range(N):
  64.     s = ''
  65.     for k in range(N): s += f'{a[i][k]}*{b[k][j]} + '
  66.     s = s[:-3]
  67.     print(f'[{i},{j}] {s}')
  68.     e[i][j] = eval(s)
  69. if ne(e, ee): raise ValueError()
  70. print()
  71. print('如果用上复数(欧拉公式),就可以用等比数列求和公式了!!')
复制代码
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册